简介
sofa-bolt是蚂蚁开源的一款基于Netty的网络通信框架。在Netty的基础上对网络编程常见问题进行了一层简单封装,让中间件开发者更关注于中间件产品本身。
Demo 关键代码
Pom依赖:
<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>bolt</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>hessian</artifactId>
<version>3.3.6</version>
</dependency>
BoltServer端:
public class MyServer {
public static boolean start() {
/**
* 创建 RpcServer 实例,指定监听 port
*/
RpcServer server = new RpcServer(8888);
/**
* 注册业务逻辑处理器 UserProcessor
*/
server.registerUserProcessor(new MyServerUserProcessor());
/**
* 启动服务端:先做 netty 配置初始化操作,再做 bind 操作
* 配置 netty 参数两种方式:[SOFABolt 源码分析11 - Config 配置管理的设计](https://www.jianshu.com/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!");
}
}
}
/**
* 自定义的业务逻辑用户处理器
* 注意:
* 对于所有的请求数据的类型,都必须有 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("recive request"+request);
response.setResp("from server -> " + request.getReq());
}
return response;
}
/**
* 指定感兴趣的请求数据类型,该 UserProcessor 只对感兴趣的请求类型的数据进行处理;
* 假设 除了需要处理 MyRequest 类型的数据,还要处理 java.lang.String 类型,有两种方式:
* 1、再提供一个 UserProcessor 实现类,其 interest() 返回 java.lang.String.class.getName()
* 2、使用 MultiInterestUserProcessor 实现类,可以为一个 UserProcessor 指定 List<String> multiInterest()
*/
@Override
public String interest() {
return MyRequest.class.getName();
}
}
/**
* 响应统一封装类
* 注意:必须实现 Serializable 接口,因为默认的编码器:ProtocolCodeBasedEncoder extends MessageToByteEncoder<Serializable>,
* 只对 Serializable 实现类进行编码
*/
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;
}
}
BoltClient端:
/**
* 客户端
*/
public class MyClient {
private static RpcClient client;
public static void start() {
// 创建 RpcClient 实例
client = new RpcClient();
// 初始化 netty 客户端:此时还没有真正的与 netty 服务端进行连接
client.init();
}
public static void main(String[] args) throws RemotingException, InterruptedException {
MyClient.start();
// 构造请求体
MyRequest request = new MyRequest();
request.setReq("Hello, bolt-server");
/**
* 1、获取或者创建连接(与netty服务端进行连接),Bolt连接的创建是延迟到第一次调用进行的
* 2、向服务端发起同步调用(四种调用方式中最常用的一种)
*/
MyResponse response = (MyResponse) client.invokeSync("127.0.0.1:8888", request, 30 * 1000);
System.out.println(response);
}
}
/**
* 请求统一封装类
* 注意:必须实现 Serializable 接口,因为默认的编码器:ProtocolCodeBasedEncoder extends MessageToByteEncoder<Serializable>,
* 只对 Serializable 实现类进行编码
*/
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;
}
}
与远程服务对接后效果图:
![在这里插入图片描述 在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200514090903270.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1lhbmdDaGVuZXk=,size_16,color_FFFFFF,t_70&x-oss-process=image/resize,w_1400/format,webp)
在服务端SOFAJraft 崩溃情况下,确保客户端对其异常处理!
![在这里插入图片描述 在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200514091059312.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1lhbmdDaGVuZXk=,size_16,color_FFFFFF,t_70&x-oss-process=image/resize,w_1400/format,webp)
参考资料
- GitHub:sofa-bolt源码库
- 简书:SOFABolt 源码分析系列
- sofa-bolt中文文档
- 简书:sofa-bolt学习