按thrift语法格式编写一个文件,这个文件定义了RPC的接口和数据类型
Hello.thrift
namespace java service.demo service Hello{ string helloString(1:string para) i32 helloInt(1:i32 para) bool helloBoolean(1:bool para) void helloVoid() string helloNull() }
其中定义了服务叫 Hello, 有五个方法,每个方法包含一个方法名,参数列表和返回类型。每个参数包括参数序号,参数类型以及参数名。 Thrift 是对 IDL(Interface Definition Language) 描述性语言的一种具体实现。因此,以上的服务描述文件使用 IDL 语法编写。使用 Thrift 工具编译 Hello.thrift,就会生成相应的 Hello.java 文件。该文件包含了在 Hello.thrift 文件中描述的服务 Hello 的接口定义,即 Hello.Iface 接口(server端需要实现的接口),以及服务调用的底层通信细节,包括客户端的调用逻辑 Hello.Client (client端需要实现的接口)以及服务器端的处理逻辑 Hello.Processor,用于构建客户端和服务器端的功能。
thrift -r –gen java Hello.thrift
这时候会生成一个Hello.java的源文件。这个文件就包含了rpc框架的实现(server端,client端都需要用到这个文件)
将上一步生成的Hello.java拷贝到当前项目中
创建 HelloServiceImpl.java 文件并实现 Hello.java 文件中的 Hello.Iface 接口
HelloServiceImpl.java
package service.demo; import org.apache.thrift.TException; public class HelloServiceImpl implements Hello.Iface { @Override public boolean helloBoolean(boolean para) throws TException { return para; } @Override public int helloInt(int para) throws TException { try { Thread.sleep(20000); } catch (InterruptedException e) { e.printStackTrace(); } return para; } @Override public String helloNull() throws TException { return null; } @Override public String helloString(String para) throws TException { System.out.println("recv: "+ para); return "return: "+ para; } @Override public void helloVoid() throws TException { System.out.println("Hello World"); } }
创建服务器端实现代码,将 HelloServiceImpl 作为具体的处理器传递给 Thrift 服务器
HelloServiceServer.java
package service.server; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TBinaryProtocol.Factory; import org.apache.thrift.server.TServer; import org.apache.thrift.server.TThreadPoolServer; import org.apache.thrift.transport.TServerSocket; import org.apache.thrift.transport.TTransportException; import service.demo.Hello; import service.demo.HelloServiceImpl; public class HelloServiceServer { /** * 启动 Thrift 服务器 * @param args */ public static void main(String[] args) { try { // 设置服务端口为 7911 TServerSocket serverTransport = new TServerSocket(7911); // 设置协议工厂为 TBinaryProtocol.Factory Factory proFactory = new TBinaryProtocol.Factory(); // 关联处理器与 Hello 服务的实现 TProcessor processor = new Hello.Processor(new HelloServiceImpl()); //TServer server = new TThreadPoolServer(processor, serverTransport, proFactory); TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(serverTransport).processor(processor)); System.out.println("Start server on port 7911..."); server.serve(); } catch (TTransportException e) { e.printStackTrace(); } } }
maven配置
<dependencies> <dependency> <groupId>org.apache.thrift</groupId> <artifactId>libthrift</artifactId> <version>0.9.2</version> </dependency> # 官方只给了上面一个配置,结果运行错误,网上搜的答复是再添加下面这个配置(错误解决) <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.6</version> <scope>compile</scope> <optional>true</optional> </dependency>
将上一步生成的Hello.java拷贝到当前项目中
创建客户端实现代码,调用 Hello.client 访问服务端的逻辑实现
HelloServiceClient.java
package service.client; import org.apache.thrift.TException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; import service.demo.Hello; public class HelloServiceClient { /** * 调用 Hello 服务 * @param args */ public static void main(String[] args) { try { // 设置调用的服务地址为本地,端口为 7911 TTransport transport = new TSocket("localhost", 7911); transport.open(); // 设置传输协议为 TBinaryProtocol TProtocol protocol = new TBinaryProtocol(transport); Hello.Client client = new Hello.Client(protocol); // 调用服务的 helloVoid 方法 System.out.println(client.helloVoid()); transport.close(); } catch (TTransportException e) { e.printStackTrace(); } catch (TException e) { e.printStackTrace(); } } }
初始化环境
# 安装thrift依赖的库 sudo easy_install pip sudo pip install thrift
修改Hello.thrift文件 (将javas 改成 py)
namespace py service.demo service Hello{ string helloString(1:string para) i32 helloInt(1:i32 para) bool helloBoolean(1:bool para) void helloVoid() string helloNull() }
生成python的rpc框架
thrift -r –gen py Hello.thrift
命令执行之后会生成Hello.py和一些其他文件。 我在当前目录下新建一个fang.py,代码如下
我为了方便测试,直接在当前目录下创建了fang.py。如果Python项目放在其他路径,一定要保证Hello.py及其依赖的文件都能被import进来
import sys from Hello import Client from thrift import Thrift from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol from thrift.protocol import TCompactProtocol def run(): try: transport = TSocket.TSocket('master', 7911) transport = TTransport.TBufferedTransport(transport) protocol = TBinaryProtocol.TBinaryProtocol(transport) # 一定要保证和服务器端的协议相同 #protocol = TCompactProtocol.TCompactProtocol(transport) client = Client(protocol) transport.open() print client.helloString("python") transport.close() except Thrift.TException, tx: print '%s' % (tx.message) if __name__ == '__main__': run()
client端发送的协议一定要和server端接收的协议相同