java 语言 实现thrift_Apache Thrift 支持异构语言之间的调用

前言

之前介绍了Apache Thrift的快速入门,我们使用java作为客户端,使用java作为服务器端Apache Thrift及其入门,我们知道RPC框架的一个基本特征就是支持异构语言之间的调用,本篇博客介绍异构语言之间的调用。

Apache Thrift allows you to define data types and service interfaces in a simple definition file. Taking that file as input, the compiler generates code to be used to easily build RPC clients and servers that communicate seamlessly across programming languages. Instead of writing a load of boilerplate code to serialize and transport your objects and invoke remote methods, you can get right down to business.

Apache Thrift可以在文件中定义数据类型和服务接口。编译器根据idl(接口定义文件)文件可以生成消息传输类型的Message对象,也生成RPC语言网络传输的代码,使得我们可以跨语言跨平台的调用服务。

Python作为Client,Java作为Server

idl文件(接口描述文件),定义了结构体(struct),异常(exception)和服务(service):

namespace java thrift.generated

namespace py py.thrift.generated

typedef i16 short

typedef i32 int

typedef i64 long

typedef bool boolean

typedef string String

struct Person{

1: optional String username,

2: optional int age,

3: optional boolean married

}

exception DataException{

1: optional String message,

2: optional String callStack,

3: optional String date

}

service PersonService{

Person getPersonByUsername(1: required String username) throws (1: DataException dateException),

void savePerson(1: required Person person) throws (1: DataException dataException)

}

使用thrift编译器生成编译文件

thrift --gen java src/thrift/data.thrift

thrift --gen py src/thrift/data.thrift

ccc608f569dd

java生成的代码

ccc608f569dd

python生成的代码

加入Thrift依赖,pom文件:

org.apache.thrift

libthrift

0.10.0

python依赖要自己编译一下官方的包下载地址,到解压后的lib目录下进入py目录下进行编译得到Apache Thrift 项目中所使用的python库(lib目录下有Apache Thrift 支持的各种语言的库):

➜ py cd /Users/naeshihiroshi/study/studySummarize/netty/thrift-0.10.0/lib/py

➜ py ll

ccc608f569dd

安装python相应的包

➜ py sudo python setup.py install

生成的依赖位于/Library/Python/2.7/site-packages/

➜ py cd /Library/Python/2.7/site-packages/

➜ site-packages ll

total 480

-rwxr-xr-x 1 root wheel 157B 7 31 2016 Extras.pth

-rw-r--r-- 1 root wheel 119B 7 31 2016 README

-rw-r--r-- 1 root wheel 263B 6 17 19:31 easy-install.pth

drwxr-xr-x 6 root wheel 204B 6 17 19:31 six-1.10.0-py2.7.egg

-rw-r--r-- 1 root wheel 235K 6 17 19:31 thrift-0.10.0-py2.7-macosx-10.12-intel.egg

Python作为Client,Java作为Server

Java Server

编写java服务器端实现代码(一般服务器端要编写一个业务代码实现供客户端调用,还有一个服务代码):

public class PersonServiceImpl implements PersonService.Iface{

@Override

public Person getPersonByUsername(String username) throws DataException, TException {

System.out.println("Got client Param:" + username);

Person person = new Person();

person.setUsername(username);

person.setAge(32);

person.setMarried(true);

return person;

}

@Override

public void savePerson(Person person) throws DataException, TException {

System.out.println("Got Client Param: ");

System.out.println(person.getUsername());

System.out.println(person.getAge());

System.out.println(person.isMarried());

}

}

服务端:

public class ThriftServer {

public static void main(String[] args) throws Exception{

TNonblockingServerSocket socket = new TNonblockingServerSocket(8899);

THsHaServer.Args arg = new THsHaServer.Args(socket).minWorkerThreads(2).maxWorkerThreads(4);

PersonService.Processor processor = new PersonService.Processor<>(new PersonServiceImpl());

//表示协议层次(压缩协议)

arg.protocolFactory(new TCompactProtocol.Factory());

//表示传输层次

arg.transportFactory(new TFramedTransport.Factory());

arg.processorFactory(new TProcessorFactory(processor));

//半同步半异步的server

TServer server = new THsHaServer(arg);

System.out.println("Thrift Server started!");

server.serve();

}

}

python的客户端:

将上面自动生成的代码拷贝到python项目中,

ccc608f569dd

python生成的代码

py_client.py代码:

# _*_ coding:utf-8 _*_

__author__ = '作者'

# 导入thrift的包

from py.thrift.generated import PersonService

from py.thrift.generated import ttypes

from thrift import Thrift

