• [OS/Linux] Linux核心参数:net.core.somaxconn(高并发场景核心参数)


    目录

    0 序言

    • 近期工作在搞压力测试,我负责开发维护的、基于sring-cloud-gateway大数据网关微服务,其底层是基于spring-webflux-->reactor-netty-->netty
    • 在压测过程中(200并发-->1000并发),发现大数据网关屡报ConnectException: finishConnect(..) failed: Connection refused错误。
    Caused by: java.net.ConnectException: finishConnect(..) failed: Connection refused
    	at io.netty.channel.unix.Errors.newConnectException0(Errors.java:155) ~[netty-transport-native-unix-common-4.1.65.Final.jar!/:4.1.65.Final]
    	at io.netty.channel.unix.Errors.handleConnectErrno(Errors.java:128) ~[netty-transport-native-unix-common-4.1.65.Final.jar!/:4.1.65.Final]
    	at io.netty.channel.unix.Socket.finishConnect(Socket.java:278) ~[netty-transport-native-unix-common-4.1.65.Final.jar!/:4.1.65.Final]
    	at io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe.doFinishConnect(AbstractEpollChannel.java:710) [netty-transport-native-epoll-4.1.65.Final-linux-x86_64.jar!/:4.1.65.Final]
    

    关键行:io.netty.channel.unix.Socket.finishConnect(Socket.java:278) ~[netty-transport-native-unix-common-4.1.65.Final.jar!/:4.1.65.Final]

    • 经过长时间、大量的分析(Debug spring-cloud-gateway 源码、观测服务所属主机资源),倾向于本微服务所属主机的net.core.somaxconn不足这种原因。

    博主的做法:128 --> 1024

    • 环境信息
    linux os : Alpine Linux 3.17.3 - 一个社区开发的、面向安全应用的、基于Musl libc和busybox的轻量级Linux发行版
        https://gitlab.alpinelinux.org/alpine/
        NAME="Alpine Linux"
        ID=alpine
        VERSION_ID=3.17.3
        PRETTY_NAME="Alpine Linux v3.17"
        HOME_URL="https://alpinelinux.org/"
        BUG_REPORT_URL="https://gitlab.alpinelinux.org/alpine/aports/-/issues"
    
    spring-cloud-gateway:2.2.9.RELEASE
    spring-cloud-starter:2.2.9.RELEASE
    spring-cloud-alibaba:2.2.7.RELEASE
    spring-cloud:Hoxton.SR12
    spring-boot:2.3.12.RELEASE
    spring:5.2.15.RELEASE
    

    1 参数定义

    • net.core.somaxconn
    • Linux 操作系统全局参数,每个 TCP连接 监听端口的队列长度

    somaxconn - INTEGER

    • Limit of socket listen() backlog,在用户空间中称为 SOMAXCONN。
    • 默认值为 4096。(在 linux-128.5 之前是 4)
    • 另请参阅tcp_max_syn_backlog,了解 TCP 套接字的其他调整。
    • CentOS/RHEL 7.9 中,默认值为128,对于高并发场景都建议调大该值。
    • 在RHEL 6和RHEL 7中,socket结构的sk_max_ack_backlog字段被定义为无符号短整型,它将值限制为16位,最大值为65535。
    • 在 RHEL 8 中,socket结构的sk_max_ack_backlog字段定义为 u32,它将值限制为 32 位,最大值为 2147483647。

    2 查看方法

    2.1 Linux

    • 方法1
    cat /proc/sys/net/core/somaxconn
    
    • 方法2
    sysctl -a | grep somaxconn
    

    3 不同应用的配置建议

    3.1 Oracle WebLogic Server

    https://docs.oracle.com/communications/E96856-01/doc.74/e96850/installing-and-configuring-weblogic-server-cluster1.htm#OSMIG-GUID-87BEF43B-4673-4062-8451-228E436D421D

    • 客户端数:设置 somaxconn 应至少设置为 1024,以 允许大量客户端服务器连接。

    排队的数据包数:将netdev_max_backlog设置为至少 32768,以最大程度地减少数据包丢失。

    3.2 Apache Zookeeper

    Configurable listen socket backlog for the client port - issues.apache.org/zookeeper

    在 Linux 上,以下参数: net.core.somaxconn 需要大于“客户端端口积压工作”以上才能正确配置侦听套接字积压工作

    3.3 TiDB

    https://blog.csdn.net/weixin_43700866/articTiDBle/details/125667286
    内核参数 - pingcap.com

    • 内核参数
    检查各项内核参数的值:
    …
    `net.core.somaxconn: 32768`
    

    3.4 Nginx

    Tuning the Operating System - Nginx.com

    net.core.somaxconn 内核参数的值从其默认值 (128) 增加到足以容纳大量流量突发的值。在此示例中,它增加到 4096

    sudo sysctl -w net.core.somaxconn=4096
    ...
    

    3.5 Netty

    推荐文献

    Caused by: io.netty.channel.ChannelException: Unable to create Channel from class class io.netty.channel.socket.nio.NioSocketChannel
    ...
    

    优化建议

    • 默认情况下,Netty 的SO_BACKLOG的值等于操作系统的somaxconn的值
    ChannelOption.SO_BACKLOG` = `io.netty.util.NetUtil#SOMAXCONN
    
    • 在面对高并发场景下时,应当适当增大BACKLOG的值,使端口可以同时建立更多的TCP请求
    • 当服务的QPS不高,且服务端进程响应请求的时间较长时,可以适当减小BACKLOG的值,避免大量连接占据系统内存资源
    • 在设置BACKLOG参数时,还需要记得修改somaxconn参数,若设置的BACKLOG参数超过了系统somaxconn参数的值时,则无法生效。

    netty 源码

    netty : 4.1.65

    • 默认: ChannelOption.SO_BACKLOG = io.netty.util.NetUtil#SOMAXCONN = /proc/sys/net/core/somaxconn(Windows中默认值:200,Linux中默认值:128)
    io.netty.util.NetUtil
    	SOMAXCONN
    		https://github.com/netty/netty/issues/4936
    		/proc/sys/net/core/somaxconn
    
    io.netty.channel.epoll.EpollServerChannelConfig extends EpollChannelConfig implements ServerSocketChannelConfig
    	private volatile int backlog = NetUtil.SOMAXCONN;
    
    D:/Program_Data/maven_repository/io/netty/netty-common/4.1.65.Final/netty-common-4.1.65.Final-sources.jar!/io/netty/util/NetUtil.java:134
        io.netty.util.NetUtil#SOMAXCONN
        static {
        	...
                    int somaxconn = PlatformDependent.isWindows() ? 200 : 128;
                    File file = new File("/proc/sys/net/core/somaxconn");
        	...
    	}
    
        //io.netty.util.internal.logging.InternalLogger | 如何将 netty 日志开关打开?
    

    如下是:gateway-service [Debug 源码分析] 以本地电脑(8 core cpu)在启动后的1次请求调用为例(与 somaxcon 无关,仅是记录;NioEventLoop 取决于 CPU 核数)

    io.netty.bootstrap.Bootstrap#config
    
    reactor.netty.resources.DefaultLoopResources#cacheNioServerLoops
    
    D:/Program_Data/maven_repository/io/projectreactor/netty/reactor-netty/0.9.20.RELEASE/reactor-netty-0.9.20.RELEASE-sources.jar!/reactor/netty/resources/DefaultLoopResources.java:195
    	reactor.netty.resources.DefaultLoopResources#cacheNioServerLoops	
    	watch reactor.netty.resources.DefaultLoopResources cacheNioServerLoops returnObj	
    io.netty.channel.nio.NioEventLoopGroup
    io.netty.channel.nio.NioEventLoop
    


    4 配置方法

    4.1.临时生效

    sysctl -w net.core.somaxconn=10240
    

    4.2.永久生效

    echo "net.core.somaxconn = 10240" >>/etc/sysctl.conf
    sysctl -p
    

    X 参考文献

    /**
     * *******************************************************************
     * 如果不设置超时,连接会一直占用本地线程,端口,连接客户端一多,阻塞在那里,会导致本地端口用尽及CPU压力
     */
    bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000);
    
    未设置超时:
    30
    io.netty.channel.ConnectTimeoutException: connection timed out: /192.168.1.1:8866
    at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe$1.run(AbstractNioChannel.java:206)
    at io.netty.util.concurrent.PromiseTask$RunnableAdapter.call(PromiseTask.java:38)
    at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:123)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:354)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:353)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
    at java.lang.Thread.run(Thread.java:745)
    Process finished with exit code 0
    
    
    设置后:
    5
    io.netty.channel.ConnectTimeoutException: connection timed out: /192.168.1.1:8866
    at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe$1.run(AbstractNioChannel.java:206)
    at io.netty.util.concurrent.PromiseTask$RunnableAdapter.call(PromiseTask.java:38)
    at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:123)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:354)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:353)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
    at java.lang.Thread.run(Thread.java:745)
    Process finished with exit code 0
    

    X 推荐文献

  • 相关阅读:
    EMLP2021 | Google大模型微调经典论文prompt tuning
    Linux安装MySQL8.0并部署数据库教程
    操作符详解(C语言)
    【Playwright+Python】系列教程(五)元素定位
    844. 比较含退格的字符串
    学习阶段单片机买esp32还是stm32?
    Linux 内核参数:min_free_kbytes
    从“熊怪吃桃”学循环和条件
    vue3+ts+threejs 1.创建场景
    [爬虫]2.2.1 使用Selenium库模拟浏览器操作
  • 原文地址:https://www.cnblogs.com/johnnyzen/p/17393171.html