Skip to content

Commit 55de7e2

Browse files
committed
add netty readme markdown file in springboot sample
1 parent 3567829 commit 55de7e2

File tree

1 file changed

+100
-33
lines changed

1 file changed

+100
-33
lines changed

springboot-netty-sample/README.md

+100-33
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
### Netty 笔记
22

3-
#### Netty对三种I/O模式的支持
3+
#### 1.Netty对三种I/O模式的支持
44

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" />
66

77
##### Netty并不是只支持过NIO,但是不建议(depercate)阻塞I/O(BIO/OIO)
88

@@ -23,29 +23,29 @@
2323

2424

2525

26-
#### Netty NIO 中的Reactor 开发模式
26+
#### 2.Netty NIO 中的Reactor 开发模式
2727

2828
Netty 三种开发模式版本
2929

30-
- BIO 下是 Thread-Per-Connection
30+
BIO 下是 Thread-Per-Connection
3131

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"/>
3333

3434
***Thread-Per-Connection:对应每个连接都有1个线程处理,1个线程同时处理:读取、解码、计算、编码、发送***
3535

3636

3737

38-
- NIO 下是 Reactor
38+
NIO 下是 Reactor
3939

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" >
4141

4242
***Reactor 多线程模式,由多个线程负责:读取、发送,由线程池负责处理:解码、计算、编码***
4343

4444
***Reactor 主从多线程模式,由单独mainReactor 单线程负责接收请求,subReactor和 Reactor 多线程模式一致***
4545

4646

4747

48-
- AIO 下是 Proactor
48+
AIO 下是 Proactor
4949

5050
Reactor 是一种开发模式,模式的核心流程:
5151

@@ -57,41 +57,108 @@ Reactor 是一种开发模式,模式的核心流程:
5757

5858
- Reactor 单线程模式
5959

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+
```
6767

6868
- Reactor 多线程模式
6969

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+
```
7777

7878
- Reactor 主从多线程模式
7979

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+
- 优缺点:衡量实际场景,很多是对现有协议的支持
89150

90-
91151

92-
93152

153+
##### Netty 粘包/半包 解决方案
94154

155+
- 固定长度
156+
- 解码:FixedLengthFrameDecoder
157+
- 分隔符
158+
- 解码:DelimiterBasedFrameDecoder
159+
- 固定长度存个内容长度字段
160+
- 解码:LengthFieldBasedFrameDecoder
161+
- 编码:LengthFieldPerpender
95162

96163

97164

0 commit comments

Comments
 (0)