Spring Cloud Gateway中netty线程池优化示例详解

 更新时间:2023年07月21日 08:53:27   作者:AC编程  
这篇文章主要介绍了Spring Cloud Gateway中netty线程池优化示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

一、背景描述

最近测试同学对系统进行压测。报出一个问题:几乎所有接口的成绩都不太好。甚至一些仅仅是主键查询,并且数据量不大的接口也是如此。排查过程中:跳过gateway网关,直接通过目标服务器ip进行压测发现成绩提升明显。初步判断是网关问题。网上翻阅资料发现一个优化点,就是netty本身的线程池配置。

二、线程池配置

要设置可同时工作的线程数需要设置netty中的reactor.netty.ioWorkerCount参数。该参数无法直接配置,需要通过System.setProperty设置,故我们可以创建以下配置类来配置该参数:

@Configuration
public static class ReactNettyConfiguration {
    @Bean
    public ReactorResourceFactory reactorClientResourceFactory() {
        System.setProperty("reactor.netty.ioSelectCount","1");
        // 这里工作线程数为2-4倍都可以。看具体情况
        int ioWorkerCount = Math.max(Runtime.getRuntime().availableProcessors()*3, 4));
        System.setProperty("reactor.netty.ioWorkerCount",String.valueOf(ioWorkerCount);
        return new ReactorResourceFactory();
    }
}

我这里版本是reactor-netty-core-1.0.3,版本不一样的话 可能参数key不太一样。可以看一下LoopResources 中写的key。

Runtime.getRuntime().availableProcessors()获取的是cpu核心线程数也就是计算资源,而不是CPU物理核心数,对于支持超线程的CPU来说,单个物理处理器相当于拥有两个逻辑处理器,能够同时执行两个线程。

三、源码分析

package reactor.netty.resources;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import java.time.Duration;
import java.util.Objects;
import reactor.core.Disposable;
import reactor.core.publisher.Mono;
@FunctionalInterface
public interface LoopResources extends Disposable {
    // 这里是worker线程数,未配置的话。从cpu核心数和4直接取一个大的
    int DEFAULT_IO_WORKER_COUNT = Integer.parseInt(System.getProperty("reactor.netty.ioWorkerCount", "" + Math.max(Runtime.getRuntime().availableProcessors(), 4)));
    // 这里是select线程数 默认是-1
    int DEFAULT_IO_SELECT_COUNT = Integer.parseInt(System.getProperty("reactor.netty.ioSelectCount", "-1"));
    ....
    // 创建一个默认的资源,把两个线程数的参数传递过去
    static LoopResources create(String prefix) {
        if (Objects.requireNonNull(prefix, "prefix").isEmpty()) {
            throw new IllegalArgumentException("Cannot use empty prefix");
        }
        return new DefaultLoopResources(prefix, DEFAULT_IO_SELECT_COUNT, DEFAULT_IO_WORKER_COUNT, true);
    }
    ....

接下来看一下 DefaultLoopResources做了什么

DefaultLoopResources(String prefix, int selectCount, int workerCount, boolean daemon) {
        this.running = new AtomicBoolean(true);
        this.daemon = daemon;
        this.workerCount = workerCount;
        this.prefix = prefix;
        this.serverLoops = new AtomicReference<>();
        this.clientLoops = new AtomicReference<>();
        this.cacheNativeClientLoops = new AtomicReference<>();
        this.cacheNativeServerLoops = new AtomicReference<>();
        // 因为默认没有配置 所以selectCode必然是-1
        if (selectCount == -1) {
            this.selectCount = workerCount;
            // serverSelectLoops没有创建,而是直接使用的serverLoops
            this.serverSelectLoops = this.serverLoops;
            this.cacheNativeSelectLoops = this.cacheNativeServerLoops;
        }
        else {
            this.selectCount = selectCount;
            this.serverSelectLoops = new AtomicReference<>();
            this.cacheNativeSelectLoops = new AtomicReference<>();
        }
    }
    @SuppressWarnings("FutureReturnValueIgnored")
    EventLoopGroup cacheNioSelectLoops() {
        // 两个相等的话 使用 cacheNioServerLoops 返回工作组
        if (serverSelectLoops == serverLoops) {
            return cacheNioServerLoops();
        }
        EventLoopGroup eventLoopGroup = serverSelectLoops.get();
        if (null == eventLoopGroup) {
            EventLoopGroup newEventLoopGroup = new NioEventLoopGroup(selectCount,
                    threadFactory(this, "select-nio"));
            if (!serverSelectLoops.compareAndSet(null, newEventLoopGroup)) {
                //"FutureReturnValueIgnored" this is deliberate
                newEventLoopGroup.shutdownGracefully(0, 0, TimeUnit.MILLISECONDS);
            }
            eventLoopGroup = cacheNioSelectLoops();
        }
        return eventLoopGroup;
    }
    // 这里相当于返回了工作组
    @SuppressWarnings("FutureReturnValueIgnored")
    EventLoopGroup cacheNioServerLoops() {
        EventLoopGroup eventLoopGroup = serverLoops.get();
        if (null == eventLoopGroup) {
            EventLoopGroup newEventLoopGroup = new NioEventLoopGroup(workerCount,
                    threadFactory(this, "nio"));
            if (!serverLoops.compareAndSet(null, newEventLoopGroup)) {
                //"FutureReturnValueIgnored" this is deliberate
                newEventLoopGroup.shutdownGracefully(0, 0, TimeUnit.MILLISECONDS);
            }
            eventLoopGroup = cacheNioServerLoops();
        }
        return eventLoopGroup;
    }

可以看出来,如果未配置。netty是没有select线程组的。结合分析reactor模型可以发现,这种情况对处理效率是有影响的。而且最大只和cpu核心数量相同的配置也明显无法重复利硬件用资源。

参考:https://www.jb51.net/program/292774r05.htm

以上就是Spring Cloud Gateway中netty线程池优化的详细内容,更多关于Spring Cloud Gateway中netty线程池优化的资料请关注脚本之家其它相关文章!

相关文章

