Thrift 不只是序列化庫,而是一個完整的跨語言 RPC 框架體系:IDL 定義 → 代碼生成 → 協議/傳輸/Server 多維度可插拔。本文系統梳理 Thrift 堆棧架構、數據類型、Server 選型基準、雙向通信實現,並提供從零構建 Java Server/Client 的完整步驟。
TSocket/TServerSocket (阻塞)、TFramedTransport (幂緩衝)、THttpClient、TSSL...TBinaryProtocol (默認)、TCompactProtocol (高效)、TJSONProtocol、TDebugProtocolTProcessor 解析調用 → 調用用戶 Handler → 序列化響應TSimpleServer、TNonblockingServer、THsHaServer、TThreadedSelectorServer、TThreadPoolServernamespace java com.example
struct User { 1: i32 id; 2: string name; 3: i16 age = 18; }
service UserService {
User getUser(1: i32 id)
void saveUser(1: User user) (1: string errMsg) // throws
oneway void notify(1: string msg) // 單向無響應
}
required/optional 控制序列化行為list<t>, set<t>, map<k,v>extends),不支援重載| Server | I/O 模型 | 線程模型 | 適用場景 | 不推薦場景 |
|---|---|---|---|---|
| TSimpleServer | 阻塞 | 單線程循環 | 單元測試、極低併發 | 任何生產環境 |
| TNonblockingServer | 非阻塞 (Selector) | 單線程處理 I/O + 業務 | 低業務耗時、中等併發 | 高業務耗時 (業務阻塞 Selector) |
| THsHaServer | 非阻塞 | 1 I/O 線程 + Worker 線程池 | **大多數生產場景推薦** | 極高併發連接數 (I/O 線程成瓶頸) |
| TThreadedSelectorServer | 非阻塞 | 多 Selector 線程 + Worker 池 | 超高併發、I/O 密集型 | 配置複雜、資源消耗大 |
| TThreadPoolServer | 阻塞 | 每連接一線程 (池化) | 併發連接數可控、業務阻塞多 | 萬級連接 (線程數爆炸) |
選型口訣:不確定選 THsHaServer;I/O 瓶頸上 TThreadedSelectorServer;業務阻塞重、連接數可控 → TThreadPoolServer。
TestQry.thriftnamespace java com.thrift
struct QryResult { 1: i32 code; 2: string msg; }
service TestQry { QryResult qryTest(1: i32 qryCode) }
thrift-0.9.2.exe -r -gen java TestQry.thrift
public class QueryImp implements TestQry.Iface {
public QryResult qryTest(int qryCode) {
QryResult r = new QryResult();
r.code = (qryCode == 1) ? 1 : 0;
r.msg = (qryCode == 1) ? "success" : "fail";
return r;
}
}
public class ThriftServerDemo {
public static void main(String[] args) throws TTransportException {
TNonblockingServerSocket socket = new TNonblockingServerSocket(30001);
TestQry.Processor processor = new TestQry.Processor(new QueryImp());
TNonblockingServer.Args sArgs = new TNonblockingServer.Args(socket)
.protocolFactory(new TBinaryProtocol.Factory())
.transportFactory(new TFramedTransport.Factory())
.processorFactory(new TProcessorFactory(processor));
new TNonblockingServer(sArgs).serve();
}
}
public class ThriftClientDemo {
public static void main(String[] args) throws Exception {
TTransport transport = new TFramedTransport(new TSocket("127.0.0.1", 30001, 5000));
transport.open();
TestQry.Client client = new TestQry.Client(new TBinaryProtocol(transport));
QryResult r = client.qryTest(1);
System.out.println("code=" + r.code + " msg=" + r.msg);
}
}
oneway 方法讓客戶端發送後立即返回,騰出連接TTransport 引用,創建 Client 反向調用Processor.process() 循環接收反向請求namespace、異常碼、分頁參數規範TFramedTransport + TCompactProtocol (或 Binary)