🏗️ 整体架构概览
这是一个基于 Netty 的 RPC 框架,采用了经典的客户端-服务端架构,主要包含以下几个核心模块:
📁 目录结构
bash
rpc-framework-simple/src/main/java/github/javaguide/remoting/transport/netty/
├── codec/ # 编解码器
│ ├── RpcMessageEncoder.java
│ └── RpcMessageDecoder.java
├── client/ # 客户端组件
│ ├── NettyRpcClient.java
│ ├── NettyRpcClientHandler.java
│ ├── ChannelProvider.java
│ └── UnprocessedRequests.java
└── server/ # 服务端组件
├── NettyRpcServer.java
└── NettyRpcServerHandler.java
🔧 核心组件分析
1. 协议设计
框架定义了自定义的 RPC 协议格式:
sql
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+-----+-----+-----+-----+--------+----+----+----+------+-----------+-------+----- --+-----+-----+-------+
| magic code |version | full length | messageType| codec|compress| RequestId |
+-----------------------+--------+---------------------+-----------+-----------+-----------+------------+
| body |
+-------------------------------------------------------------------------------------------------------+
- 4B magic code(魔法数)
- 1B version(版本)
- 4B full length(消息长度)
- 1B messageType(消息类型)
- 1B compress(压缩类型)
- 1B codec(序列化类型)
- 4B requestId(请求ID)
- body(消息体)
2. 数据传输对象
RpcMessage
- 传输消息包装
java:rpc-framework-simple/src/main/java/github/javaguide/remoting/dto/RpcMessage.java
public class RpcMessage {
private byte messageType; // 消息类型
private byte codec; // 序列化类型
private byte compress; // 压缩类型
private int requestId; // 请求ID
private Object data; // 消息数据
}
RpcRequest
- RPC 请求
java:rpc-framework-simple/src/main/java/github/javaguide/remoting/dto/RpcRequest.java
public class RpcRequest {
private String requestId; // 请求ID
private String interfaceName; // 接口名
private String methodName; // 方法名
private Object[] parameters; // 参数
private Class<?>[] paramTypes; // 参数类型
private String version; // 版本
private String group; // 分组
}
RpcResponse
- RPC 响应
java:rpc-framework-simple/src/main/java/github/javaguide/remoting/dto/RpcResponse.java
public class RpcResponse<T> {
private String requestId; // 请求ID
private Integer code; // 响应码
private String message; // 响应消息
private T data; // 响应数据
}
🚀 服务端架构
NettyRpcServer - 服务端启动器
java:rpc-framework-simple/src/main/java/github/javaguide/remoting/transport/netty/server/NettyRpcServer.java
public class NettyRpcServer {
public static final int PORT = 9998;
public void start() {
// 1. 创建线程组
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
DefaultEventExecutorGroup serviceHandlerGroup = new DefaultEventExecutorGroup(
RuntimeUtil.cpus() * 2,
ThreadPoolFactoryUtil.createThreadFactory("service-handler-group", false)
);
// 2. 配置服务端启动器
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childOption(ChannelOption.TCP_NODELAY, true)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.option(ChannelOption.SO_BACKLOG, 128)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
// 3. 配置处理器链
p.addLast(new IdleStateHandler(30, 0, 0, TimeUnit.SECONDS));
p.addLast(new RpcMessageEncoder());
p.addLast(new RpcMessageDecoder());
p.addLast(serviceHandlerGroup, new NettyRpcServerHandler());
}
});
}
}
NettyRpcServerHandler - 服务端消息处理器
java:rpc-framework-simple/src/main/java/github/javaguide/remoting/transport/netty/server/NettyRpcServerHandler.java
public class NettyRpcServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof RpcMessage) {
RpcMessage rpcMessage = (RpcMessage) msg;
byte messageType = rpcMessage.getMessageType();
if (messageType == RpcConstants.HEARTBEAT_REQUEST_TYPE) {
// 处理心跳请求
rpcMessage.setMessageType(RpcConstants.HEARTBEAT_RESPONSE_TYPE);
rpcMessage.setData(RpcConstants.PONG);
} else {
// 处理RPC请求
RpcRequest rpcRequest = (RpcRequest) rpcMessage.getData();
Object result = rpcRequestHandler.handle(rpcRequest);
RpcResponse<Object> rpcResponse = RpcResponse.success(result, rpcRequest.getRequestId());
rpcMessage.setData(rpcResponse);
}
ctx.writeAndFlush(rpcMessage);
}
}
}
📱 客户端架构
NettyRpcClient - 客户端连接器
java:rpc-framework-simple/src/main/java/github/javaguide/remoting/transport/netty/client/NettyRpcClient.java
public class NettyRpcClient implements RpcRequestTransport {
public NettyRpcClient() {
// 1. 初始化客户端启动器
eventLoopGroup = new NioEventLoopGroup();
bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup)
.channel(NioSocketChannel.class)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
// 2. 配置处理器链
p.addLast(new IdleStateHandler(0, 5, 0, TimeUnit.SECONDS));
p.addLast(new RpcMessageEncoder());
p.addLast(new RpcMessageDecoder());
p.addLast(new NettyRpcClientHandler());
}
});
}
@Override
public Object sendRpcRequest(RpcRequest rpcRequest) {
CompletableFuture<RpcResponse<Object>> resultFuture = new CompletableFuture<>();
// 1. 获取服务地址
InetSocketAddress inetSocketAddress = serviceDiscovery.lookupService(rpcRequest);
// 2. 获取或创建连接
Channel channel = getChannel(inetSocketAddress);
if (channel.isActive()) {
// 3. 发送请求
unprocessedRequests.put(rpcRequest.getRequestId(), resultFuture);
RpcMessage rpcMessage = RpcMessage.builder()
.data(rpcRequest)
.codec(SerializationTypeEnum.HESSIAN.getCode())
.compress(CompressTypeEnum.GZIP.getCode())
.messageType(RpcConstants.REQUEST_TYPE)
.build();
channel.writeAndFlush(rpcMessage);
}
// 4. 等待响应
return resultFuture.get();
}
}
NettyRpcClientHandler - 客户端消息处理器
java:rpc-framework-simple/src/main/java/github/javaguide/remoting/transport/netty/client/NettyRpcClientHandler.java
public class NettyRpcClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof RpcMessage) {
RpcMessage tmp = (RpcMessage) msg;
byte messageType = tmp.getMessageType();
if (messageType == RpcConstants.HEARTBEAT_RESPONSE_TYPE) {
// 处理心跳响应
log.info("heart [{}]", tmp.getData());
} else if (messageType == RpcConstants.RESPONSE_TYPE) {
// 处理RPC响应
RpcResponse<Object> rpcResponse = (RpcResponse<Object>) tmp.getData();
unprocessedRequests.complete(rpcResponse);
}
}
}
}
🔄 完整调用链路
🔄 完整调用链路
客户端发起请求流程:
-
请求发起
scssRpcClientProxy.invoke() → NettyRpcClient.sendRpcRequest()
-
服务发现
scssServiceDiscovery.lookupService() → 获取服务地址
-
连接管理
scssChannelProvider.get() → 获取或创建连接 NettyRpcClient.doConnect() → 建立新连接(如需要)
-
请求发送
scss构建 RpcMessage → UnprocessedRequests.put() → 注册待处理请求 → Channel.writeAndFlush() → 发送到网络
-
编码过程
scssRpcMessage → RpcMessageEncoder.encode() → ByteBuf
服务端处理流程:
-
消息接收
Netty EventLoop → ChannelPipeline
-
解码过程
scssByteBuf → RpcMessageDecoder.decode() → RpcMessage
-
业务处理
scssNettyRpcServerHandler.channelRead() → RpcRequestHandler.handle() → ServiceProvider.getService() → 获取服务实例 → Method.invoke() → 反射调用目标方法
-
响应发送
scss构建 RpcResponse → 包装为 RpcMessage → RpcMessageEncoder.encode() → Channel.writeAndFlush()
客户端接收响应:
-
响应接收
Netty EventLoop → ChannelPipeline
-
解码响应
scssByteBuf → RpcMessageDecoder.decode() → RpcMessage
-
完成请求
scssNettyRpcClientHandler.channelRead() → UnprocessedRequests.complete() → CompletableFuture.complete() → 返回结果给调用方
🛠️ 关键特性
1. 连接管理
ChannelProvider
:管理客户端到服务端的连接池- 连接复用:相同地址复用已建立的连接
- 连接检测:自动检测连接状态,失效时重新建立
2. 异步处理
UnprocessedRequests
:管理未完成的请求CompletableFuture
:实现异步请求-响应匹配- 通过
requestId
关联请求和响应
3. 心跳机制
- 客户端:5秒无写操作时发送心跳
- 服务端:30秒无读操作时关闭连接
- 保证连接活性,及时清理死连接
4. 线程模型
- Boss线程组:处理连接接受
- Worker线程组:处理I/O操作
- 业务线程组:处理具体的RPC调用(避免阻塞I/O线程)
5. 编解码
- 自定义协议格式
- 支持多种序列化方式(Hessian、Protostuff等)
- 支持压缩(GZIP)
- 基于
LengthFieldBasedFrameDecoder
解决粘包拆包
这个框架设计简洁而完整,很好地展示了如何使用 Netty 构建一个高性能的 RPC 框架。通过分层设计、异步处理和连接复用等技术,实现了高效的远程服务调用能力。