vieyahn2017 / thrift-trial

my thrift trial.
0 stars 0 forks source link

样例(python版本) #3

Open vieyahn2017 opened 5 years ago

vieyahn2017 commented 5 years ago

python版本看来最简单

vieyahn2017 commented 5 years ago

样例一

来自 thrift安装和使用 https://blog.csdn.net/minstyrain/article/details/83928280

还是推荐用python版本,C++版实在是太麻烦了,默认的CMakeList.txt对文件结构产生了依赖,在外面无法编译过.

我们以最简单的实现两个数相加的服务为例,用python实现对应的逻辑

首先需要编写的就是协议文件,将其定义在calculator命名空间下,输入为两个整数,输出为一个整数

namespace py calculator

service Calculator{
    i32 add(1: i32 a, 2:i32 b),
}

然后用thrift生成相应的代码

thrift --gen py add.thrift

这样就会生成python对应的代码

接下来编写服务端的代码server.py

import glob
import sys
sys.path.append('gen-py')
from calculator import Calculator

from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer

class CalculatorHandler:
    def __init__(self):
        self.log = {}
    def add(self, n1, n2):
        print('add(%d,%d)' % (n1, n2))
        return n1 + n2

if __name__=="__main__":
    handler=CalculatorHandler()
    processor=Calculator.Processor(handler)
    transport=TSocket.TServerSocket(host='127.0.0.1', port=9090)
    tfactory=TTransport.TBufferedTransportFactory()
    pfactory=TBinaryProtocol.TBinaryProtocolFactory()
    server=TServer.TSimpleServer(processor,transport,tfactory,pfactory)
    print('Starting the server...')
    server.serve()
    print('done.')
```p
最后是客户端部分的代码client.py
```python
import sys
import glob
sys.path.append('gen-py')

from calculator import Calculator

from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol

def main():
    transport=TSocket.TSocket('localhost', 9090)
    transport=TTransport.TBufferedTransport(transport)
    protocol=TBinaryProtocol.TBinaryProtocol(transport)
    client=Calculator.Client(protocol)
    transport.open()
    sum=client.add(1,1)
    print(sum)

if __name__ == '__main__':
    main()

测试效果:

服务端启动及输出:

python server.py
Starting the server...
add(1,1)

客户端启动

python client.py
2
vieyahn2017 commented 5 years ago

样例二 thrift的使用--python

https://blog.csdn.net/luoyexuge/article/details/80433139

转载blog:http://www.cnblogs.com/pinking/p/7726478.html

在这里要补充一点的就是在

在这里python要安装thrift包时候,可以直接在安装好的thrift好的模块中sudo python setup.py install安装就可以,

以下原文,作者在Windows上面,我在linux上面:

1、下载thrift,下载地址:http://archive.apache.org/dist/thrift/0.9.3/

2、在编写python的thrift代码时,需要先安装thrift module,下载路径:https://pypi.python.org/pypi/thrift/0.9.1

3、安装thrift:

tar -zvxf thrift-0.9.3.tar.gz 直接下一步。。。

在命令行中输入:

thrift --version

Thrift version 0.9.3

即可以看到安装后的版本信息。

4、thrift 采用IDL(Interface Definition Language)来定义通用的服务接口,并通过生成不同的语言代理实现来达到跨语言、平台的功能。 在thrift的IDL中可以定义以下一些类型:基本数据类型,结构体,容器,异常、服务。

thrift脚本helloworld.thrift:

const string HELLO_YK = "yk"
service HelloWorld {
void ping(),
string sayHello(),
string sayMsg(1:string msg)
}

thrift脚本通过Thrift编辑器生成所要求的python开发语言代码。即:

thrift  -r  --gen py  helloworld.thrift 

5、Thrift是一个典型的CS结构,客户端和服务端可以使用不同的语言开发。本文以python为例:

PythonServer.py:

import sys
sys.path.append('./gen-py')

from helloworld import HelloWorld
from helloworld.ttypes import *

from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer

import socket

class HelloWorldHandler:
  def __init__(self):
    self.log = {}

  def ping(self):
    print "ping()"

  def sayHello(self):
    print "sayHello()"
    return "say hello from " + socket.gethostbyname(socket.gethostname())

  def sayMsg(self, msg):
    print "sayMsg(" + msg + ")"
    return "say " + msg + " from " + socket.gethostbyname(socket.gethostname())

