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.comapache hrift utorial中的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: utorial.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 ", 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.comapache hrift utorialcsharp下找到),如图所示:

客户端测试代码如下:

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

原文地址:https://www.cnblogs.com/wenjingu/p/3522026.html