资料参考来源拉钩Java高薪训练营
文章目录
一、Netty简介
Netty 是由 JBOSS 提供一个异步的、 基于事件驱动的网络编程框架。
Netty 可以帮助你快速、简单的开发出一个网络应用,相当于简化和流程化了 NIO 的开发过程。作为当前最流行的 NIO 框架,Netty 在互联网领域、大数据分布式计算领域、游戏行业、通信行业等获得了广泛的应用,知名的Elasticsearch 、Dubbo 框架内部都采用了Netty。
NIO缺点
- NIO 的类库和 API 繁杂,使用麻烦。你需要熟练掌握 Selector、ServerSocketChannel、SocketChannel、ByteBuffer 等.
- 可靠性不强,开发工作量和难度都非常大.
- NIO 的 Bug,例如 Epoll Bug,它会导致 Selector 空轮询,最终导致 CPU 100%.
Netty优点
- 对各种传输协议提供统一的 API
- 高度可定制的线程模型——单线程、一个或多个线程池
- 更好的吞吐量,更低的等待延迟
- 更少的资源消耗
- 最小化不必要的内存拷贝
netty模型:
Netty 抽象出两组线程池, BossGroup 专门负责接收客户端连WorkerGroup 专门负责网络读写操作。
NioEventLoop表示一个不断循环执行处理 任务的线程,每个NioEventLoop 都有一个 selector, 用于监听绑定在其上的 socket 网络通道。
NioEventLoop 内部采用串行化设计, 从消息的读取->解码->处理->编码->发送,始终由 IO线程NioEventLoop 负责。
二、Netty核心组件
1.ChannelHandler
ChannelHandler 接口定义了许多事件处理的方法, 我们可以通过重写这些方法去实现具体的业务逻辑。
我们经常需要自定义一个 Handler 类去继ChannelInboundHandlerAdapter,可以重写一下方法:
public void channelActive(ChannelHandlerContext ctx), 通道就绪事件
public void channelRead(ChannelHandlerContext ctx, Object msg), 通道读取数据事件
public void channelReadComplete(ChannelHandlerContext ctx) , 数据读取完毕事件
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause), 通道发生异常事件
2.ChannelPipeline
ChannelPipeline 是一个 Handler 的集合,它负责处理和拦截 inbound 或者 outbound 的事 件和操作,相当于一个贯穿 Netty 的链。
ChannelPipeline addFirst(ChannelHandler... handlers),把一个业务处理类(handler)添加到链中的第一个位置
ChannelPipeline addLast(ChannelHandler... handlers),把一个业务处理类(handler)添加到链中的最后一个位置
3.ChannelHandlerContext
事件处理器上下文对象,Pipeline链中的实际处理节点。每个处理节点ChannelHandlerContext中包含一个具体的事件处理器ChannelHandler,同 时ChannelHandlerContext中也绑定了对应的pipeline和Channel的信息,方便对ChannelHandler进行调用。
ChannelFuture close(),关闭通道
ChannelOutboundInvoker flush(),刷新
ChannelFuture writeAndFlush(Object msg),将数据写到ChannelPipeline中当前ChannelHandler,并且下一个ChannelHandler开始处理
4.ChannelFuture
表示Channel 中异步I/O操作的结果,在Netty中所有的I/O操作都是异步的,I/O的调用会直接返回,调用者并不能立刻获得结果,但是可以通过ChannelFuture来获取I/O操作的处理状态。
Channel channel(),返回当前正在进行IO操作的通道
ChannelFuture sync(),等待异步操作执行完毕
5.EventLoopGroup和实现类NioEventLoopGroup
EventLoopGroup是一组EventLoop的抽象,Netty为了更好的利用多核 CPU 资源,一般会有多个EventLoop同时工作,每个EventLoop维护着一个Selector实例。EventLoopGroup提供next接口,可以从组里面按照一定规则获取其中一个 EventLoop 来处理任务。在Netty服务器端编程中,我们一般都需要提供两个EventLoopGroup,例如:BossEventLoopGroup和WorkerEventLoopGroup。
public NioEventLoopGroup(),构造方法
public Future<?> shutdownGracefully(),断开连接,关闭线程
6.ServerBootstrap和Bootstrap
ServerBootstrap是Netty中的服务器端启动助手,通过它可以完成服务器端的各种配置。
Bootstrap是Netty中的客户端启动助手,通过它可以完成客户端的各种配。
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup),该方法用于服务器端,用来设置两个EventLoop
public B group(EventLoopGroup group),该方法用于客户端,用来设置一个 EventLoop
public B channel(Class<? extends C> channelClass),该方法用来设置一个服务器端的通道实现
public <T> B option(ChannelOption<T> option, T value),用来给ServerChannel 添加配置
public <T> ServerBootstrap childOption(ChannelOption<T> childOption, T value),用来给接收到的 通道添加配置
public ServerBootstrap childHandler(ChannelHandler childHandler), 该方法用来设置业务处理类(自定义的 handler)
public ChannelFuture bind(int inetPort),该方法用于服务器端,用来设置占用的端口号
public ChannelFuture connect(String inetHost, int inetPort),该方法用于客户端,用来连接服务器端
三、使用Netty开发一个简易的RPC框架
RPC全称为remote procedure call,即远程过程调用。
借助RPC可以做到像本地调用方法一样调用远程服务,是一种进程间的通信方式。在java中RPC框架比较多,常见的有Hessian、gRPC、Thrift、HSF (High Speed Service Framework)、Dubbo 等,其实对于RPC框架而言,核心模块就是通讯和序列化
这里我们使用netty来实现一个简易的RPC框架。也可以使用RMI,RMI依赖于java虚拟机,所以只支持两个JVM之间的调用。
- rpc-common 公用接口api
- rpc-frame 自定义rpc框架代码
- rcp-server 服务端
- rcp-consumer 客户端
源码地址: https://github.com/pengtw/rpc-custom