这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战
CONNECT_TIMEOUT_MILLIS
- 属于 SocketChannal 的参数
- 用在客户端建立连接时,如果在指定毫秒内无法连接,会抛出 timeout 异常
- 注意:Netty 中不要用成了SO_TIMEOUT 主要用在阻塞 IO,而 Netty 是非阻塞 IO
使用
1 | java复制代码public class TestParam { |
- 客户端通过
Bootstrap.option
函数来配置参数,配置参数作用于 SocketChannel - 服务器通过
1 | erlang复制代码ServerBootstrap. |
来配置参数,但是对于不同的 Channel 需要选择不同的方法
+ 通过 `option` 来配置 **ServerSocketChannel** 上的参数
+ 通过 `childOption` 来配置 **SocketChannel** 上的参数
源码分析
客户端中连接服务器的线程是 NIO 线程,抛出异常的是主线程。这是如何做到超时判断以及线程通信的呢?
AbstractNioChannel.AbstractNioUnsafe.connect
方法中
1 | java复制代码public final void connect( |
超时的判断主要是通过 Eventloop 的 schedule 方法和 Promise 共同实现的
- schedule 设置了一个定时任务,延迟
connectTimeoutMillis
秒后执行该方法 - 如果指定时间内没有建立连接,则会执行其中的任务
- 任务负责创建
ConnectTimeoutException
异常,并将异常通过 Pormise 传给主线程并抛出
- 任务负责创建
SO_BACKLOG
该参数是 ServerSocketChannel 的参数,在服务器端
三次握手与连接队列
第一次握手时,因为客户端与服务器之间的连接还未完全建立,与这个客户端的连接信息会被放入半连接队列中
当完成三次握手以后,连接会被放入全连接队列中
服务器处理Accept事件是在TCP三次握手,也就是建立连接之后。服务器会从全连接队列中获取连接并进行处理
在 linux 2.2 之前,backlog 大小包括了两个队列的大小,在 linux 2.2 之后,分别用下面两个参数来控制
- 半连接队列 - sync queue
- 大小通过 /proc/sys/net/ipv4/tcp_max_syn_backlog 指定,在
syncookies
启用的情况下,逻辑上没有最大值限制,这个设置便被忽略
- 大小通过 /proc/sys/net/ipv4/tcp_max_syn_backlog 指定,在
- 全连接队列 - accept queue
- 其大小通过 /proc/sys/net/core/somaxconn 指定,在使用 listen 函数时,内核会根据传入的 backlog 参数与系统参数,取二者的较小值
- 如果 accpet queue 队列满了,server 将发送一个拒绝连接的错误信息到 client
作用
在Netty中,SO_BACKLOG
主要用于设置全连接队列的大小。当处理Accept的速率小于连接建立的速率时,全连接队列中堆积的连接数大于SO_BACKLOG
设置的值是,便会抛出异常
设置方式如下
1 | scss复制代码// 设置全连接队列,大小为2 |
默认值
backlog参数在NioSocketChannel.doBind
方法被使用
1 | java复制代码@Override |
其中backlog被保存在了DefaultServerSocketChannelConfig
配置类中
1 | arduino复制代码private volatile int backlog = NetUtil.SOMAXCONN; |
具体的赋值操作如下
1 | java复制代码SOMAXCONN = AccessController.doPrivileged(new PrivilegedAction<Integer>() { |
- backlog的值会根据操作系统的不同,来
选择不同的默认值
+ Windows 200
+ Linux/Mac OS 128
- 如果配置文件
/proc/sys/net/core/somaxconn
存在,会读取配置文件中的值,并将backlog的值设置为配置文件中指定的
TCP_NODELAY
- 属于 SocketChannal 参数
- 因为 Nagle 算法,数据包会堆积到一定的数量后一起发送,这就可能导致数据的发送存在一定的延时
- 该参数默认为false,如果不希望的发送被延时,则需要将该值设置为true
SO_SNDBUF & SO_RCVBUF
- SO_SNDBUF 属于 SocketChannal 参数
- SO_RCVBUF 既可用于 SocketChannal 参数,也可以用于 ServerSocketChannal 参数(建议设置到 ServerSocketChannal 上)
- 该参数用于指定接收方与发送方的滑动窗口大小,不过不建议去调整这两个参数,也不应该过大,否则会占用操作系统的缓冲区
ALLOCATOR
- 属于 SocketChannal 参数
- 用来配置 ByteBuf 是池化还是非池化,是直接内存还是堆内存
使用
1 | scss复制代码// 选择ALLOCATOR参数,设置SocketChannel中分配的ByteBuf类型 |
ByteBufAllocator类型
- 池化并使用直接内存
1 | arduino复制代码// true表示使用直接内存 |
- 池化并使用堆内存
1 | arduino复制代码// false表示使用堆内存 |
- 非池化并使用直接内存
1 | arduino复制代码// ture表示使用直接内存 |
- 非池化并使用堆内存
1 | arduino复制代码// false表示使用堆内存 |
RCVBUF_ALLOCATOR
- 属于 SocketChannal 参数
- 控制 Netty 接收缓冲区大小
- 负责入站数据的分配,决定入站缓冲区的大小(并可动态调整),统一采用 direct 直接内存,具体池化还是非池化由 allocator 决定
本文转载自: 掘金