User Tools

Site Tools


Sidebar

Go Back

Refresh

You are not allowed to add pages

Direct Link

library:rpc:thrift_tutorial

Thrift Tutorial

1. Abstract

本Demo用于展示 Thrift 跨平台(Linux,Windows)、跨编程语言(Python,Javascript,C++)的远过程调用(传输消息)功能,实现从某一应用程序(client)向另一应用程序(server)发送消息的过程。

  • Server端(被调用的过程)实现两个接口:

ping() – 原文返回Client端送来的文本,在前面添加文本“echo:”

post() – 接收client送来的一个JSON字符串,并添加 “res”:True 字段/数值作为回应,否则,当收到非法JSON串,返回包含 “res”:False 字段/数值 的JSON串。

  • Client端调用 ping 和 post接口,并打印返回值。

已完成测试:

Windows : Python, Javascript

Linux: Python, C++

Windows Linux
Server Client Server Client
Python
JScript
C++

1.1 Install Thrift on Window

1.2 Install Thrift on Ubuntu

  • 安装相关依赖包

sudo apt-get install automake bison flex g++ git libboost-all-dev libevent-dev libssl-dev libtool make pkg-config

  • 下载 Thrift 并解压(可采取多种下载方式)
wget https://dlcdn.apache.org/thrift/0.15.0/thrift-0.15.0.tar.gz
tar -xf thrift-0.15.0.tar.gz
  • 配置
./configure 

配置运行结果:

thrift 0.16.0

Building C (GLib) Library .... : no
Building C++ Library ......... : yes
Building Common Lisp Library.. : no
Building D Library ........... : no
Building Dart Library ........ : no
Building .NET Standard Library : no
Building Erlang Library ...... : no
Building Go Library .......... : no
Building Haxe Library ........ : no
Building Java Library ........ : no
Building Lua Library ......... : no
Building NodeJS Library ...... : no
Building Perl Library ........ : no
Building PHP Library ......... : no
Building Python Library ...... : yes
Building Py3 Library ......... : yes
Building Ruby Library ........ : no
Building Rust Library ........ : no
Building Swift Library ....... : no

C++ Library:
   C++ compiler .............. : g++ -std=c++11
   Build TZlibTransport ...... : yes
   Build TNonblockingServer .. : yes
   Build TQTcpServer (Qt5) ... : no
   C++ compiler version ...... : g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0

Python Library:
   Using Python .............. : /usr/bin/python
   Using Python version ...... : Python 3.8.10
   Using Python3 ............. : /usr/bin/python
   Using Python3 version ..... : Python 3.8.10

If something is missing that you think should be present,
please skim the output of configure to find the missing
component.  Details are present in config.log.

确认支持 C++, Python

  • 编译、安装、验证安装成功
sudo make
sudo make install
thrift -version

显示以下信息表示安装成功:

Thrift version 0.16.0
  • 更新系统环境

修改/etc/ld.so.conf文件,增加搜索路径,将/usr/local/lib添加到ld.so.conf文件中(指定库文件 *.so 的路径,否则运行应用程序时会出现缺少库文件错误)

sudo ldconfig

1.3 Thrift supported data type

基本数据类型 数据类型简单明了,包含了所有编程语言中的可用基本数据类型。

bool:布尔值(true/false) byte:8位有符号整型 i16:16位有符号整型 i32:32位有符号整型 i64:64位有符号整型 double:64位浮点数 string:由utf8编码的文本字符串

特殊类型 binary:未编码的字节流

结构体(struct)

容器(container)

枚举

服务

命名空间

注释

2. Service description file

A RPC description file below defining the RPC service interfaces.

DemoService.thrift
service DemoService
{
    string ping(1:string param)
    string post(1:string param)
}

3. @Python

3.1 Install Thrift module

pip install thrift

3.2 Generate interface

# Interface for Python,generated code at ./gen-py
thrift --gen py DemoService.thrift

3.3 Service and Client code

service.py
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer
import sys
 
sys.path.append("./gen-py/")
 
from DemoService import DemoService
import json
 
class DemoServer:
 
    def __init__(self):
        self.log = {}
 
    def ping(self, param):
        return "echo:" + param
 
    def post(self, jstr):
        try:
            jdict = json.loads(jstr)
        except Exception as e :
            return json.dumps({"res":False})
 
        jdict["res"] = True
        return json.dumps(jdict);
 
if __name__ == '__main__':
    handler = DemoServer()
    processor = DemoService.Processor(handler)
 
    # 监听端口
    transport = TSocket.TServerSocket(host="0.0.0.0", port=9999)
 
    # 选择传输层
    tfactory = TTransport.TBufferedTransportFactory()
 
    # 选择传输协议
    pfactory = TBinaryProtocol.TBinaryProtocolFactory()
 
    # 创建服务端
    server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory)
 
    # 设置连接线程池数量
    server.setNumThreads(5)
 
    # 启动服务
    server.serve()
client.py
from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
import sys
 
