【问题标题】:Spring boot thread hanging?Spring Boot 线程挂起?
【发布时间】:2019-02-07 14:29:52
【问题描述】:

我有一个简单的(这就是我的想法)Spring Boot 应用程序。有4层:

  1. 休息控制器
  2. 应用服务(由 Rest Controller 调用)
  3. 域服务(由应用服务调用。它连接到数据库 - 存储库层)
  4. 适配器服务(由应用服务调用以通过 Hystrix 进行出站调用)

现在的问题是它最多只能处理 15 个并行调用。如果在处理这些调用时有任何其他 REST API 请求到达,它会到达 应用程序服务层,然后等待。一旦这 15 个并行调用之一返回,则新请求继续调用 域服务层 并返回。

我尝试了多种方法:

  1. 在 application.properties 文件中增加服务器的备用线程

    server.tomcat.min-spare-threads=1000
    server.tomcat.max-connections=1000
    server.tomcat.max-threads=1000
    

执行此操作后,我看到 http-nio-* 线程数增加到 1000,但挂起问题并未解决。

  1. 我在网上找到了这个 sn-p 来自定义 tomcat 容器,但它也没有帮助:

    @Bean
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> containerCustomizer() {
    
      return new WebServerFactoryCustomizer<TomcatServletWebServerFactory>() {
    
        @Override
        public void customize(TomcatServletWebServerFactory factory) {
          factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
          @Override
          public void customize(Connector connector) {
    Arrays.stream(connector.getProtocolHandler().findUpgradeProtocols())
            .filter(upgradeProtocol -> upgradeProtocol instanceof Http2Protocol)
            .map(upgradeProtocol -> (Http2Protocol) upgradeProtocol)
            .forEach(http2Protocol -> {
              http2Protocol.setMaxConcurrentStreamExecution(1000);
            });
           }
         });
        }
      };
    }
    
  2. 我尝试通过代码配置线程池

    @Bean(name = "taskExecutor")
    public TaskExecutor threadPoolTaskExecutor() {
    
      ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    
      executor.setCorePoolSize(200);
      executor.setMaxPoolSize(300);
      executor.setQueueCapacity(300);
      executor.setThreadNamePrefix("anniversary");
    
      executor.initialize();
      System.out.println("******* name "  + executor.getThreadNamePrefix());
      System.out.println("********** core pool size " + executor.getCorePoolSize());
    
      return executor;
    }
    

但这些都没有帮助,我认为问题不在于线程数,而在于其他地方,因为请求无法从一项服务转到另一项服务。有数百个 http-nio-* 线程处于等待状态,当有新请求进来时,它分配了自己的线程,我可以在调试模式下看到。

非常感谢任何指针、帮助和提示。 Spring Boot 调用服务到服务需要什么资源?

【问题讨论】:

  • 提示:获取线程堆栈转储并使用堆栈跟踪找出线程等待等待的原因。

标签: java spring multithreading spring-boot


【解决方案1】:

我相信您的观察是正确的 - 这里的瓶颈很可能不是 tomcat。从你写的,宁愿看域服务。域服务是在与数据库进行一些通信还是通过网络(例如通过 HTTP)与其他东西进行通信?

如果你碰巧在那里做数据库,检查 spring 的数据源配置。将有一个数据库连接池,其中与数据库的最大并发连接数有限。一旦这些连接都在使用中,想要与数据库通信的线程将被阻塞,直到其中一个连接再次空闲。

类似的连接池与许多其他通过网络通信的东西都存在(例如,Apache HTTP 客户端也有一个可以配置的连接池)。

这就是我接下来要看的地方。

干杯, 马蒂亚斯

【讨论】:

  • 谢谢你们!就是这样。我将 hikari 池大小增加到 500,它开始工作了。
  • 不客气。但是,请注意与数据库的许多连接。如果您的应用程序在生产环境中运行多个实例,您的数据库不仅需要处理 500 个并发连接,还需要处理 n * 500。如果您有 10 个实例在运行,则将有 5000 个连接。我建议尝试一些值,看看在哪里可以获得最佳结果。
  • 是的,我将其拆分为每个环境中的服务器数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-04-04
  • 1970-01-01
  • 2012-04-18
  • 2014-09-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多