目前有這么一個需求:線上有很多個爬蟲程序,它們在數據清洗完成后都要做文本情感分析。以往同學的做法是在每個爬蟲中把相同代碼都Copy一份,但是考慮到這樣會讓項目維護變得極其困難,所以在重構的使用考慮以基礎服務的方式提供情感分析模塊。thrift是Facebook開源的一套跨語言服務調用RPC,用它便可以進行某些功能模塊的服務化,thriftpy是餓了么開源的thrift協議的純Python實現。由于它的使用更加符合Python的編碼習慣,對Pythoneer更友好,所以在剛接觸thrift的時候我選擇了后者。
在thriftpy的example中,我們可以看到大量使用demo。首先我們來看一個最簡單的例子pingpong
service PingService {
string ping(),
}
該文件的作用是描述服務接口,形式采用C語言的語法,所有基本類型(如上述文件的string
)如下
bool:布爾類型(true or value),占一個字節
byte:有符號字節
i16:16位有符號整型
i32:32位有符號整型
i64:64位有符號整型
double:64位浮點數
string:未知編碼或者二進制的字符串
比如,我定義一個需要帶參數的接口,就該這樣
service AargsPingService {
string ping(1:string ping);
}
除了同步調用以外,還可以采用異步調用的方式,我們也需要在.thrift
文件中進行定義,比如我想定義一個異步調用,且返回內容的方法
service Sleep {
oneway void sleep(1: i32 seconds)
}
可以看到,我們加了關鍵詞oneway
。
我們再來看看如何編寫thriftpy的服務端代碼,還是以最簡單的ping
為例進行說明
ping_server.py
# 導入thriftpy提供的接口
import thriftpy
from thriftpy.rpc import make_server
pp_thrift = thriftpy.load("pingpong.thrift", module_name="pp_thrift")
# 實現.thrift文件定義的接口
class Dispatcher(object):
def ping(self):
print("ping pong!")
return 'pong'
def main():
# 定義監聽的端口和服務
server = make_server(pp_thrift.PingService, Dispatcher(),
'127.0.0.1', 6000)
print("serving...")
server.serve()
if __name__ == '__main__':
main()
如果我們要同時提供多個服務呢?比如PingService
和AargsPingService
。這個時候需要建立多個.thrift
文件,可以參考multiplexer 。
我們再來看看客戶端代碼怎么寫。
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()
如果一個服務比較耗時,但是我們需要同步拿到返回結果,那么怎么辦?這個時候需要注意客戶端調用超時,thriftpy
的默認超時時間是3秒,我們可以通過修改客戶端的socket_time
和connect_time
來進行設置
with client_context(pp_thrift.PingService, '127.0.0.1', 6000, socket_timeout=10 * 1000, connect_timeout=10*1000) as c:
此外,由于thriftpy
默認的server是單進程的,為了充分利用CPU資源,eleme又開源了一個多進程的server gunicorn_thrift。需要單獨通過
pip install gunicorn_thrift
此外還需要注意一點,在Python3中,只支持 多進程同步模型,也就是需要在gunicorn_config.py修改
worker_class = "thriftpy_gevent"
為worker_class = "thriftpy_sync"
。Python2中是支持協程的。