sys.path.append("./gen-py/")
from DemoService import DemoService
import json
if __name__ == '__main__':
    transport = TSocket.TSocket('127.0.0.1', 9999)
 
    transport = TTransport.TBufferedTransport(transport)
 
    protocol = TBinaryProtocol.TBinaryProtocol(transport)
 
    client = DemoService.Client(protocol)
 
    # 连接服务端
    transport.open()
 
    recv = client.ping("test")
    print(recv)
 
    recv = client.post(json.dumps({"Request":"Play"}) )
    print(recv)
 
    # 断连服务端
    transport.close()

3.4 Test

运行服务端:

# Run service
python service.py

运行Client端:

# Run client
python client.py

运行结果:

echo:test
{"Request": "Play", "res": true}

4. @ Node.js

4.1 Install Thrift module

npm install thrift

4.2 Generate interface

# Interface for Node.js, generated code at ./gen-node.js
thrift --gen js:node DemoService.thrift

4.3 Client code

client.js
var thrift = require('thrift');
 
var DemoService = require('./gen-nodejs/DemoService.js');
 
var transport = thrift.TBufferdTransport;
var protocol = thrift.TBinaryProtocol;
 
var connection = thrift.createConnection('localhost', 9999,{
	transport : transport,
	protocol : protocol
	});
 
 
client = thrift.createClient(DemoService, connection);
 
connection.on('error', function(err) {
	console.error(err);
});
 
 
client.ping('From Node.js')
	.then(log);
 
var json = {
	"Source": "node.js",
	"Request": "None"
}
 
client.post( JSON.stringify(json))
	.then(log)
 
function log(msg) {
	console.log(msg);
}

4.4 Test

运行client:

node client.js

运行结果:

echo:From Node.js
{"Source": "node.js", "Request": "None", "res": true}

5. @C++

5.1 Generate interface

# Interface for C++,generated code at ./gen-cpp
thrift -r --gen cpp DemoService.thrift

5.2 Client code

client.cpp
#include <iostream>
 
#include "gen-cpp/DemoService.h"
#include <transport/TSocket.h>
#include <transport/TBufferTransports.h>
#include <protocol/TBinaryProtocol.h>
 
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
 
using namespace std;
 
#define REMOTE_ADDRESS  "192.168.109.1"
#define REMOTE_PORT     9999
 
int main(int argc, char **argv) {
    string res;
 
    ::std::shared_ptr<TSocket> socket(new TSocket(REMOTE_ADDRESS, REMOTE_PORT));
    ::std::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
    ::std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
 
    DemoServiceClient client(protocol);
    transport->open();
    client.ping(res, "From C++ Client");
    cout << res << '\n';
 
    client.post(res, "{\"Source\":\"C++\"}");
    cout << res << '\n';
 
    transport->close();
    return 0;
}
 
// g++ -g -I/usr/local/include/thrift gen-cpp/DemoService.cpp client.cpp -lthrift -L/usr/local/lib/*.so -o client

编译:

g++ -g -I/usr/local/include/thrift gen-cpp/DemoService.cpp client.cpp -lthrift -L/usr/local/lib/*.so -o client

运行client:

./client

运行结果:

echo:From C++ Client
{"Source": "C++", "res": true}

5.3 Service code

service.cpp
#include <iostream>
 
#include "gen-cpp/DemoService.h"
#include <server/TSimpleServer.h>
#include <transport/TServerSocket.h>
#include <transport/TBufferTransports.h>
#include <protocol/TBinaryProtocol.h>
 
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::thrift::server;
 
using boost::shared_ptr;
using namespace std;
 
#define REMOTE_ADDRESS  "192.168.109.1"
#define REMOTE_PORT     9999
 
 
class ServiceHandler : virtual public ServiceIf {
	public:
	ServiceHandler() {
	}
 
	void ping(std::string& _return, const std::string& param) {
		cout << param << '\n';
	}
 
 
	void post(std::string& _return, const std::string& param) {
		cout << param << '\n';
	}
 
};
 
 
int main(int argc, char **argv) {
	int port = 9090;
	stdcxx::shared_ptr<ServiceHandler> handler(new ServiceHandler());
	stdcxx::shared_ptr<TProcessor> processor(new ServiceProcessor(handler));
	stdcxx::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
	stdcxx::shared_ptr<TNonblockingServerTransport> serverTransport(new TNonblockingServerSocket(port));
	stdcxx::shared_ptr<PlatformThreadFactory> threadFactory = std::shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory());
	stdcxx::shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(10);
 
	threadManager->threadFactory(threadFactory);
	threadManager->start();
 
	stdcxx::shared_ptr<TNonblockingServer> server(new TNonblockingServer(processor, protocolFactory, serverTransport, threadManager));
 
	server->serve();
 
	return 0;
}
 
// g++ -g -I/usr/local/include/thrift gen-cpp/DemoService.cpp service.cpp -lthrift -L/usr/local/lib/*.so -o service
library/rpc/thrift_tutorial.txt · Last modified: 2022/05/07 00:58 by lhaosen