Spring Cloud Gateway 服务器性能异常,以及优化策略

2年前 (2022) 程序员胖胖胖虎阿
652 0 0

版本说明

<spring-boot.version>2.3.2.RELEASE</spring-boot.version>
<spring-cloud.version>Hoxton.SR8</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.5.RELEASE</spring-cloud-alibaba.version>

服务器状态异常

部署模式

nginx + 3台 cloud gateway

现象

nginx连接数异常,直线上升
使用如下命令,查询服务器tcp连接状态发现情况

# 图1命令
netstat -ant|grep TIME_WAIT|wc -l
# 图二命令
netstat -apn|grep 18080 |wc -l # 18080为gateway端口

Spring Cloud Gateway 服务器性能异常,以及优化策略
服务器出现大量TIME_WAIT
Spring Cloud Gateway 服务器性能异常,以及优化策略

解决方案,修改内核参数

执行以下命令,编辑系统内核配置。

vi /etc/sysctl.conf

修改或加入以下内容。

# 开启SYN的cookies,当出现SYN等待队列溢出时,启用cookies进行处理
net.ipv4.tcp_syncookies = 1 
# 允许将TIME-WAIT的socket重新用于新的TCP连接。如果新请求的时间戳,比存储的时间戳更大,则系统将会从TIME_WAIT状态的存活连接中选取一个,重新分配给新的请求连接。
net.ipv4.tcp_tw_reuse = 1 
#警告:对于服务端来说,在NAT环境中,开启net.ipv4.tcp_tw_recycle = 1配置可能导致校验时间戳递增,从而影响业务,不建议开启该功能。
# 开启TCP连接中TIME-WAIT的sockets快速回收功能。需要注意的是,该机制也依赖时间戳选项,系统默认开启tcp_timestamps机制,而当系统中的tcp_timestamps和tcp_tw_recycle机制同时开启时,会激活TCP的一种行为,即缓存每个连接最新的时间戳,若后续的请求中时间戳小于缓存的时间戳时,该请求会被视为无效,导致数据包会被丢弃。
# 特别是作为负载均衡服务器的场景,不同客户端请求经过负载均衡服务器的转发,可能被认为是同一个连接,若客户端的时间不一致,对于后端服务器来说,会发生时间戳错乱的情况,因此会导致数据包丢失,从而影响业务。
net.ipv4.tcp_tw_recycle = 1
# 如果socket由服务端要求关闭,则该参数决定了保持在FIN-WAIT-2状态的时间。
net.ipv4.tcp_fin_timeout = 15

刷新配置文件,使其生效

/sbin/sysctl -p 

Gateway配置优化处理

application.yml

spring:
  application:
    name: gateway
  cloud:
    gateway:
      # http连接设置
      httpclient:
        # 全局的响应超时时间,网络链接后,后端服务多久不返回网关就报错 The response timeout.
        response-timeout: PT10S
        # 全局的TCP连接超时时间默认时间是45秒,修改为5秒
        connect-timeout: 5000
        # 链接池配置
        pool:
          # 最大连接数
          max-connections: 10000
          # 最大连接时间
          max-life-time: 10
          # 返回时间
          acquire-timeout: 10
          # 最大空闲时间
          max-idle-time: 10000
          # 设置固定链接池
          type: fixed

server:
  port: 18080
  servlet:
    context-path: /

踩坑点一:连接池类型

spring.cloud.gateway.httpclient.pool.type,该参数一共有三种类型
ELASTIC:弹性链接池,连接数上限为Integer.MAX,默认值就是这个类型
FIXED: 固定连接池,最大连接数采用spring.cloud.gateway.httpclient.pool.max-connections的配置
DISABLED:不使用任何连接池

由于使用了ELASTIC类型,连接数不可控。。。。

踩坑点二:gateway线程数参数设置

@SpringBootApplication
public class GateWayApplication {
    private static final Logger logger = LoggerFactory.getLogger(GateWayApplication.class);

    public static void main(String[] args) {
		// 用几个cpu处理select,如果不是很懂的情况下,可以注释掉
        String ioSelectCount = System.getProperty(ReactorNetty.IO_SELECT_COUNT);
        if(StringUtils.isEmpty(ioSelectCount)){
            String selectCount = "1";
            System.setProperty(ReactorNetty.IO_SELECT_COUNT, selectCount);
            logger.info("未发现设置的参数,启用自定义配置selectCount:{}", selectCount);
        }else{
            logger.info("使用默认值selectCount:{}",ioSelectCount);
        }

		// 设置工作线程数量,最好不要超过cpu * 3
        String ioWorkerCount = System.getProperty(ReactorNetty.IO_WORKER_COUNT);
        if(StringUtils.isEmpty(ioWorkerCount)){
            int cpu = Runtime.getRuntime().availableProcessors();
            // *3 还是 *2 可以根据具体情况设置,默认是 cpu核心数,线程过多,可能会导致服务器上下文切换过多导致cpu更高
            String workerCount = String.valueOf(cpu * 3);
            System.setProperty(ReactorNetty.IO_WORKER_COUNT, workerCount);
            logger.info("未发现设置的参数,启用自定义配置workerCount:{}", workerCount);
        }else{
            logger.info("使用默认值workerCount:{}",ioWorkerCount);
        }


        String poolLeasingStrategy = System.getProperty(ReactorNetty.POOL_LEASING_STRATEGY);
        if(StringUtils.isEmpty(poolLeasingStrategy)){
             // 这个参数的作用是先使用后回收的连接,而不是先使用先回收的连接
            System.setProperty("reactor.netty.pool.leasingStrategy", "lifo");
            logger.info("未发现设置的参数,启用自定义配置leasingStrategy:{}", "lifo");
        }else{
            logger.info("使用默认值leasingStrategy:lifo");
        }

        SpringApplication.run(GateWayApplication.class);
        logger.info("--------------start done--------------");
    }

踩坑点三:可选添加reactor-poll

 <dependency>
  	  <groupId>io.projectreactor.addons</groupId>
     <artifactId>reactor-pool</artifactId>
 </dependency>

功底不够,reactor源码看得不是很懂,但是发现装配时候,缺少reactor-poll相关依赖
也许会有性能提升,待验证

相关文章

暂无评论

暂无评论...