Netty源码分析-服务器端启动流程
参考文献
黑马Netty
环境
基于Netty4.1.92.Final-SNAPSHOT
启动流程
Netty中启动流程大致处理步骤
12345678910111213141516171819202122//1 netty 中使用 NioEventLoopGroup (简称 nio boss 线程)来封装线程和 selectorSelector selector = Selector.open(); //2 创建 NioServerSocketChannel,同时会初始化它关联的 handler,以及为原生 ssc 存储 configNioServerSocketChannel attachment = new NioServerSocketChannel();//3 创建 NioServerSocketChannel 时,创建了 java 原生的 ServerSocketChannelServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.confi ...
Netty-Handler&Pipeline
参考文献
ChannelPipline
每一个新创建的Channel都将会被分配一个新的ChannelPipeline.这项关联是永久性的;Channel 既不能附加另外一个ChannelPipeline,也不能分离其当前的.在 Netty 组件的生命周期中,这是一项固定的操作,不需要开发人员的任何干预.
ChannelPipeline可以看作ChannelHandler的容器载体,它是由一组ChannelHandler实例组成的,内部通过双向链表将不同的ChannelHandler链接在一起.ChannelPipeline 的双向链表分别维护了HeadContext 和 TailContext 的头尾节点。我们自定义的ChannelHandler会插入到Head和Tail 之间.
保存 ChannelHandler的List,用于处理或拦截Channel的入站事件和出站操作**,它们的执行顺序是由它们被添加的顺序所决定的**.
ChannelPipeline 实现了一种高级形式的拦截过滤器模式,使用户可以完全控制事件的处理方式,以及 Channel中各个的 Chann ...
Netty-Future&Promise
参考文献
Future & Promise
在异步处理时,经常用到这两个接口
首先要说明Netty中的Future与JDK中的Future同名,但是是两个接口,Netty的Future继承自JDK的Future,而Promise又对NettyFuture进行了扩展
JDKFuture只能同步等待任务结束(或成功、或失败)才能得到结果
NettyFuture可以同步等待任务结束得到结果,也可以异步方式得到结果,但都是要等任务结束
NettyPromise不仅有nettyFuture的功能,而且脱离了任务独立存在,只作为两个线程间传递结果的容器
功能/名称
JDK Future
Netty Future
Promise
cancel
取消任务
-
-
isCanceled
任务是否取消
-
-
isDone
任务是否完成,不能区分成功失败
-
-
get
获取任务结果,阻塞等待
-
-
getNow
-
获取任务结果,非阻塞,还未产生结果时返回 null
-
await
-
等待任务结束,如果任务失败,不会抛异常,而是通 ...
Netty-Channel
参考文献
Channel
与Socket类似
Netty 网络通信的组件,能够用于执行网络 I/O 操作.Channel 为用户提供
当前网络连接的通道的状态(例如是否打开?是否已连接?
网络连接的配置参数 (例如接收缓冲区大小)
提供异步的网络 I/O 操作(如建立连接,读写,绑定端口),异步调用意味着任何 I/O 调用都将立即返回,并且不保证在调用结束时所请求的 I/O 操作已完成.
调用立即返回一个 ChannelFuture 实例,通过注册监听器到 ChannelFuture 上,可以 I/O 操作成功、失败或取消时回调通知调用方.
支持关联 I/O 操作与对应的处理程序.
不同协议、不同的阻塞类型的连接都有不同的 Channel 类型与之对应,下面是一些常用的 Channel 类型:
NioSocketChannel: 异步的客户端 TCP Socket 连接.
NioServerSocketChannel: 异步的服务器端 TCP Socket 连接.
NioDatagramChannel: 异步的 UDP 连接.
NioSctpChannel: 异步的客 ...
Netty-EventLoop
参考文献
如何解决 Netty Channel.isWritable 返回 false
Netty Best Practices
Channel、EventLoop和 EventLoopGroup
一个EventLoopGroup包含一个或者多个EventLoop;
一个EventLoop在它的生命周期内只和一个Thread绑定;
所有由EventLoop处理的I/O 事件都将在它专有的Thread上被处理;
一个Channel在它的生命周期内只注册于一个EventLoop;
一个EventLoop可能会被分配给一个或多个Channel.
EventLoop事件循环对象
EventLoop是一种事件等待和处理的程序模型,可以解决多线程资源消耗高的问题.
EventLoop通用运行模式为,当事件发生时,应用程序都会将产生的事件放入事件队列中,然后EventLoop会轮询从队列中取出事件执行或者将事件分发给相应的事件监听者执行.事件执行的方式通常分为立即执行,延后执行,定期执行.
EventLoop本质是一个单线程执行器(同时维护了一个Selector),里面有run方 ...
Netty-ByteBuf
参考文献
https://netty.io/4.1/api/index.html
ByteBuffer
12345678910+--------------------------------------------------------------------------------+| ByteBuffer |+-------------------+-----------------------------------+-------+----------------+| | 可读区 (readable) | | |+--------+----------+-----------------------------------+-------+-------+--------+| | | [数据, 数据, 数据, 数 ...
Netty(四)-线程模型
参考文献
Scalable IO in Java --Doug Lea
线程模型
基本的线程池化模式可以描述为
从池的空闲线程列表中选择一个Thread,并且指派它去运行一个已提交的任务(一个Runnable的实现);
当任务完成时,将该Thread返回给该列表,使其可被重用。
Reactor线程模式
Reactor线程模式是一种基于事件驱动的编程模式.
它将事件的处理分解为两个基本操作:事件的分发和事件的处理.
Reactor模式通常包括以下角色:
Reactor:Reactor是整个模式的核心,它负责监听和分发事件,将事件分发给相应的处理器进行处理.Reactor通常使用事件循环来轮询事件队列,将事件分发给相应的处理器.
Handler:Handler是事件处理器,负责处理具体的事件.当Reactor将事件分发给Handler时,Handler会执行相应的业务逻辑,并将处理结果返回给Reactor.
Acceptor :Acceptor 是连接处理器,负责处理新的连接请求.当有新的连接请求到来时,Acceptor 会创建一个新的连接,并将其注册 ...
Netty-实现基于WebSocket+Protobuf的消息推送系统
参考文献
项目结构
该项目主要分两个部分message-server和message-client
message-client: 基于Netty实现的WebSocket客户端,具有与message-server交互的功能.
message-server: 基于SpringBoot结合Netty实现的WebSocket服务端.
核心代码
消息格式定义
12345678910111213141516171819202122232425262728syntax = "proto3";package protocol;option optimize_for = SPEED;option java_package = "cn.holelin.messagepushnetty.protocol";option java_outer_classname = "MessageProtocol";// 消息格式message MessageProto{ // 消息的唯一Id可以用 UUID 表示 string mes ...
Netty(二)-Netty粘包半包
参考文献
粘包现象
粘包现象指的是发送方在一次发送中,将多个数据包粘在一起发送,接收方在接收数据时可能会将多个数据包看作一个数据包进行处理,导致数据解析错误的情况.这种现象通常出现在TCP协议中,由于TCP是面向流的协议,它会将应用层传递的数据流拆分成多个数据包进行传输,而接收方并不知道这些数据包的边界,因此可能会将多个数据包看作一个数据包进行处理.
发送 abc def,接收 abcdef
粘包产生的原因
应用层缓冲区:接收方 ByteBuf 设置太大(Netty 默认 1024),即数据包大小小于应用层缓冲区,多个数据包黏在一起.
滑动窗口:假设发送方 256 bytes 表示一个完整报文,但由于接收方处理不及时且窗口大小足够大,这 256 bytes 字节就会缓冲在接收方的滑动窗口中,当滑动窗口中缓冲了多个报文就会粘包
Nagle 算法:会造成粘包
发送方发送速率过快:如果发送方发送数据的速率过快,接收方可能无法及时处理所有的数据包,就会导致多个数据包被合并成一个数据包发送,从而产生粘包现象.
网络拥塞:如果网络拥塞,数据包的传输可能会受到阻碍,TCP协议为了减少网络传输的 ...
Netty-Netty编解码
参考文献
Netty实战
黑马Netty
什么是编解码器
每个网络应用程序都必须定义如何解析在两个节点之间来回传输的原始字节,以及如何将其和目标应用程序的数据格式做相互转换.这种转换逻辑由编解码器处理,编解码器由编码器和解码器组成,它们每种都可以将字节流从一种格式转换为另一种格式.
如果将消息看作是对于特定的应用程序具有具体含义的结构化的字节序列—它的数据.那么编码器是将消息转换为适合于传输的格式(最有可能的就是字节流);而对应的解码器则是将网络字节流转换回应用程序的消息格式.因此,编码器操作出站数据,而解码器处理入站数据
Netty编码器
Netty提供的编码器:
MessageToByteEncoder: 将指定类型的Java对象转换为ByteBuf对象,常用于自定义协议的编码.
ByteToMessageEncoder: 将ByteBuf对象转换为指定类型的Java对象,常用于自定义协议的解码.
MessageToMessageEncoder: 将一种类型的Java对象编码为另一种类型的Java对象,常用于协议转换或数据转换的场景
比较推荐的做法是使用 ...