from thrift.transport import TSocket

from thrift.transport import TTransport

from thrift.protocol import TCompactProtocol

import sys

# 解决中文编码问题

reload(sys)

sys.setdefaultencoding('utf8')

try:

tSocket = TSocket.TSocket('localhost',8899)

tSocket.setTimeout(600)

# 与java服务器一样使用相同的传输协议,数据的传输方式,服务模型

transport = TTransport.TFramedTransport(tSocket)

protocal = TCompactProtocol.TCompactProtocol(transport)

client = PersonService.Client(protocal)

transport.open()

# 调用getPersonByUsername方法返回一个person对象

person = client.getPersonByUsername("张三")

print person.username

print person.age

print person.married

print '--------------'

newPerson = ttypes.Person()

newPerson.username ='lisi'

newPerson.age = 30

newPerson.married =True

client.savePerson(newPerson)

transport.close()

except Thrift.TException,tx:

print '%s' % tx.message

启动java服务器端和python客户端,

python客户端打印:

张三

32

True

--------------

java服务器端的打印结果:

Got client Param:张三

Got Client Param:

lisi

30

true

java客户端,python服务器端

服务器端要编写服务接口的实现和服务器端代码:

# _*_ coding:utf-8 _*_

__author__ = '作者'

# 导入包

from py.thrift.generated import ttypes

#处理器

class PersonHandler :

def getPersonByUsername(self,username):

print "Got client param: "+username

person = ttypes.Person()

person.username = username

person.age = 20

person.married = False

return person

def savePerson(self,person):

print "Got client param: "

print person.username

print person.age

print person.married

python 服务器端代码

# _*_ coding:utf-8 _*_

__author__ = '作者'

# 导入包

from py.thrift.generated import PersonService

from PersonHandler import PersonHandler

from thrift import Thrift

from thrift.transport import TSocket

from thrift.transport import TTransport

from thrift.protocol import TCompactProtocol

from thrift.server import TServer

try:

personHandler = PersonHandler()

processor = PersonService.Processor(personHandler)

serverSocket = TSocket.TServerSocket(port=8899)

# 传输方式工厂

transportFactory = TTransport.TFramedTransportFactory()

# 协议工厂

protocolFactory = TCompactProtocol.TCompactProtocolFactory()

server = TServer.TSimpleServer(processor,serverSocket,transportFactory,protocolFactory)

server.serve()

except Thrift.TException, ex:

print '%s' % ex.message

java客户端:

import org.apache.thrift.protocol.TCompactProtocol;

import org.apache.thrift.protocol.TProtocol;

import org.apache.thrift.transport.TFastFramedTransport;

import org.apache.thrift.transport.TSocket;

import org.apache.thrift.transport.TTransport;

import thrift.generated.Person;

import thrift.generated.PersonService;

//服务端的协议和客户端的协议要一致

public class ThriftClient {

public static void main(String[] args) {

TTransport tTransport = new TFastFramedTransport(new TSocket("localhost",8899),600);

TProtocol tProtocol = new TCompactProtocol(tTransport);

PersonService.Client client = new PersonService.Client(tProtocol);

try{

tTransport.open();

Person person = client.getPersonByUsername("张三");

System.out.println(person.getUsername());

System.out.println(person.getAge());

System.out.println(person.isMarried());

System.out.println("............");

Person person2 = new Person();

person2.setUsername("李四");

person2.setAge(30);

person2.setMarried(true);

client.savePerson(person2);

}catch (Exception ex){

throw new RuntimeException(ex.getMessage(),ex);

}finally {

tTransport.close();

}

}

}

启动python服务器端和java客户端,python服务器端控制台打印:

Got client param: 张三

Got client param:

李四

30

True

java客户端代码:

Received 1

张三

20

false

............

Received 2

总结

比较一下Apache thrift与Protobuf之间的区别:

单纯的只看Protobuf本身,Protobuf只是一个序列化与反序列化的一个库而已,而Protobuf并没有提供网络传输载体,我们之前的netty与Protobuf结合就是使用netty作为网络传输组件(也就是说netty作为RPC框架中的Transport(传输方式)组件),而Protobuf作为Protocal(传输协议)组件。而Apache thrift本身就是一个跨语言的RPC框架,可以直接通过thrift就可以客户端与服务器之间的通信(通过idl文件生成的代码即提供了传输协议,也提供了网络传输方式)。基于Protobuf没有提供网络传输组件,google又推出了自己的RPC框架GRPC,GRPC是基于Protobuf 3.0版本,基于.proto文件不仅能生成序列化反序列化程序代码,也可以生成传输层次的代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值