1
1
### Netty 笔记
2
2
3
- #### Netty对三种I/O模式的支持
3
+ #### 1. Netty对三种I/O模式的支持
4
4
5
- <img src =" https://tva1.sinaimg.cn/large/008i3skNly1gyol111yspj31aa0jggob.jpg " alt =" image-20220124110420220 " style = " zoom : 50 % ; " align =" left " />
5
+ <img src =" https://tva1.sinaimg.cn/large/008i3skNly1gyol111yspj31aa0jggob.jpg " alt =" image-20220124110420220 " width = " 700 " align =" left " />
6
6
7
7
##### Netty并不是只支持过NIO,但是不建议(depercate)阻塞I/O(BIO/OIO)
8
8
23
23
24
24
25
25
26
- #### Netty NIO 中的Reactor 开发模式
26
+ #### 2. Netty NIO 中的Reactor 开发模式
27
27
28
28
Netty 三种开发模式版本
29
29
30
- - BIO 下是 Thread-Per-Connection
30
+ BIO 下是 Thread-Per-Connection
31
31
32
- <img src =" https://tva1.sinaimg.cn/large/008i3skNly1gyolp1ody6j31fy0kggpn.jpg " alt =" image-20220124112504631 " style = " zoom : 40 % ; " algin =" left " />
32
+ <img src =" https://tva1.sinaimg.cn/large/008i3skNly1gyolp1ody6j31fy0kggpn.jpg " alt =" image-20220124112504631 " width = " 700 " align =" left " />
33
33
34
34
*** Thread-Per-Connection:对应每个连接都有1个线程处理,1个线程同时处理:读取、解码、计算、编码、发送***
35
35
36
36
37
37
38
- - NIO 下是 Reactor
38
+ NIO 下是 Reactor
39
39
40
- <img src =" https://tva1.sinaimg.cn/large/008i3skNly1gyolp5zqpaj316w0pmadn.jpg " alt =" image-20220124112753682 " style = " zoom : 40 % ; " align =" left " >
40
+ <img src =" https://tva1.sinaimg.cn/large/008i3skNly1gyolp5zqpaj316w0pmadn.jpg " alt =" image-20220124112753682 " width = " 700 " align =" left " >
41
41
42
42
*** Reactor 多线程模式,由多个线程负责:读取、发送,由线程池负责处理:解码、计算、编码***
43
43
44
44
*** Reactor 主从多线程模式,由单独mainReactor 单线程负责接收请求,subReactor和 Reactor 多线程模式一致***
45
45
46
46
47
47
48
- - AIO 下是 Proactor
48
+ AIO 下是 Proactor
49
49
50
50
Reactor 是一种开发模式,模式的核心流程:
51
51
@@ -57,41 +57,108 @@ Reactor 是一种开发模式,模式的核心流程:
57
57
58
58
- Reactor 单线程模式
59
59
60
- - ``` java
61
- // 线程数1
62
- EventLoopGroup eventGroup = new NioEventLoopGroup (1 );
63
-
64
- ServerBootStrap serverBootStrap = new ServerBootStrap ();
65
- serverBootStrap. group(eventGroup);
66
- ```
60
+ ``` java
61
+ // 线程数1
62
+ EventLoopGroup eventGroup = new NioEventLoopGroup (1 );
63
+
64
+ ServerBootStrap serverBootStrap = new ServerBootStrap ();
65
+ serverBootStrap. group(eventGroup);
66
+ ```
67
67
68
68
- Reactor 多线程模式
69
69
70
- - ```java
71
- // 多线程,不传具体的线程数时,Netty会根据CPU核心数分配
72
- EventLoopGroup eventGroup = new NioEventLoopGroup ();
73
-
74
- ServerBootStrap serverBootStrap = new ServerBootStrap ();
75
- serverBootStrap. group(serverBootStrap);
76
- ```
70
+ ``` java
71
+ // 多线程,不传具体的线程数时,Netty会根据CPU核心数分配
72
+ EventLoopGroup eventGroup = new NioEventLoopGroup ();
73
+
74
+ ServerBootStrap serverBootStrap = new ServerBootStrap ();
75
+ serverBootStrap. group(serverBootStrap);
76
+ ```
77
77
78
78
- Reactor 主从多线程模式
79
79
80
- - ```java
81
- // 主线程负责接收请求 acceptor,是单线程
82
- EventLoopGroup bossGroup = new NioEventLoopGroup ();
83
- // 从线程负责:读取、解码、计算、编码、发送,是多线程
84
- EventLoopGroup workerGroup = new NioEventLoopGroup ();
85
-
86
- SeverBootStrap serverBootStrap = new ServerBootStrap ();
87
- serverBootStrap. group(bossGroup, workerGroup);
88
- ```
80
+ ``` java
81
+ // 主线程负责接收请求 acceptor,是单线程
82
+ EventLoopGroup bossGroup = new NioEventLoopGroup ();
83
+ // 从线程负责:读取、解码、计算、编码、发送,是多线程
84
+ EventLoopGroup workerGroup = new NioEventLoopGroup ();
85
+
86
+ SeverBootStrap serverBootStrap = new ServerBootStrap ();
87
+ serverBootStrap. group(bossGroup, workerGroup);
88
+ ```
89
+
90
+
91
+
92
+ #### 3.Netty 粘包/半包解决方案
93
+
94
+ 关于半包的主要原因:
95
+
96
+ - 发送写入数据 > 套接字缓冲区大小
97
+ - 发送的数据大于协议 MTU(Maximum Transmission Unit,最大传输单元),必须拆包
98
+
99
+ <img src =" https://tva1.sinaimg.cn/large/008i3skNly1gyorpiywgrj30z00aq0ul.jpg " alt =" image-20220124144456949 " width =" 700 " align =" left " />
100
+
101
+
102
+
103
+ 关于粘包的主要原因:
104
+
105
+ - 发送方每次写入数据 > 套接字缓冲区大小
106
+ - 接收方读取套接字缓冲区不够及时
107
+
108
+
109
+
110
+ 换个角度看原因:
111
+
112
+ - 收发时:一个发送可能多次接收,多个发送可能被一次接收
113
+ - 传输时:一个发送可能占用多个传输包,多个发送可能公用一个传输包
114
+
115
+
116
+
117
+ 导致粘包/半包的根本原因:
118
+
119
+ TCP 是流式协议,消息无边界
120
+
121
+ > 提醒:UDP 像邮寄的包裹,虽然一次运输多个,但每个包裹都是 “界限”,一个一个签收,所以无粘包、半包问题
122
+
123
+
124
+
125
+ *** 解决粘包和半包的手段: 找出消息的边界***
126
+
127
+ - 方式一:*** 短连接*** (不推荐)
128
+ - 手段:TCP 连接改成短连接,一个请求一个短连接,建立连接到释放连接之间的信息即为传输信息
129
+ - 优点:简单
130
+ - 缺点:效率低下
131
+
132
+ - 方式二:*** 固定长度*** (不推荐)
133
+ - 手段:满足固定长度即可
134
+ - 优点:简单
135
+ - 缺点:浪费空间
136
+
137
+ - 方式三:*** 分隔符*** (推荐)
138
+ - 手段:用确定分隔符切割
139
+ - 优点:空间不浪费,也比较简单
140
+ - 缺点:内容本身出现分隔符时需要转义,所以需要扫描内容
141
+
142
+ - 方式四:*** 固定长度字段存个内容的长度信息*** (推荐+)
143
+ - 手段:先解析固定长度的字段获取长度,然后读取后续的内容
144
+ - 优点:精确定位用户数据,内容也不用转义
145
+ - 缺点:长度理论上是有限制,需要提前预知可能的最大长度从而定义长度占用字节数
146
+
147
+ - 方式五:*** 序列化方式*** (根据场景衡量)
148
+ - 手段:每种都不同,例如JSON 可以看{} 是否应己成对
149
+ - 优缺点:衡量实际场景,很多是对现有协议的支持
89
150
90
-
91
151
92
-
93
152
153
+ ##### Netty 粘包/半包 解决方案
94
154
155
+ - 固定长度
156
+ - 解码:FixedLengthFrameDecoder
157
+ - 分隔符
158
+ - 解码:DelimiterBasedFrameDecoder
159
+ - 固定长度存个内容长度字段
160
+ - 解码:LengthFieldBasedFrameDecoder
161
+ - 编码:LengthFieldPerpender
95
162
96
163
97
164
0 commit comments