RPC - Thrift Demo
2019-11-25 本文已影响0人
红薯爱帅
1. 前言
解决应用程序与服务器
传递数据的问题,大体上分为三类:
- SOA模型(面向消息)
- RPC模型(面向方法)
- REST模型(面向资源)
其中 RPC 模型,又分成三类:
- XML-RPC
- JSON-RPC,以写函数的思维去写出来的API,它在用的时候,就跟一个远程的函数似的。(叫JSON的原因是因为返回值是JSON)
- SOAP + WSDL [SOAP 本质上是 XML-RPC 的升级版]
目前,SOA模型很少在使用,RPC常用的也只有JSON-RPC
一种,还有著名的Thrift。
REST模型的资源,在大多情况情况,对应数据库的Table,通过Method很好地区分开了不同的操作。通过API的简洁设计,大大降低了项目开发过程中的沟通成本,提高了前后端开发的效率。因此,REST模型得到了广泛应用。
现在,GraphQL兴起,可以期待下。
- WEB开发中,使用JSON-RPC好,还是RESTful API好?
https://www.zhihu.com/question/28570307/answer/549218509
本文重点介绍一个Thrift的Demo。
2. Thrift
The Apache Thrift software framework, for scalable cross-language services development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages.
Thrift是一个典型的CS(客户端/服务端)结构,客户端和服务端可以使用不同的语言开发。既然客户端和服务端能使用不同的语言开发,那么一定就要有一种中间语言来关联客户端和服务端的语言,没错,这种语言就是IDL(Interface Description Language)。
thrift-layers.png- 支持的数据类型:
类型 描述
bool true, false
byte 8位的有符号整数
i16 16位的有符号整数
i32 32位的有符号整数
i64 64位的有符号整数
double 64位的浮点数
string UTF-8编码的字符串
binary 字符数组
struct 结构体
list 有序的元素列表,类似于STL的vector
set 无序的不重复元素集,类似于STL的set
map key-value型的映射,类似于STL的map
exception 是一个继承于本地语言的exception基类
service 服务,包含多个函数接口(纯虚函数)
- Thrift github
https://github.com/apache/thrift - thrift入门教程
https://www.jianshu.com/p/0f4113d6ec4b - thrift types
https://thrift.apache.org/docs/types
3. Thrift Demo
- Files
$ tree .
.
├── gen-py
│ ├── helloworld
│ │ ├── constants.py
│ │ ├── HelloWorld.py
│ │ ├── HelloWorld-remote
│ │ ├── __init__.py
│ │ └── ttypes.py
│ └── __init__.py
├── helloworld.thrift
└── my_proj
├── client.py
└── server.py
- IDL File,helloworld.thrift
service HelloWorld {
string ping(),
string say(1:string msg)
}
- generate python code through docker
$ docker run -v "$PWD:/data" thrift thrift -o /data --gen py /data/helloworld.thrift
- create server.py
# server.py
import socket
import sys
sys.path.append('../gen-py')
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer
from helloworld import HelloWorld
from helloworld.ttypes import *
class HelloWorldHandler:
def ping(self):
return "pong"
def say(self, msg):
ret = "Received: " + msg
print(ret)
return ret
#创建服务端
handler = HelloWorldHandler()
processor = HelloWorld.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!")
- create client.py
# client.py
import sys
sys.path.append('../gen-py')
from helloworld import HelloWorld #引入客户端类
from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
try:
#建立socket
transport = TSocket.TSocket('localhost', 9090)
#选择传输层,这块要和服务端的设置一致
transport = TTransport.TBufferedTransport(transport)
#选择传输协议,这个也要和服务端保持一致,否则无法通信
protocol = TBinaryProtocol.TBinaryProtocol(transport)
#创建客户端
client = HelloWorld.Client(protocol)
transport.open()
print("client - ping")
print("server - " + client.ping())
print("client - say")
msg = client.say("Hello!")
print("server - " + msg)
#关闭传输
transport.close()
#捕获异常
except Thrift.TException as ex:
print("%s" % (ex.message))
4. Demo Test
- 运行server,在启动client之后收到
Hello!
$ python3 server.py
Starting thrift server in python...
Received: Hello!
- 运行client
$ python3 client.py
client - ping
server - pong
client - say
server - Received: Hello!
5. Refers
- Thrift documents
https://thrift.apache.org/ - 什么是Thrift
https://blog.csdn.net/san1156/article/details/41146429 - Thrift跨语言样例开发
https://blog.csdn.net/san1156/article/details/43308305