Netty的SO_LINGER不要随便用

SO_LINGER

SO_LINGER是一个Socket选项,它决定一个Socket关闭时的行为,因此配在server端配置的时候使用childOption配置,该选项针对每个连接配置生效,而不是全局性的配置。

该配置主要在阻塞IO的关闭场景下用的更多,当然,对于非阻塞式IO这个也是同样可以使用的,毕竟是针对socket的关闭行为,但是实际意义有限。

该参数指定了关闭时的超时时间,当SO_LINGER设置为0时,表示禁用SO_LINGER,关闭Socket后立即返回,内核丢弃套接字发送队列中的数据,并发送TCP RST。这种行为经常被称为“硬关闭”。

当SO_LINGER设置为非零正整数时,当Socket关闭时将等待所有数据都已发送或超时到达所指定的超时值。如果要发送的数据与指定的超时时间相比较,那么将立即返回。

在Netty中,SO_LINGER选项默认设置为-1,它采用操作系统默认行为。在大多数情况下,使用操作系统默认行为即可,但在某些特殊情况下可能需要调整此选项,例如在需要确保所有数据已经发送的应用程序中。

配置示例

        bootstrap = new ServerBootstrap().group(bossGroup, workerGroup)
                .channel(NettyUtils.nioOrEpollServerSocketChannel())
                .childOption(ChannelOption.SO_LINGER, -1)
                .childOption(NioChannelOption.SO_LINGER, -1)

如示例代码,有两种配置方式,使用ChannelOption.SO_LINGER或者NioChannelOption.SO_LINGER。
这两种方式的主要区别在代码:io.netty.channel.socket.nio.NioServerSocketChannel的内部类:NioServerSocketChannelConfig有setOption方法:

        @Override
        public <T> boolean setOption(ChannelOption<T> option, T value) {
            if (PlatformDependent.javaVersion() >= 7 && option instanceof NioChannelOption) {
                return NioChannelOption.setOption(jdkChannel(), (NioChannelOption<T>) option, value);
            }
            return super.setOption(option, value);
        }

如果java版本大于等于7并且是NioChannelOption最终会调用jdk的设置方式。
实际上这个地方区别对于这个参数的配置结果都是一样的,没有区别,可以随便选择一种方式。

不建议使用

在非阻塞IO下,SO_LINGER选项的作用有限。因为在非阻塞IO中,写操作通常是异步的,即数据被发送到缓冲区后就会立即返回,不会等待数据被传输到目标机器。因此,关闭套接字时如果设置了SO_LINGER选项,也不会等待所有未发送的数据发送完毕,因为已经无法确保所有数据都被发送出去了。

在Netty中,如果设置了SO_LINGER选项,在使用非阻塞IO时可能会导致套接字无法正确关闭,从而导致资源泄露。因此,在Netty中,我们通常不会使用SO_LINGER选项,而是使用Netty提供的优雅关闭机制,即调用Channel.close()方法并在关闭前等待所有数据发送完毕。

需要注意的是,在某些特殊情况下,SO_LINGER选项仍然有用。比如在使用TCP连接池等技术时,可能会出现连接池中的连接状态不同步的问题,此时可能需要使用SO_LINGER选项来确保所有数据被发送完毕,从而避免数据丢失或者连接不同步的问题。

注意事项

  1. SO_LINGER选项只对关闭套接字时的行为有影响,对于读写操作没有任何影响。
  2. SO_LINGER选项默认是禁用的,如果要启用需要手动设置。
  3. SO_LINGER选项的值为-1时,表示关闭套接字时将等待所有未发送的数据发送完毕,直到超时或数据全部发送完毕。
  4. SO_LINGER选项的值为0时,表示关闭套接字时将立刻关闭套接字,已发送但未被确认的数据将被丢弃。
  5. SO_LINGER选项的值大于0时,表示关闭套接字时将等待指定的时间,以确保数据被发送完毕。
  6. 在使用SO_LINGER选项时需要注意超时时间的设置,避免出现无法关闭套接字的情况,从而导致资源泄漏。

你可能感兴趣的:(网络协议,java,java,开发语言,netty,网络)