Fork me on GitHub

Thriftpy—[RPC文件传输]

ThriftPy is a pure python implementation of Apache Thrift in a pythonic way.


Github地址
Documentation


环境及版本

1
2
3
4
5
【Server、Client】
Ubuntu 14.04 LTS x64
Thriftpy 0.3.8
Python 2.7
Pycharm 4.5.1

简单Server & Client

Thriftpy的使用和Thrift类似,用两台Ubuntu分别做Server和Client,实现跨机器通信

Server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import thriftpy
from thriftpy.rpc import make_server
import os

class MyRPC(object):
# 提供调用的方法
def print_fun(self,name):
str = "Hello " + name
return str

if __name__ == "__main__":
file_path = os.path.abspath("../conf/simple.thrift")
# 加载注册文件
simple_thrift = thriftpy.load(file_path, module_name="simple_thrift")

server = make_server(simple_thrift.RPCTest, MyRPC(), '192.168.1.105', 6000)
print "Thriftpy listening 6000......"
server.serve()

Client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import thriftpy
from thriftpy.rpc import make_client
import os

if __name__ == "__main__":
file_path = os.path.abspath("../conf/simple.thrift")

# 加载注册文件
simple_thrift = thriftpy.load(file_path, module_name="simple_thrift")

client = make_client(simple_thrift.RPCTest, '192.168.1.105', 6000)
print client.print_fun("wxmimperio")

Service Conf

方法注册文件以.thrif为后缀,Server与Client都必须有,文件目录可以指定

1
2
3
service RPCTest {
string print_fun(1:string name),
}

Thrift支持的数据类型Thriftpy里都支持

  • 基本数据类型(Java为准)
类型 说明
bool(boolean) 布尔类型(TRUE or FALSE)
byte(byte) 8位带符号整数
i16(short) 16位带符号整数
i32(int) 32位带符号整数
i64(long) 64位带符号整数
double(double) 64位浮点数
string(String) 采用UTF-8编码的字符串
  • 复合数据类型(Java为准)
类型 说明
list(java.util.ArrayList) 列表
set(java.util.HashSet) 集合
map(java.util.HashMap) 键值对
  • 特殊数据类型(Java为准)
类型 说明
binary(ByteBuffer) 未经过编码的字节流
struct(结构体) 定义了一个很普通的OOP对象,但是没有继承特性

复合、特殊数据、基本数据类型可以嵌套使用


RPC传输文件

这里我采用Base64进行编码与解码,将文件从Client传向Server

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。Base64编码可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。

Server 接收文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = 'wxmimperio'

import thriftpy
from thriftpy.rpc import make_server
import os

class MyFileRPC(object):
def file_server(self, file_list):
if file_list:
files_path = os.path.abspath("../")
for item in file_list:
with open(files_path + "/" + item[0], "wb") as file:
file.write(item[1].decode("base64"))
return "file create!"
else:
return "file_list is empty!"

def server_start(conf_path, server_ip, server_port):
# 加载注册文件
file_thrift = thriftpy.load(conf_path, module_name="file_thrift")
server = make_server(file_thrift.FileRPC, MyFileRPC(), server_ip, server_port)
print "Thriftpy listening " + str(server_port) + "......"
server.serve()

if __name__ == "__main__":
conf_path = os.path.abspath("../conf/file.thrift")
server_start(conf_path, "192.168.1.105", 6000)

Client 发送文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = 'wxmimperio'

import thriftpy
from thriftpy.rpc import make_client
import os

def client_start(conf_path, client_ip, client_port):
file_thrift = thriftpy.load(conf_path, module_name="file_thrift")
return make_client(file_thrift.FileRPC, client_ip, client_port)

def opt_files(files_path_list):
files_context_list = []
files_name_list = []

for item in files_path_list:
with open(item, "rb") as files:
files_context_list.append(files.read().encode("base64"))
# 获取文件名
files_name_list.append(item.split('/')[-1])
return zip(files_name_list, files_context_list)

if __name__ == "__main__":
conf_path = os.path.abspath("../conf/file.thrift")
client = client_start(conf_path, "192.168.1.105", 6000)

files_path_list = []
files_path_list.append(os.path.abspath("../files/markdown.md"))
files_path_list.append(os.path.abspath("../files/markdown.pdf"))
files_path_list.append(os.path.abspath("../files/photo.jpg"))

files_info = opt_files(files_path_list)
print client.file_server(files_info)

Service Conf

1
2
3
service FileRPC {
string file_server(1:list<list<string>> file_list),
}

本文Github源码


转载请注明出处


Thank you for your support.