如何构建一个简单的RPC调用
1、什么叫RPC?

RPC构成
- RPC Consumer
- RPC Provider
- ConfigServer
- 1、
Provider启动ConfigServer注册服务 - 2、
Consumer启动ConfigServer订阅服务, - 3、发起调用
Consumer—>Provider - 4、响应调用
Consumer<—Provider
2、什么是 Netty ? https://netty.io/

3、现有的开源的项目是否使用了 Netty ?
- Dubbo
- Grpc
- Spark
- ….
4、RPC Provider 启动
Netty Server方式启动Rpc服务的注册
5、RPC Consumer 启动
Netty Client方式启动RPC泛化调用、通过字节码基于反射来实现远程调度Consumer服务订阅- 启动时建立长连接

6、从第四可以看出,多个 Provider 是由一个 NettyServer 提供的,通过 HandlerMap 映射找到对应的 Ioc Bean,完成服务调用
服务端
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new RpcEncoder(RpcRequest.class));
p.addLast(new RpcDecoder(RpcResponse.class));
p.addLast(new RpcHandler());
}});
// Start the server.
ChannelFuture f = b.bind(PORT).sync();
// Wait until the server socket is closed.
f.channel().closeFuture().sync();
} finally {
// Shut down all event loops to terminate all threads.
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}


BossGroup-> 处理客户端的请求EventGroup—> 处理IORead/Write操作、执行任务系统Task、定时任务ChildChannelHandler方式是对ChannelPipeline的设置、ChannelPipeline是相当于任务链的模式, 是一串ChannelHandler的实例ChannelHandlerContext是ChannelPipeline和ChannelHandler的关系- 每个链接对于
Sever端都会创建一个Channel,可以将Channel理解为Connection(其实真正的是Connection属于Channel的一部分) - 每个
Channel都有一个自己的唯一的ChannelPipeline操作,对于其他的Channel的ChannelPipeline是隔离的 RPC Handler是我们对于自己的找寻RPC服务处理的Handler实现RPC Encoder是我们对于自己的找寻RPC序列化的编码的Handler实现RPC Decoder是我们对于自己的找寻RPC序列化的解码的Handler实现
客户端
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new RpcEncoder(RpcResponse.class));
p.addLast(new RpcDecoder(RpcRequest.class));
p.addLast(new RpcClientHandler());
}});
// Start the client.
ChannelFuture f = b.connect(HOST, PORT).sync();
// Wait until the connection is closed.
f.channel().closeFuture().sync();
} finally {
// Shut down the event loop to terminate all threads.
group.shutdownGracefully();
}
7、RPC 序列化
- 二进制数据
- Hessian
- Avro
- ProtoBuffer (Protobuf)
- JSON
- XML
8、关于 RPC 的实现思考与技术讨论
- 业务方法、因为是收到请求消息而触发的后续动作调用,不做额外设置,肯定是使用的
WorkGroup里面的线程操作的。 而作为业务层,不应该与底层关联,应该切割开来,势必会引入真的业务侧线程池。 那么如何引用、怎么引用?(关于 业务线程池 与WorkGroup的EvenLoop的思考 ) - 关于
RPC调用大部分是同步的调用,而Netty底层是完全异步事件机制,在RPC框架层面如何实现同步的调用方式的? - 基于
TCP的长链接调用,在RPC上你会想到其他的哪些东东? - 在此环境下,我没有介绍
RPC服务于 IOC容器的结合,可以思考一下,如何做到 注解机制、JAVA CONFIG机制、XML SCHEMA机制来做?- GUICE
- SPRING
- SPI
- ….