从零实现一个RPC框架(一)
仿照Dubbo,自己实现一个RPC框架。
文章中只包含部分示例代码,完全代码请移步我的github:
RPC框架的github地址
架构
工作流程
- 服务端将服务注册到注册中心并且在服务端监听客户端请求。
- 客户端在消费中心拿到服务,远程调用服务(发送一个request给服务端)。
- 服务端根据request,调用对应的服务并将结果返回给客户端。
- 客户端接收response,结束调用。
技术选型
Netty + kryo + zookeeper
Netty:网络应用框架,使用它来进行网络传输。
kryo:序列化/反序列化工具。
zookeeper:做注册中心。
项目骨架
一、先搭Netty客户端和服务端
服务端:
public class NettyServer implements InitializingBean {
private final KryoSerializer kryoSerializer = new KryoSerializer();
public static final int PORT = 9998;
private final ServiceProvider serviceProvider = SingletonFactory.getInstance(ServiceProviderImpl.class);
public void registerService(Object service, RpcServiceProperties rpcServiceProperties) {
serviceProvider.publishService(service, rpcServiceProperties);
}
@SneakyThrows
public void start() {
String host = InetAddress.getLocalHost().getHostAddress();
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
// 不启用 Nagle 算法
.childOption(ChannelOption.TCP_NODELAY, true)
// 开启 TCP 底层心跳机制
.childOption(ChannelOption.SO_KEEPALIVE, true)
.option(ChannelOption.SO_BACKLOG, 128)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
// 添加netty心跳检测机制,30秒读
ch.pipeline().addLast(new IdleStateHandler(30, 0, 0, TimeUnit.SECONDS));
// todo 编、解码器 和 真正处理业务逻辑的Handler
}
});
ChannelFuture channelFuture = b.bind(host, PORT).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
log.error("occur exception when start server:", e);
} finally {
log.error("shutdown bossGroup and workerGroup");
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
客户端:
public class NettyClient {
private final KryoSerializer kryoSerializer = new KryoSerializer();
private final EventLoopGroup eventLoopGroup;
private final Bootstrap bootstrap;
public NettyClient() {
eventLoopGroup = new NioEventLoopGroup();
bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup)
.channel(NioSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
// 添加netty心跳检测机制,5秒写
ch.pipeline().addLast(new IdleStateHandler(0, 5, 0, TimeUnit.SECONDS));
// todo 编、解码器 和 真正处理业务逻辑的Handler
}
});
}
/**
* 连接成功后返回 channel
*
* @param inetSocketAddress 服务端地址
* @return channel
*/
@SneakyThrows
public Channel doConnect(InetSocketAddress inetSocketAddress) {
ChannelFuture channelFuture = bootstrap.connect(inetSocketAddress).sync();
return channelFuture.channel();
}