small-rpc 框架(七)-服务端消息处理
@Slf4j
public class NettyRpcServer {
//用这种方式会阻塞 spring 容器初始化
// @PostConstruct
public void start() {
String host = serverConfig.getHost();
int port = serverConfig.getPort();
try {
boss = new NioEventLoopGroup(1);
worker = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(boss, worker).channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
//编解码器
ChannelPipeline pipeline = ch.pipeline();
//自定义
//lengthFieldOffset=8+1+1+1
//lengthFieldLength=4(data.length)
//lengthAdjustment=1(padding)
//initialBytesToStrip=0,完整数据,字段自己都解析,不需要丢弃
pipeline.addLast(new IdleStateHandler(30, 0, 0, TimeUnit.SECONDS));
pipeline.addLast(new LengthFieldBasedFrameDecoder(65535, 11, 4, 1, 0));
pipeline.addLast(new RpcMessageCodec());
//消息接收处理
pipeline.addLast(new ServerHandler(requestProcessor));
}
});
channelFuture = bootstrap.bind(host, port).sync();
channelFuture.addListener((ChannelFutureListener) future -> {
if (future.isSuccess()) {
log.info("server start at: {}:{}", host, port);
//启动成功,实例注册-服务名注册
serviceRegistry.register(serverConfig.getAppName(), new InetSocketAddress(host, port));
}
});
} catch (Exception e) {
log.error("server start error:{}:{}", host, port, e);
}
}
}
在服务端netty启动时,我们新增了 ServerHandler 处理来自客户端的请求
ServerHandler
@Slf4j
public class ServerHandler extends SimpleChannelInboundHandler<RpcMessage> {
private RequestProcessor requestProcessor;
public ServerHandler( RequestProcessor requestProcessor) {
this.requestProcessor = requestProcessor;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, RpcMessage msg) throws Exception {
RpcRequest request = (RpcRequest) msg.getData();
try {
Object result = requestProcessor.invoke(request);
RpcResponse<Object> response = RpcResponse.success(result, request.getRequestId());
log.info("ServerHandler handler response: {}-{}", request.getRequestId(),JSON.toJSONString(response));
ctx.writeAndFlush(RpcMessage.buildResponse(response,msg)).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
} catch (Exception e) {
log.error("ServerHandler handler request error: {}", JSON.toJSONString(msg), e);
RpcResponse<Object> response = RpcResponse.failed("rpc处理失败", request.getRequestId());
ctx.writeAndFlush(RpcMessage.buildResponse(response, msg)).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
log.error("ServerHandler exceptionCaught", cause);
ctx.close();
}
}
RequestProcessor
@Slf4j
public class RequestProcessor {
private ServiceProviderRegistry serviceProviderRegistry;
public RequestProcessor(ServiceProviderRegistry serviceProviderRegistry) {
this.serviceProviderRegistry = serviceProviderRegistry;
}
/**
* 处理RPC请求
* @param request
* @return
*/
public Object invoke(RpcRequest request){
try {
Object handler = serviceProviderRegistry.getService(request.getInterfaces());
Method method = handler.getClass().getMethod(request.getMethod(), request.getParameterTypes());
return method.invoke(handler, request.getArgs());
} catch (Exception e) {
log.error("handle request error: {}", JSON.toJSONString(request), e);
throw new RuntimeException(e);
}
}
}
交给 ServiceProviderRegistry 根据接口名称查询对应的 handler, 然后用反射进行方法执行