handler = HelloWorldHandler()
processor = HelloWorld.Processor(handler)
transport = TSocket.TServerSocket('127.0.0.1',30303)
tfactory = TTransport.TBufferedTransportFactory()
pfactory = TBinaryProtocol.TBinaryProtocolFactory()

server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)

print "Starting python server..."
server.serve()
print "done!"

PythonClient.py

import sys
sys.path.append('./gen-py')

from helloworld import HelloWorld
from helloworld.ttypes import *
from helloworld.constants import *

from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol

try:
  # Make socket
  transport = TSocket.TSocket('127.0.0.1', 30303)

  # Buffering is critical. Raw sockets are very slow
  transport = TTransport.TBufferedTransport(transport)

  # Wrap in a protocol
  protocol = TBinaryProtocol.TBinaryProtocol(transport)

  # Create a client to use the protocol encoder
  client = HelloWorld.Client(protocol)

  # Connect!
  transport.open()

  client.ping()
  print "ping()"

  msg = client.sayHello()
  print msg
  msg = client.sayMsg(HELLO_YK)
  print msg

  transport.close()

except Thrift.TException, tx:
  print "%s" % (tx.message)

运行结果:

server端:

python  PythonServer.py 

Starting python server...

ping()

client端:

python PythonClient.py 

ping()

say hello from 10.101.173.116

say yk from 10.101.173.116
vieyahn2017 commented 5 years ago

样例三

Python Thrift 简单示例 http://www.cnblogs.com/hapjin/p/8075721.html

本文基于Thrift-0.10,使用Python实现服务器端,使用Java实现客户端,演示了Thrift RPC调用示例。Java客户端提供两个字符串参数,Python服务器端计算这两个字符串的相似度,并返回相似度结果(double类型,范围[0, 1],0表示不相似,1表示完全相同)

一,环境安装

开发环境:Windows10,PyCharm2016,Anaconda3,Python3.6

首先安装python 的thrift包:windows打开Anaconda prompt,输入:conda install -c anaconda thrift 安装thrift包。

输入:conda list 可查看系统中已经安装了哪些包,及包的版本,如下图所示:我们安装的是:thrift-0.10.0

在写代码之前,需要先定义一个 .thrift文件,然后使用Thrift Compiler生成相应的Thrift服务需要依赖的“文件”

1 定义.thrift文件

namespace py similarityservice
namespace java similarityservice

service ChatSimilarityService{
    double similarity(1:string chat1, 2:string chat2),
}

namespace提供了一种组织代码的方式。其实就是,生成的文件放在:similarityservice这个文件夹下。

由于前面的Python安装的thrift-0.10,因此在官网上下载:thrift-0.10.exe,将它放在与 .thrift相同的目录下,cmd切换到该目录下,执行命令:

.\thrift-0.10.0.exe --gen py chat_similarity.thrift

生成的文件如下,将它们放在合适的python包下,即可供python 服务端程序 import 了。

二,Python服务端实现

pycharm thrift插件支持

可以去pycharm插件官网下载一个thrift插件,安装好之后,编写 .thrift 文件能够自动补全提示。

服务端的实现 主要有以下五方面:(个人理解,可能有错)

①Handler

服务端业务处理逻辑。这里就是业务代码,比如 计算两个字符串 相似度

②Processor

从Thrift框架 转移到 业务处理逻辑。因此是RPC调用,客户端要把 参数发送给服务端,而这一切由Thrift封装起来了,由Processor将收到的“数据”转交给业务逻辑去处理

③Protocol

数据的序列化与反序列化。客户端提供的是“字符串”,而数据传输是一个个的字节,因此会用到序列化与反序列化。

④Transport

传输层的数据传输。

⑤TServer

服务端的类型。服务器以何种方式来处理客户端请求,比如,一次Client请求创建一个新线程呢?还是使用线程池?……可参考:阻塞通信之Socket编程

TSimpleServer —— 单线程服务器端使用标准的阻塞式 I/O

TThreadPoolServer —— 多线程服务器端使用标准的阻塞式 I/O

TNonblockingServer —— 多线程服务器端使用非阻塞式 I/O

把上面生成的thrift文件复制到 thrift_service包下,如下图:

