=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=