简介

Thrift是由Facebook为“大规模跨语言服务开发”而开发的一种接口描述语言和二进制通讯协议,它被用来定义和创建跨语言的服务。目前被作为一个RPC框架使用。

下载

使用之前需要先下载Thrift的源代码和Thrift编译器。

下载源代码后解压,进入到thrift-0.12.0\lib\csharp\src目录下,打开Thrift.sln,根据需要编译相应的库,这里选择Thrift.45,即.NET 4.5可以使用的库,编译生成Thrift45.dll

创建项目

新建解决方案,包含3个项目

  • ThriftSample

    类库,Thrift生成的服务接口

  • server

    控制台程序,服务端

  • client

    控制台程序,客户端

这3个项目都需要引用刚刚编译的Thrift45.dll,为什么不用Nuget来安装Thrift呢?因为我注意到Nuget上的Thrift已经好几年没更新了,还是手动编译最新的要好。

然后,serverclient同时引用项目ThriftSample

定义服务接口

在解决方案目录下新建一个文件Sample.thrift来定义服务接口,Thrift语法可以在网上找到

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
namespace csharp kira.Interface

service SampleService {
    ServiceVersion GetVersion()
    list<string> SayHello(1: string name)
}

struct ServiceVersion {
    1: required string name;
    2: required string version;
}

这里指定了生成类的命名空间,以及定义了一个结构体作为返回值

生成服务接口

这里就需要用到之前下载的Thrift编译器,可以直接在Thrift官网找到。将下载的thrift-0.12.0.exe也拷贝到解决方案目录下(和Sample.thrift相同目录),打开命令窗口,执行以下命令

1
$ thrift-0.12.0.exe -gen csharp Sample.thrift

不得不说,Thrift的命令行语法真的比gRPC简洁多了。

执行完没有错误的话,就可以看到目录下又多出了一个gen-csharp的文件夹,里面有对应命名空间的文件夹,最后找到生成的.cs文件。将文件全部拷贝到ThriftSample项目目录下,并将它们添加到项目,编译生成库。

服务端程序

server项目下新建类MySampleService并实现接口SampleService.Iface,重写其中的两个服务接口函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
namespace server
{
    using System.Collections.Generic;
    using kira.Interface;

    public class MySampleService : SampleService.Iface
    {
        public ServiceVersion GetVersion()
        {
            return new ServiceVersion()
            {
                Name = "My Sample Service",
                Version = "0.0.1.20"
            };
        }

        public List<string> SayHello(string name)
        {
            return new List<string>()
            {
                $"你好 {name}",
                $"Hello {name}",
                $"Hola {name}",
                $"Bonjour {name}",
                $"こんにちは {name}",
                $"hallo {name}"
            };
        }
    }
}

编写服务启动程序

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
namespace server
{
    using Thrift.Server;
    using Thrift.Transport;
    using kira.Interface;

    class Program
    {
        static void Main(string[] args)
        {
            MySampleService service = new MySampleService();

            SampleService.Processor processor = new SampleService.Processor(service);

            TServerTransport serverTransport = new TServerSocket(10240);
            TServer server = new TThreadPoolServer(processor, serverTransport);
            System.Console.WriteLine("server listening at tcp://localhost:10240/");
            server.Serve();
        }
    }
}

客户端程序

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
namespace client
{
    using Thrift.Protocol;
    using Thrift.Transport;
    using kira.Interface;

    class Program
    {
        static void Main(string[] args)
        {
            TTransport transport = new TSocket("localhost", 10240);
            transport.Open();

            TProtocol protocol = new TBinaryProtocol(transport);
            SampleService.Client cli = new SampleService.Client(protocol);

            ServiceVersion ver = cli.GetVersion();
            System.Console.WriteLine("Remote Service Version: {0} - v{1}", ver.Name, ver.Version);

            var hellos = cli.SayHello("Thrift");

            foreach (string item in hellos)
            {
                System.Console.WriteLine(item);
            }

            System.Console.ReadKey();
            transport.Close();
        }
    }
}

运行测试

老样子,先启动服务端程序,然后运行客户端程序,可以看到客户端输出

Remote Service Version: My Sample Service - v0.0.1.20
你好 Thrift
Hello Thrift
Hola Thrift
Bonjour Thrift
こんにちは Thrift
hallo Thrift

总结

对比Thrift和gRPC两个主流的RPC框架,个人感觉Thrift使用起来要更加灵活一些,当然这只是初步接触,较深层次的内容还没有去研究,实际项目的应用感觉两个都可以,有对比说Thrift框架的性能要优于gRPC,但对于小的项目来说已经完全够用了。