Thrift框架學習


參考文章:1、http://www.kankanews.com/ICkengine/archives/54084.shtml

2、http://www.cnblogs.com/liping13599168/archive/2011/09/15/2176836.html

Golang內置了對RPC支持,但只能適用於go語言程序之間調用。Thrift是一種可伸縮的跨語言服務框架,它支持C++,C#,Java,Python,Go等多種語言。

thrift允許你定義一個簡單的定義文件中的數據類型和服務接口,以作為輸入文件,編譯器生成代碼用來方便地生成RPC客戶端和服務器通信的無縫跨編程語言。 

這種方式與微軟的WCF框架以及Android中的AIDL服務的做法很類似。

1、安裝Go語言的thrift包

參考文章1給出的地址是:go get git.apache.org/thrift.git/lib/go/thrift,但該地址現在似乎不能訪問了,請使用下面的命令:

go get github.com/apache/thrift/lib/go/thrift

2、下載腳本編譯器

下載地址:http://www.apache.org/dyn/closer.cgi?path=/thrift/0.9.1/thrift-0.9.1.exe

該編譯工具可將thrift腳本文件編譯為目標變成語言代碼。

3、創建腳本

腳本文件采用thrift自帶教程github.com\apache\thrift\tutorial中的shared.thrift和tutorial.thrift:

shared.thrift文件如下:

namespace go shared

struct SharedStruct {
1: i32 key
2: string value
}

service SharedService {
SharedStruct getStruct(1: i32 key)
}

tutorial.thrift文件如下:

include "shared.thrift"

namespace go tutorial

typedef i32 MyInteger

const i32 INT32CONSTANT = 9853
const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'}

enum Operation {
ADD = 1,
SUBTRACT = 2,
MULTIPLY = 3,
DIVIDE = 4
}

struct Work {
1: i32 num1 = 0,
2: i32 num2,
3: Operation op,
4: optional string comment,
}

exception InvalidOperation {
1: i32 what,
2: string why
}

service Calculator extends shared.SharedService {

void ping(),

i32 add(1:i32 num1, 2:i32 num2),

i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),

oneway void zip()

}

4、編譯腳本

分別執行 thrift -gen go x:\shared.thrift和thrift -gen go x:\tutorial.thrift  命令,參數go表示生成go代碼,可以根據實際情況使用csharp,java,python等參數。

5、示例代碼

下面我們使用C#語言實現的客戶端與Go語言實現的服務端通信,進行跨語言調用。

將第4步中生成的go代碼放到服務端目錄下,服務端代碼如下:

main.go文件

package main

import (
"crypto/tls"
"fmt"
"github.com/apache/thrift/lib/go/thrift"
"tutorial"
)

func main() {
protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
transportFactory := thrift.NewTTransportFactory()
addr := "localhost:9090"
secure := false

if err := runServer(transportFactory, protocolFactory, addr, secure); err != nil {
fmt.Println("error running server:", err)
}
}

func runServer(transportFactory thrift.TTransportFactory, protocolFactory thrift.TProtocolFactory, addr string, secure bool) error {
var transport thrift.TServerTransport
var err error
if secure {
cfg := new(tls.Config)
if cert, err := tls.LoadX509KeyPair("server.crt", "server.key"); err == nil {
cfg.Certificates = append(cfg.Certificates, cert)
} else {
return err
}
transport, err = thrift.NewTSSLServerSocket(addr, cfg)
} else {
transport, err = thrift.NewTServerSocket(addr)
}

if err != nil {
return err
}
fmt.Printf("%T\n", transport)
handler := NewCalculatorHandler()
processor := tutorial.NewCalculatorProcessor(handler)
server := thrift.NewTSimpleServer4(processor, transport, transportFactory, protocolFactory)

fmt.Println("Starting the simple server... on ", addr)
return server.Serve()
}

handler.go文件使用原文件。

將第4步生成的c#代碼加入客戶端工程,並引用thrift.dll(該組件的代碼可在..\github.com\apache\thrift\tutorial\csharp下找到),如圖所示:

客戶端測試代碼如下:

class Program
    {
        static void Main(string[] args)
        {
            try
            {
                TTransport transport = new TSocket("localhost", 9090);
                TProtocol protocol = new TBinaryProtocol(transport);
                Calculator.Client client = new Calculator.Client(protocol);

                transport.Open();
                try
                {
                    client.ping();
                    Console.WriteLine("ping()");

                    int sum = client.add(1, 1);
                    Console.WriteLine("1+1={0}", sum);

                    Work work = new Work();

                    work.Op = Operation.DIVIDE;
                    work.Num1 = 1;
                    work.Num2 = 0;
                    try
                    {
                        int quotient = client.calculate(1, work);
                        Console.WriteLine("Whoa we can divide by 0");
                    }
                    catch (InvalidOperation io)
                    {
                        Console.WriteLine("Invalid operation: " + io.Why);
                    }

                    work.Op = Operation.SUBTRACT;
                    work.Num1 = 15;
                    work.Num2 = 10;
                    try
                    {
                        int diff = client.calculate(1, work);
                        Console.WriteLine("15-10={0}", diff);
                    }
                    catch (InvalidOperation io)
                    {
                        Console.WriteLine("Invalid operation: " + io.Why);
                    }

                    SharedStruct log = client.getStruct(1);
                    Console.WriteLine("Check log: {0}", log.Value);

                }
                finally
                {
                    transport.Close();
                }
            }
            catch (TApplicationException x)
            {
                Console.WriteLine(x.StackTrace);
            }
            Console.ReadKey();
        }
    }

測試結果:

本文結束。源碼下載:thriftserver  thriftclient


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM