java Spring引导线程挂起?
我有一个简单的(我就是这么想的)Spring boot应用程序。共有4层:
- 休息控制器
- 应用程序服务(由Rest控制器调用)
- 域服务(由应用程序服务调用。它连接到数据库-存储库层)
- 适配器服务(由应用程序服务通过Hystrix调用出站呼叫)
现在的问题是,它最多只能处理15个并行调用。如果在处理这些调用时,有任何额外的REST API请求到达,它会进入应用程序服务层,然后等待。一旦这15个并行调用中的一个返回,那么新的请求将继续向域服务层进行调用并返回
我尝试了多种方法:
在应用程序中增加服务器的备用线程。属性文件
server.tomcat.min-spare-threads=1000 server.tomcat.max-connections=1000 server.tomcat.max-threads=1000
一旦我这么做了,我看到http nio-*线程的#增加到1000个,但挂起的问题并没有得到解决
我在网上找到了这段代码来定制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); }); } }); } }; }
我尝试通过代码配置线程池
@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调用服务到服务需要什么资源
# 1 楼答案
我相信你的观察是正确的——很可能不是tomcat是这里的瓶颈。从您所写的内容来看,我们更愿意看看域服务。域服务是否与数据库进行通信,或者通过网络(例如通过HTTP)与其他对象进行通信
如果您碰巧在其中创建了数据库,请检查spring的数据源配置。将有一个数据库连接池,其最大并发数据库连接数有限。一旦这些连接都被使用,想要与DB对话的线程将被阻塞,直到其中一个连接再次空闲
类似的连接池与许多其他通过网络进行对话的东西(例如,Apache HTTP客户端也有一个可以配置的连接池)
那就是我接下来要看的地方
干杯, 马蒂亚斯