  • Jenkins与SVN持续集成的示例代码

    Jenkins与SVN持续集成的示例代码

    这篇文章主要介绍了Jenkins与SVN持续集成的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-03-03
  • 解决SpringBoot整合Mybatis扫描不到Mapper的问题

    解决SpringBoot整合Mybatis扫描不到Mapper的问题

    这篇文章主要介绍了解决SpringBoot整合Mybatis扫描不到Mapper的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-04-04
  • JavaWeb实现文件上传与下载实例详解

    JavaWeb实现文件上传与下载实例详解

    在Web应用程序开发中,文件上传与下载功能是非常常用的功能,下面通过本文给大家介绍JavaWeb实现文件上传与下载实例详解,对javaweb文件上传下载相关知识感兴趣的朋友一起学习吧
    2016-02-02
  • Spring Boot 2.x 实现文件上传功能

    Spring Boot 2.x 实现文件上传功能

    这篇文章主要介绍了Spring Boot 2.x 实现文件上传功能,本文分步骤通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • 从@CrossOrigin到Gateway详解Spring Boot跨域处理的10种姿势

    从@CrossOrigin到Gateway详解Spring Boot跨域处理的10种姿势

    在前后端分离架构成为主流的今天,跨域问题已成为每个Web开发者必须面对的挑战,本文将系统性地介绍10种Spring Boot跨域处理方案,下面小编就和大家简单介绍一下吧
    2025-11-11
  • 模拟Ping操作的一个Java类

    模拟Ping操作的一个Java类

    这篇文章主要为大家详细介绍了一个模拟Ping操作的Java类,感兴趣的小伙伴们可以参考一下
    2016-03-03
  • 浅谈标签和JLabel类构造方法

    浅谈标签和JLabel类构造方法

    这篇文章主要介绍了标签和JLabel类构造方法,具有一定参考价值,需要的朋友可以参考下。
    2017-09-09
  • Spring MVC如何设置响应

    Spring MVC如何设置响应

    本文介绍了如何在Spring框架中设置响应,并通过不同的注解返回静态页面、HTML片段和JSON数据,此外,还讲解了如何设置响应的状态码和Header
    2025-01-01
  • Java基础篇之List集合举例详解

    Java基础篇之List集合举例详解

    Java中的List集合是一种常用的数据结构,它提供了一种有序、可重复的元素集合,下面这篇文章主要给大家介绍了关于Java基础篇之List集合的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-03-03
  • SpringBoot使用Validation校验参数的详细过程

    SpringBoot使用Validation校验参数的详细过程

    这篇文章主要介绍了SpringBoot使用Validation校验参数,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09

最新评论