整个python 服务端的完整代码如下:

from thrift.protocol import TBinaryProtocol
from thrift.server import TServer
from thrift.transport import TSocket, TTransport

from text.thrift_service.similarityservice import ChatSimilarityService
from difflib import SequenceMatcher
from pypinyin import pinyin

import zhon
import pypinyin
from zhon.hanzi import punctuation
import re

__HOST = '127.0.0.1'
__PORT = 9090

def similar_num(list1, list2):
    return len(set(list1).intersection(list2))

def similar_ration(str1, str2):
    return SequenceMatcher(lambda x: x == ' ', str1, str2).ratio()

class SimilarityHandler(ChatSimilarityService.Iface):
    def __init__(self):
        self.log={}
    def ping(selfs):
        print('ping')

    def similarity(self, chat1, chat2):
        #去掉中文字符串中的特殊标点符号
        list1 = re.findall('[^{}]'.format(zhon.hanzi.punctuation), chat1)
        list2 = re.findall('[^{}]'.format(zhon.hanzi.punctuation), chat2)

        #将标点符号转换成拼音
        pinyin1 = pinyin(list1, style=pypinyin.STYLE_NORMAL)
        pinyin2 = pinyin(list2, style=pypinyin.STYLE_NORMAL)

        #将所有的拼音统一保存到 单个list 中
        pinyin_list1 = [word[0] for word in pinyin1]
        pinyin_list2 = [word[0] for word in pinyin2]

        #计算 list 中元素相同的个数
        result1 = similar_num(pinyin_list1, pinyin_list2)

        #list convert to string
        str1_pinyin = ''.join(pinyin_list1)
        str2_pinyin = ''.join(pinyin_list2)
        #计算字符串的相似度
        result2 = similar_ration(str1_pinyin, str2_pinyin)

        print('ratio:{}, nums:{}'.format(result2, result1))
        return result2

if __name__ == '__main__':
    handler = SimilarityHandler()
    processor = ChatSimilarityService.Processor(handler)
    transport = TSocket.TServerSocket(host=__HOST, port=__PORT)
    tfactory = TTransport.TBufferedTransportFactory()
    pfactory = TBinaryProtocol.TBinaryProtocolFactory()

    server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory)

    print('Starting the server')
    server.serve()
    print('done')

这里简单地介绍下实现思路:

①使用python 的 zhon 包过滤掉中文中出现的标点符号等特殊字符

②python的 pypinyin 包 将中文转换成字符串(其实也可以直接比较中文字符串的相似度,但我这里转换成了拼音,就相当于比较英文字符串了)

③使用python 的 difflib 包中的SequenceMatcher 类来计算两个字符串之间的相似度

三,Java客户端实现

①在maven工程的pom.xml中添加thrift依赖。这里的libthrift版本、windows10下载的thrift compiler版本(thrift-0.10.0.exe),还有 python的 thrift包的版本 最好保持一致。

        <!-- https://mvnrepository.com/artifact/org.apache.thrift/libthrift -->
        <dependency>
            <groupId>org.apache.thrift</groupId>
            <artifactId>libthrift</artifactId>
            <version>0.10.0</version>
        </dependency>

②cmd命令行执行:.\thrift-0.10.0.exe --gen java chat_similarity.thrift 生成 ChatSimilarityService.java 文件,Java 客户端代码需要依赖它。

整个Java Client的代码如下:

import thrift.similarityservice.ChatSimilarityService;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;

/**
  * Created by Administrator on 2017/12/20.
  */

public class SimilarityThriftClient {

    public static void main(String[] args) {
        try {
            TTransport transport;
            transport = new TSocket("127.0.0.1", 9090);
            transport.open();

            TProtocol protocol = new TBinaryProtocol(transport);
            ChatSimilarityService.Client client = new ChatSimilarityService.Client(protocol);
            perform(client);
            transport.close();

        } catch (TException e) {
            e.printStackTrace();
        }
    }

    private static void perform(ChatSimilarityService.Client client)throws TException {
        String chat1 = "您好。";
        String chat2 = "你好";
        double ratio = client.similarity(chat1, chat2);
        System.out.println(ratio);
    }
}

四,总结

本文介绍了一个简单的 Python Server、Java Client的Thrift服务调用示例。关于Thrift可参考: