thrift服务(for Python/Java)的简易搭建步骤(不求甚解版)

关于这个话题,网上有大量的文章;但是配置部分都讲得比较混乱,直接拷来并不能跑通。
本文以python和java分别作为服务端/客户端及其逆形式进行了演示,不求甚解,只求能用。

定义好thrift文件,作为C/S的契约[1]

xxx.thrift
注意:以下代码都是手动混淆过的,仅大致示意写法,不保证内容正确

namespace java com.x1.x2.x3.x4.x5.gen_java # 注意,如果是为java版本准备的,一定要写好package

struct MyStruct1{
    1:string field1,
    2:list<string> field2,
    3:optional list<MyStruct1> field3, # 注意java不支持optinal,生成的代码中只有必选项
}

struct MyStruct2{
    1:list<i16> data
}

service MyService{
    void f1(1:MyStruct1 s1)
    list<MyStruct2> f2(1:string field1, 2:MyStruct1 data)
}

将thrift文件分别编译成服务器端语言和客户端语言
注意:自动生成的python代码中,可能有class A依赖class B,而A的代码却写到了同一个文件中B的下方的情况;这可能是thrift的一个BUG,手动调整代码顺序即可

mkdir gen_py gen_java # 默认名字是用短横线分隔(gen-py),不符合python的包命名要求;手动改成下划线
thrift -r --gen py -out gen_py xxx.thrift
thrift -r --gen java -out ../../../../../../ xxx.thrift # 路径中有x1-x5,就要上6层

实现服务端逻辑

注意:

  • gen_py和gen_java文件夹的内容最好别改动;它们都只是作为辅助类库使用的
  • 服务器端要自己写一个Handler类去override指定的方法
  • 客户端只要绑定到指定的端口上调用即可

python版服务器端

先用自己的类来继承IFace,实现各个接口

# thrift 相关的引用
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer
from thrift.transport import TSocket, TTransport
# import ... # 逻辑相关的引用

class MyHandler(MyService.Iface):
    def __init__(self):
        transport = TSocket.TSocket('hostname', 8095) # 最好用IP,稳一点
        transport = TTransport.TBufferedTransport(transport)
        transport.open()  # 注意这一行不能少
        protocol = TBinaryProtocol.TBinaryProtocol(transport)
        # self.xxx = yyy 之类的初始化,省略 ...

    def f1(self, arg1):
        pass # ...

然后写一个server.py来包裹handler并控制服务的起停

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

# sys.path.append('thrift/gen_py') # 可能需要把gen_py加到PYTHONPATH
# import ... # 逻辑相关的引用

def main():
    handler = MyHandler()
    processor = MyService.Processor(handler)
    transport = TSocket.TServerSocket('10.1.x.x', 8081)
    tfactory = TTransport.TBufferedTransportFactory()
    pfactory = TBinaryProtocol.TBinaryProtocolFactory()
    server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory)

    logger.info('---------- starting xxx server over thrift...')
    server.serve()
    logger.info('---------- shutting down xxx server over thrift...')

if __name__ == '__main__':
    main()

java版的服务器端

同理,先写个Handler类来覆盖相应的method

package com.xxx.xxx.xxx
// import ...

public class MyHandler implements MyService.Iface {
    @Override
    public synchronized void f1(MyStruct1 arg1) throws TException {
        // ...
    }
    // ... 
}

然后写个Server类来包裹Handler并控制服务的起停

package com.x.x.x.xxx

import ... // 逻辑相关的引用
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TTransportException;

import java.io.IOException;
import java.net.InetSocketAddress;

public class MyServer {
    public static void main(String[] args) throws IOException, TTransportException {
        MyService.Processor processor = new MyService.Processor(new MyHandler());

        TServerSocket serverTransport = new TServerSocket(new InetSocketAddress("1.2.3.4", 1234));
        TServer server = new TSimpleServer(new TThreadPoolServer.Args(serverTransport).processor(processor));
        System.out.println("Starting server...");
        server.serve();
    }
}

实现客户端逻辑

java版客户端

先把之前运行thrift -r --gen java ...命令生成的gen_java文件夹拷进来,作为一个package;
然后把Guava等其它各种类库写进maven/Gradle。
插一句:如果用到读写wav文件的功能,可以把wavFile相关的类库[2]下载了拷进来。

package com.xxx.yyy;

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;
// import ...

public class App {
    public void work(List<String> arg) {
        try {
            TTransport transport = new TSocket("1.2.3.4", 1234); // 注意两边都尽量用IP,比较稳一点
            transport.open();
            TProtocol protocol = new TBinaryProtocol(transport);
            
            MyService.Client client = new MyService.Client(protocol);
            // arg1 = ...
            client.f1(arg);
            // 多次调用 client.f2(...)

            transport.close();
            System.out.println("----- client done");
        } catch (TException ex) {
            ex.printStackTrace();
        } // 更多catch ...
    }

    public static void main(String[] args) {
        App app = new App();
        app.work(Lists.newArrayList("arm", "aunt", "autumn"));
    }
}

python版的客户端写法

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

# 可能需要将gen_py加到PYTHONPATH
# import 逻辑相关的模块 ...

def main():
    transport = TSocket.TSocket('1.2.3.4', 8081)
    transport = TTransport.TBufferedTransport(transport)
    transport.open()
    protocol = TBinaryProtocol.TBinaryProtocol(transport)
    client = MyService.Client(protocol)

    # arg = ...
    client.f1(arg)
    # 多次调用 client.f2(...)
    print('----- client done')

if __name__ == '__main__':
    main()

  1. thrift文件写法参考:http://www.jianshu.com/p/0f4113d6ec4b

  2. Java Wav File IO API:http://www.labbookpages.co.uk/audio/javaWavFiles.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容