目前有這么一個(gè)需求:線上有很多個(gè)爬蟲(chóng)程序辑畦,它們?cè)跀?shù)據(jù)清洗完成后都要做文本情感分析眠屎。以往同學(xué)的做法是在每個(gè)爬蟲(chóng)中把相同代碼都Copy一份蕴轨,但是考慮到這樣會(huì)讓項(xiàng)目維護(hù)變得極其困難欠动,所以在重構(gòu)的使用考慮以基礎(chǔ)服務(wù)的方式提供情感分析模塊。thrift是Facebook開(kāi)源的一套跨語(yǔ)言服務(wù)調(diào)用RPC贾漏,用它便可以進(jìn)行某些功能模塊的服務(wù)化候学,thriftpy是餓了么開(kāi)源的thrift協(xié)議的純Python實(shí)現(xiàn)。由于它的使用更加符合Python的編碼習(xí)慣纵散,對(duì)Pythoneer更友好梳码,所以在剛接觸thrift的時(shí)候我選擇了后者。
在thriftpy的example中伍掀,我們可以看到大量使用demo掰茶。首先我們來(lái)看一個(gè)最簡(jiǎn)單的例子pingpong
service PingService {
string ping(),
}
該文件的作用是描述服務(wù)接口,形式采用C語(yǔ)言的語(yǔ)法硕盹,所有基本類型(如上述文件的string
)如下
bool:布爾類型(true or value)符匾,占一個(gè)字節(jié)
byte:有符號(hào)字節(jié)
i16:16位有符號(hào)整型
i32:32位有符號(hào)整型
i64:64位有符號(hào)整型
double:64位浮點(diǎn)數(shù)
string:未知編碼或者二進(jìn)制的字符串
比如,我定義一個(gè)需要帶參數(shù)的接口瘩例,就該這樣
service AargsPingService {
string ping(1:string ping);
}
除了同步調(diào)用以外啊胶,還可以采用異步調(diào)用的方式,我們也需要在.thrift
文件中進(jìn)行定義垛贤,比如我想定義一個(gè)異步調(diào)用焰坪,且返回內(nèi)容的方法
service Sleep {
oneway void sleep(1: i32 seconds)
}
可以看到,我們加了關(guān)鍵詞oneway
聘惦。
我們?cè)賮?lái)看看如何編寫(xiě)thriftpy的服務(wù)端代碼某饰,還是以最簡(jiǎn)單的ping
為例進(jìn)行說(shuō)明
ping_server.py
# 導(dǎo)入thriftpy提供的接口
import thriftpy
from thriftpy.rpc import make_server
pp_thrift = thriftpy.load("pingpong.thrift", module_name="pp_thrift")
# 實(shí)現(xiàn).thrift文件定義的接口
class Dispatcher(object):
def ping(self):
print("ping pong!")
return 'pong'
def main():
# 定義監(jiān)聽(tīng)的端口和服務(wù)
server = make_server(pp_thrift.PingService, Dispatcher(),
'127.0.0.1', 6000)
print("serving...")
server.serve()
if __name__ == '__main__':
main()
如果我們要同時(shí)提供多個(gè)服務(wù)呢?比如PingService
和AargsPingService
。這個(gè)時(shí)候需要建立多個(gè).thrift
文件黔漂,可以參考multiplexer 诫尽。
我們?cè)賮?lái)看看客戶端代碼怎么寫(xiě)。
ping_client.py
import thriftpy
from thriftpy.rpc import client_context
# 讀入thrift文件炬守,module_name最好與server端保持一致牧嫉,也可以不保持一致
pp_thrift = thriftpy.load("pingpong.thrift", module_name="pp_thrift")
def main():
with client_context(pp_thrift.PingService, '127.0.0.1', 6000) as c:
pong = c.ping()
print(pong)
if __name__ == '__main__':
main()
如果一個(gè)服務(wù)比較耗時(shí),但是我們需要同步拿到返回結(jié)果减途,那么怎么辦酣藻?這個(gè)時(shí)候需要注意客戶端調(diào)用超時(shí),thriftpy
的默認(rèn)超時(shí)時(shí)間是3秒鳍置,我們可以通過(guò)修改客戶端的socket_time
和connect_time
來(lái)進(jìn)行設(shè)置
with client_context(pp_thrift.PingService, '127.0.0.1', 6000, socket_timeout=10 * 1000, connect_timeout=10*1000) as c:
此外辽剧,由于thriftpy
默認(rèn)的server是單進(jìn)程的,為了充分利用CPU資源税产,eleme又開(kāi)源了一個(gè)多進(jìn)程的server gunicorn_thrift怕轿。需要單獨(dú)通過(guò)
pip install gunicorn_thrift
此外還需要注意一點(diǎn),在Python3中砖第,只支持 多進(jìn)程同步模型撤卢,也就是需要在gunicorn_config.py修改
worker_class = "thriftpy_gevent"
為worker_class = "thriftpy_sync"
。Python2中是支持協(xié)程的梧兼。