在微服務架構盛行的今天,RPC 框架早已不是新鮮事物。Dubbo、gRPC、Spring Cloud 等成熟方案琳瑯滿目,但並非所有場景都需要重型武器。本文分享一個基於 Apache Thrift 自研的輕量級 Java RPC 框架 —— java-rpc-thrift,它專為中小型集群(50 節點以內)設計,追求極致簡單、高性能、低依賴,適合不想引入 Zookeeper 等重組件、又想擺脫 HTTP/REST 性能瓶頸的團隊。
故事始於一次系統模塊拆分:原有單體應用需抽離服務,尋找遠程調用方案時發現兩難:
核心需求很明確:簡單、依賴少、高性能、高並發、支持集群/負載均衡/容錯、零學習成本、源碼可定制。既然市面上沒有完美契合的,那就自己寫一個。
框架在 Client 端為服務接口生成動態代理,方法調用自動轉為遠程請求:參數經 Kryo 序列化 → Thrift 協議傳輸 → Server 端反序列化執行業務邏輯 → 結果原路返回。對業務代碼完全透明,體驗如同本地調用。
| 組件 | 選型 | 理由 |
|---|---|---|
| 網絡層 | Apache Thrift | 利用其成熟的 Server 模型(ThreadPool/ThreadedSelector)支撐高並發低延遲;代碼極輕量,僅是 Socket 封裝,性能接近原生 Socket,比 Netty 更適合同步 RPC 調用 |
| 序列化 | Kryo | 序列化體積小、速度極快,可換裝其他實現 |
| 連接池 | Commons Pool | 成熟穩定,支援最大/最小閒置、等待超時、存活時間等精細控制 |
| 配置管理 | Spring Beans | 複用 Spring 容器生命周期,XML 配置直觀 |
kill PID(非 -9)觸發關閉鉤子,等待進行中請求完成<bean id="servicePublisher" class="com.appchina.rpc.thrift.remote.base.ThriftServicePublisher">
<property name="definitions">
<array>
<bean class="com.appchina.rpc.remote.ServiceDefinition">
<property name="serviceName" value="addServiceImpl"/>
<property name="interfaceClass" value="com.appchina.rpc.test.api.AddService"/>
<property name="implInstance">
<bean class="com.appchina.rpc.test.impl.AddServiceImpl"/>
</property>
</bean>
</array>
</property>
</bean>
<bean class="com.appchina.rpc.thrift.server.ThriftThreadPoolServer">
<property name="processor" ref="servicePublisher"/>
<property name="port" value="9090"/>
<property name="minWorkerThreads" value="100"/>
<property name="workerThreads" value="500"/>
<property name="security" value="true"/>
<property name="stopTimeoutVal" value="3000"/>
<property name="clientTimeout" value="10000"/>
<property name="allowedFromTokens">
<map>
<entry key="DONGJIAN" value="DSIksduiKIOYUIOkYIOhIOUIOhjklYUI"/>
</map>
</property>
</bean>
啟動類僅需加載 Spring 上下文並註冊關閉鉤子:
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("/application-server.xml");
ctx.registerShutdownHook();
ctx.start();
<bean id="factoryProvider" class="com.appchina.rpc.thrift.cluster.ThriftClientFactoryProvider">
<property name="hostPorts">
<list>
<value>127.0.0.1:9090</value>
<value>127.0.0.1:9191</value>
</list>
</property>
<property name="timeout" value="60000"/>
<property name="connectionTimeout" value="10000"/>
<property name="framed" value="false"/>
<property name="from" value="DONGJIAN"/>
<property name="token" value="DSIksduiKIOYUIOkYIOhIOUIOhjklYUI"/>
</bean>
<bean id="client" class="com.appchina.rpc.base.cluster.client.DistributeClient">
<property name="factoryProvider" ref="factoryProvider"/>
<property name="loadBalance">
<bean class="com.appchina.rpc.base.cluster.RoundrobinLoadBalance"/>
</property>
<property name="heartbeat" value="1000"/>
<property name="maxHeartbeatThread" value="1"/>
<property name="retry" value="3"/>
<property name="maxActive" value="300"/>
<property name="maxIdle" value="200"/>
<property name="minIdle" value="5"/>
<property name="maxWait" value="1000"/>
<property name="maxKeepMillis" value="-1"/>
<property name="maxSendCount" value="-1"/>
</bean>
<bean id="addService" class="com.appchina.rpc.thrift.remote.base.ThriftRemoteProxyFactory">
<property name="serviceName" value="addService"/>
<property name="proxyInterface" value="com.appchina.rpc.test.api.AddService"/>
<property name="client" ref="client"/>
</bean>
業務調用極簡:
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("/application-client.xml");
AddService addService = (AddService) ctx.getBean("addService");
addService.add(100); // 透明遠程調用
🔗 GitHub:https://github.com/dongjian1029/java-rpc-thrift.git
適用場景:節點數 < 50、追求極致輕量、團隊有能力維護源碼、不需要服務治理儀表盤。
不適用場景:大規模集群、需服務發現/熔斷/鏈路追蹤、團隊偏好開箱即用成熟框架(請直接用 Dubbo)。
造輪子不是為了炫技,而是為了在特定約束下找到最優解。java-rpc-thrift 證明了:拒絕過度設計,專注核心價值,小而美同樣有力量。若你正為 RPC 選型糾結,不妨克隆源碼跑通 Demo,或許它就是你要的那把「輕劍」。