SOFABolt 是一個(gè)輕量級(jí)、高性能、易用的遠(yuǎn)程通信框架,基于netty4.1,由螞蟻金服開(kāi)源。
重要的四個(gè)學(xué)習(xí)資料:
github:https://github.com/alipay/sofa-bolt
使用手冊(cè):https://github.com/alipay/sofa-bolt/wiki/SOFA-Bolt-Handbook
螞蟻通信框架實(shí)踐:https://mp.weixin.qq.com/s/JRsbK1Un2av9GKmJ8DK7IQ
金融級(jí)分布式架構(gòu)公眾號(hào):SOFABoltLab 組織的源碼分析文章
本文會(huì)提供一個(gè) SOFABolt 最簡(jiǎn)使用示例,之后的源碼分析都會(huì)基于該示例及其擴(kuò)展進(jìn)行。
SOFABolt 坐標(biāo):
<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>bolt</artifactId>
<version>1.5.1</version>
</dependency>
一、請(qǐng)求封裝類和響應(yīng)封裝類
所有的rpc框架都會(huì)提供這樣兩個(gè)類:統(tǒng)一封裝請(qǐng)求和響應(yīng),例如 SOFARPC 中的 SofaRequest 和 SofaResponse。
1.1、請(qǐng)求統(tǒng)一封裝類
/**
* 請(qǐng)求統(tǒng)一封裝類
* 注意:必須實(shí)現(xiàn) Serializable 接口,因?yàn)槟J(rèn)的編碼器:ProtocolCodeBasedEncoder extends MessageToByteEncoder<Serializable>,
* 只對(duì) Serializable 實(shí)現(xiàn)類進(jìn)行編碼
*/
public class MyRequest implements Serializable {
private static final long serialVersionUID = -7242884346498114969L;
private String req;
public String getReq() {
return req;
}
public void setReq(String req) {
this.req = req;
}
@Override
public String toString() {
return req;
}
}
1.2、響應(yīng)統(tǒng)一封裝類
/**
* 響應(yīng)統(tǒng)一封裝類
* 注意:必須實(shí)現(xiàn) Serializable 接口,因?yàn)槟J(rèn)的編碼器:ProtocolCodeBasedEncoder extends MessageToByteEncoder<Serializable>,
* 只對(duì) Serializable 實(shí)現(xiàn)類進(jìn)行編碼
*/
public class MyResponse implements Serializable {
private static final long serialVersionUID = -6215194863976521002L;
private String resp = "default resp from server";
public String getResp() {
return resp;
}
public void setResp(String resp) {
this.resp = resp;
}
@Override
public String toString() {
return resp;
}
}
二、用戶自定義業(yè)務(wù)邏輯處理器
/**
* 自定義的業(yè)務(wù)邏輯用戶處理器
* 注意:
* 對(duì)于所有的請(qǐng)求數(shù)據(jù)的類型,都必須有 UserProcessor 可以處理(感興趣),
* 否則將拋出 RpcServerException 異常,類似于 "RpcServerException:No user processor found for request: java.lang.String"
*/
public class MyServerUserProcessor extends SyncUserProcessor<MyRequest> {
@Override
public Object handleRequest(BizContext bizCtx, MyRequest request) throws Exception {
MyResponse response = new MyResponse();
if (request != null) {
System.out.println(request);
response.setResp("from server -> " + request.getReq());
}
return response;
}
/**
* 指定感興趣的請(qǐng)求數(shù)據(jù)類型,該 UserProcessor 只對(duì)感興趣的請(qǐng)求類型的數(shù)據(jù)進(jìn)行處理;
* 假設(shè) 除了需要處理 MyRequest 類型的數(shù)據(jù),還要處理 java.lang.String 類型,有兩種方式:
* 1、再提供一個(gè) UserProcessor 實(shí)現(xiàn)類,其 interest() 返回 java.lang.String.class.getName()
* 2、使用 MultiInterestUserProcessor 實(shí)現(xiàn)類,可以為一個(gè) UserProcessor 指定 List<String> multiInterest()
*/
@Override
public String interest() {
return MyRequest.class.getName();
}
}
三、服務(wù)端
/**
* 服務(wù)端
*/
public class MyServer {
public static boolean start() {
/**
* 創(chuàng)建 RpcServer 實(shí)例,指定監(jiān)聽(tīng) port
*/
RpcServer server = new RpcServer(8888);
/**
* 注冊(cè)業(yè)務(wù)邏輯處理器 UserProcessor
*/
server.registerUserProcessor(new MyServerUserProcessor());
/**
* 啟動(dòng)服務(wù)端:先做 netty 配置初始化操作,再做 bind 操作
* 配置 netty 參數(shù)兩種方式:[SOFABolt 源碼分析11 - Config 配置管理的設(shè)計(jì)](http://www.itdecent.cn/p/76b0be893745)
*/
return server.start();
}
public static void main(String[] args) {
if (MyServer.start()) {
System.out.println("server start success!");
} else {
System.out.println("server start fail!");
}
}
}
四、客戶端
/**
* 客戶端
*/
public class MyClient {
private static RpcClient client;
public static void start() {
// 創(chuàng)建 RpcClient 實(shí)例
client = new RpcClient();
// 初始化 netty 客戶端:此時(shí)還沒(méi)有真正的與 netty 服務(wù)端進(jìn)行連接
client.init();
}
public static void main(String[] args) throws RemotingException, InterruptedException {
MyClient.start();
// 構(gòu)造請(qǐng)求體
MyRequest request = new MyRequest();
request.setReq("hello, bolt-server");
/**
* 1、獲取或者創(chuàng)建連接(與netty服務(wù)端進(jìn)行連接),Bolt連接的創(chuàng)建是延遲到第一次調(diào)用進(jìn)行的
* 2、向服務(wù)端發(fā)起同步調(diào)用(四種調(diào)用方式中最常用的一種)
*/
MyResponse response = (MyResponse) client.invokeSync("127.0.0.1:8888", request, 30 * 1000);
System.out.println(response);
}
}
ok,完成!?。〈a很簡(jiǎn)單,服務(wù)端啟動(dòng)用了三行代碼,客戶端啟動(dòng)用了兩行代碼,調(diào)用用了一行代碼。
這個(gè)最簡(jiǎn)示例僅用于學(xué)習(xí)源碼使用,SOFABolt 在生產(chǎn)中的最佳實(shí)踐是 SOFARPC,后續(xù)在分析 SOFARPC 源碼的時(shí)候,會(huì)分析 SOFARPC 對(duì) SOFABolt 的使用姿勢(shì)。