=Start=
缘由:
之前在学习Apache Thrift的过程中记录了一篇文章,但没有包含代码演示,这次加上参考文章中验证过可用的Java代码,同时补上其它语言(这里是Python)的client端调用代码。
正文:
参考解答:
1. 先创建 Thrift(IDL) 文件,同时生成代码
namespace java com.ixyzero.learn.thrift //这一行里面的java关键字必不可少,否则生成Java代码的时候可能会报错 service HelloWorldService { string sayHello(1:string username) }
我遇到过的一些报错信息:
(last token was 'service') syntax error Parser error during include pass.
&
#生成Java版本,会在当前目录下生成 gen-java 子目录 thrift -r --gen java helloWorld.thrift #生成Python版本,会在当前目录下生成 gen-py 子目录 thrift -r --gen py helloWorld.thrift
2. 实现接口 Iface
package com.ixyzero.learn.thrift; import org.apache.thrift.TException; /** * Created by ixyzero.com on 2018/5/30. */ public class HelloWorldImpl implements HelloWorldService.Iface { public HelloWorldImpl() { } @Override public String sayHello(String username) throws TException { long time1 = System.currentTimeMillis(); System.out.println(time1); try { Thread.sleep(1000L * 1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(System.currentTimeMillis()); System.out.println(System.currentTimeMillis() - time1); return "Hi, '" + username + "' welcome to thrift world"; } }
3. 编写 Server端 代码
# Java 版本
package com.ixyzero.learn.thrift; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.server.TServer; import org.apache.thrift.server.TSimpleServer; import org.apache.thrift.transport.TServerSocket; public class HelloServerDemo { public static final int SERVER_PORT = 8090; public void startServer() { try { System.out.println("HelloWorld TSimpleServer start ...."); TProcessor tprocessor = new HelloWorldService.Processor<HelloWorldService.Iface>(new HelloWorldImpl()); // 简单的单线程服务模型,一般用于测试 TServerSocket serverTransport = new TServerSocket(SERVER_PORT); TServer.Args tArgs = new TServer.Args(serverTransport); tArgs.processor(tprocessor); tArgs.protocolFactory(new TBinaryProtocol.Factory()); // tArgs.protocolFactory(new TCompactProtocol.Factory()); // tArgs.protocolFactory(new TJSONProtocol.Factory()); TServer server = new TSimpleServer(tArgs); server.serve(); } catch (Exception e) { System.out.println("Server start error!!!"); e.printStackTrace(); } } public static void main(String[] args) { HelloServerDemo server = new HelloServerDemo(); server.startServer(); } }
# Python版本
#!/usr/bin/env python # coding=utf-8 import socket import sys from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol from thrift.server import TServer from helloWorld import HelloWorldService from helloWorld.ttypes import * class HelloWorldServiceHandler: def sayHello(self, msg): ret = "Received: " + msg print ret return ret handler = HelloWorldServiceHandler() processor = HelloWorldService.Processor(handler) transport = TSocket.TServerSocket("localhost", 9090) tfactory = TTransport.TBufferedTransportFactory() pfactory = TBinaryProtocol.TBinaryProtocolFactory() server = TServer.TSimpleServer(processor, transport, tfactory, pfactory) print "Starting thrift server in python..." server.serve() print "done!"
4. 编写 Client端 代码
# Java版本
package com.ixyzero.learn.thrift; 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; public class HelloClientDemo { public static final String SERVER_IP = "localhost"; public static final int SERVER_PORT = 8090; public static final int TIMEOUT = 30000; /** * @param userName */ public void startClient(String userName) { TTransport transport = null; try { transport = new TSocket(SERVER_IP, SERVER_PORT, TIMEOUT); // 协议要和服务端一致 TProtocol protocol = new TBinaryProtocol(transport); // TProtocol protocol = new TCompactProtocol(transport); // TProtocol protocol = new TJSONProtocol(transport); HelloWorldService.Client client = new HelloWorldService.Client(protocol); transport.open(); long time1 = System.currentTimeMillis(); String result = client.sayHello(userName); long time2 = System.currentTimeMillis(); System.out.print("spend "); System.out.print(time2 - time1); System.out.println(" ms to call method client.sayHello()"); System.out.println("Thrift client result =: " + result); } catch (TTransportException e) { e.printStackTrace(); } catch (TException e) { e.printStackTrace(); } finally { if (null != transport) { transport.close(); } } } public static void main(String[] args) { HelloClientDemo client = new HelloClientDemo(); client.startClient("china"); } }
# Python版本
#!/usr/bin/env python # coding=utf-8 import sys from thrift import Thrift from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol from helloWorld import HelloWorldService try: socket = TSocket.TSocket('localhost', 8090) # 8090调用的Java,9090调用的Python socket.setTimeout(2000) # transport = TTransport.TFramedTransport(socket) #用这个会出现time out异常 transport = TTransport.TBufferedTransport(socket) #用这个就没问题,因为和Server端一致 protocol = TBinaryProtocol.TBinaryProtocol(transport) client = HelloWorldService.Client(protocol) transport.open() msg = client.sayHello("hello") print msg msg = client.sayHello("nihao") print msg transport.close() except: print "{0}".format(traceback.format_exc())
Server端 和 Client端 的 transport 要一致,protocol 也要一致,否则会出现一些问题,比如 time out 。
参考链接:
- PHP and python thrift
- Thrift RPC 使用指南实战(附golang & PHP代码)
- Golang、Php、Python、Java基于Thrift0.9.1实现跨语言调用
- Python Thrift示例# 先写 IDL 文件,再用Python分别实现 Server端 和 Client端
- https://thrift.apache.org/docs/concepts
- Python thrift使用示例
- Apache Thrift学习之一(入门及Java实例演示)
=END=