我是靠谱客的博主 陶醉小甜瓜,最近开发中收集的这篇文章主要介绍Netty 参数调优一、CONNECT_TIMEOUT_MILLIS二、SO_BACKLOG三、TCP_NODELAY四、SO_SNDBUF & SO_RCVBUF五、ALLOCATOR六、RCVBUF_ALLOCATOR,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
文章目录
- 一、CONNECT_TIMEOUT_MILLIS
- 二、SO_BACKLOG
- 三、TCP_NODELAY
- 四、SO_SNDBUF & SO_RCVBUF
- 五、ALLOCATOR
- 六、RCVBUF_ALLOCATOR
一、CONNECT_TIMEOUT_MILLIS
- 属于 SocketChannal 的参数
- 用在客户端建立连接时,如果在指定毫秒内无法连接,会抛出 timeout 异常
- 注意:Netty 中不要用成了SO_TIMEOUT 主要用在阻塞 IO,而 Netty 是非阻塞 IO
示例
public class TimeOutTest {
public static void main(String[] args) {
NioEventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap()
.group(group)
.channel(NioSocketChannel.class)
// 一秒内没建立连接就抛出异常
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000)
.handler(new LoggingHandler());
ChannelFuture channelFuture = bootstrap.connect(new InetSocketAddress("localhost", 8080)).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
group.shutdownGracefully();
}
}
}
- 客户端通过 Bootstrap.option 函数来配置参数,配置参数作用于 SocketChannel
- 服务器通过 ServerBootstrap来配置参数,但是对于不同的 Channel 需要选择不同的方法
- 通过 option 来配置 ServerSocketChannel 上的参数
- 通过 childOption 来配置 SocketChannel 上的参数
源码分析
客户端中连接服务器的线程是 NIO 线程,抛出异常的是主线程。这是如何做到超时判断以及线程通信的呢?
AbstractNioChannel 的 connect 方法中设置了异常:
@Override
public final void connect(
final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) {
. . .
// 从参数中获取超时时间
int connectTimeoutMillis = config().getConnectTimeoutMillis();
if (connectTimeoutMillis > 0) {
// 通过schedule 去执行一个定时任务
connectTimeoutFuture = eventLoop().schedule(new Runnable() {
@Override
public void run() {
ChannelPromise connectPromise = AbstractNioChannel.this.connectPromise;
ConnectTimeoutException cause =
new ConnectTimeoutException("connection timed out: " + remoteAddress);
//如果超时没有获取连接,则tryFailure将异常放入promise中,供主线程取
if (connectPromise != null && connectPromise.tryFailure(cause)) {
close(voidPromise());
}
}
}, connectTimeoutMillis, TimeUnit.MILLISECONDS);
}
. . .
}
} catch (Throwable t) {
promise.tryFailure(annotateConnectException(t, remoteAddress));
closeIfClosed();
}
}
超时的判断主要是通过 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 启用的情况下,逻辑上没有最大值限制,这个设置便被忽略
- 全连接队列 - accept queue
- 其大小通过 /proc/sys/net/core/somaxconn 指定,在使用 listen 函数时,内核会根据传入的 backlog 参数与系统参数,取二者的较小值
- 如果 accpet queue 队列满了,server 将发送一个拒绝连接的错误信息到 client
示例
在Netty中,SO_BACKLOG主要用于设置全连接队列的大小。当处理Accept的速率小于连接建立的速率时,全连接队列中堆积的连接数大于SO_BACKLOG设置的值是,便会抛出异常
public class BackLogTest {
public static void main(String[] args) {
NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap server = new ServerBootstrap()
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
//设置全连接队列大小为2
.option(ChannelOption.SO_BACKLOG, 2)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
}
});
ChannelFuture channelFuture = server.bind(8080).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
三、TCP_NODELAY
- 属于 SocketChannal 参数
- 因为 Nagle 算法,数据包会堆积到一定的数量后一起发送,这就可能导致数据的发送存在一定的延时
- 该参数默认为false,如果不希望的发送被延时,则需要将该值设置为true
四、SO_SNDBUF & SO_RCVBUF
- SO_SNDBUF 属于 SocketChannal 参数(发送缓冲区大小)
- SO_RCVBUF 既可用于 SocketChannal 参数,也可以用于 ServerSocketChannal 参数(建议设置到 ServerSocketChannal 上)(接受缓冲区大小)
- 该参数用于指定接收方与发送方的滑动窗口大小
五、ALLOCATOR
- 属于 SocketChannal 参数
- 用来配置 ByteBuf 是池化还是非池化,是直接内存还是堆内存
使用
ServerBootstrap server = new ServerBootstrap()
.childOption(ChannelOption.ALLOCATOR, new PooledByteBufAllocator())
- 池化并使用直接内存
// true表示使用直接内存
new PooledByteBufAllocator(true);
- 池化并使用堆内存
// false表示使用堆内存
new PooledByteBufAllocator(false);
- 非池化并使用直接内存
// ture表示使用直接内存
new UnpooledByteBufAllocator(true);
- 非池化并使用堆内存
// false表示使用堆内存
new UnpooledByteBufAllocator(false);
六、RCVBUF_ALLOCATOR
- 属于 SocketChannal 参数
- 控制 Netty 接收缓冲区大小
- 负责入站数据的分配,决定入站缓冲区的大小(并可动态调整),统一采用 direct 直接内存,具体池化还是非池化由 allocator 决定
最后
以上就是陶醉小甜瓜为你收集整理的Netty 参数调优一、CONNECT_TIMEOUT_MILLIS二、SO_BACKLOG三、TCP_NODELAY四、SO_SNDBUF & SO_RCVBUF五、ALLOCATOR六、RCVBUF_ALLOCATOR的全部内容,希望文章能够帮你解决Netty 参数调优一、CONNECT_TIMEOUT_MILLIS二、SO_BACKLOG三、TCP_NODELAY四、SO_SNDBUF & SO_RCVBUF五、ALLOCATOR六、RCVBUF_ALLOCATOR所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复