RPC(Remote Procedure Call)即远程过程调用,说简单点就是服务端和客户端遵守一套约定好的协议,然后客户端就可以调用服务端的函数。目前主流的rpc框架对比如下:
功能 | Hessian | Montan | rpcx | gRPC | Thrift | Dubbo | Dubbox | Spring Cloud |
---|---|---|---|---|---|---|---|---|
开发语言 | 跨语言 | Java | Go | 跨语言 | 跨语言 | Java | Java | Java |
分布式(服务治理) | × | √ | √ | × | × | √ | √ | √ |
多序列化框架支持 | hessian | √(支持Hessian2、Json,可扩展) | √ | × 只支持protobuf) | ×(thrift格式) | √ | √ | √ |
多种注册中心 | × | √ | √ | × | × | √ | √ | √ |
管理中心 | × | √ | √ | × | × | √ | √ | √ |
跨编程语言 | √ | ×(支持php client和C server) | × | √ | √ | × | × | × |
支持REST | × | × | × | × | × | × | √ | √ |
关注度 | 低 | 中 | 低 | 中 | 中 | 中 | 高 | 中 |
上手难度 | 低 | 低 | 中 | 中 | 中 | 低 | 低 | 中 |
运维成本 | 低 | 中 | 中 | 中 | 低 | 中 | 中 | 中 |
开源机构 | Caucho | Apache | Apache | Alibaba | Dangdang | Apache |
公司内部目前使用的方案是(server mesh or http) + protobuf,并不是真正意义上的RPC,最近自己研究了下,可以采用Thrift实现远程服务调用,然后使用zookeeper构建服务发现和治理功能。下面主要介绍Thrift的使用。
Thrift项目的使用主要为以下流程(安装工具环境等请自行百度):
服务端:
1.定义接口文件
2.根据接口文件利用命令生成服务端对应语言的接口代码
3.构建服务端代码,部署服务端代码
客户端:
1.找服务端开发获取其定义的接口文件
2.根据接口文件利用命令生成客户端对应语言的接口代码
3.构建客户端代码,调用服务端方法
下面介绍利用Thrift服务端和客户端都是python实现RPC的案例
1.定义接口文件test.thrift
service TestService {
string test(1: i32 num,
2: string name)
}
这就是一个很简单的接口,接口有连个参数,第一个为32位的整数,第二个为字符串,返回值为字符串。
2.服务端根据接口文件生成接口代码
thrift -gen py test.thrift
运行完这个命令后你会收获以下文件
3.根据接口代码编写服务端代码server.py,放在gen-py根目录,并运行main函数启动服务
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer
from test import TestService
class TestServiceHandler:
def test(self, num, name):
return 'My name is ' + name + ', my age is ' + str(num)
if __name__ == '__main__':
handler = TestServiceHandler()
processor = TestService.Processor(handler)
transport = TSocket.TServerSocket(host='0.0.0.0', port=9090)
tfactory = TTransport.TBufferedTransportFactory()
pfactory = TBinaryProtocol.TBinaryProtocolFactory()
server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)
print 'python server:ready to start'
server.serve()
4.将test.thrift文件人肉发送给客户端开发,然后客户端开发重复第二步。
5.根据生成的接口代码开发客户端代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from test8 import TestService
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
transport = TSocket.TSocket('0.0.0.0', 9090)
transport = TTransport.TBufferedTransport(transport)
protocol = TBinaryProtocol.TBinaryProtocol(transport)
client = TestService.Client(protocol)
transport.open()
cmd = 20
token = 'zhang san'
msg = client.test(cmd, token)
print(msg)
transport.close()
6.运行客户端代码,服务端返回结果
My name is zhang san, my age is 20
ps:需要保证客户端和服务端在一个局域网内,能互相拼通