我有一个运行默认嵌入式tomcat的spring启动应用程序(带有tomcat jdbc连接池(。它的生产和运行良好。我正在使用mysql作为我的数据库。
我现在正在测试环境中进行一些压力测试,并试图看看如果我从嵌入式Tomcat切换到嵌入式Undertow,我是否会得到任何明显的好处。人们声称,由于欠拖请求处理的异步性质,这样做可以明显提高吞吐量。
我知道如何排除雄猫并将暗流添加到启动应用程序。完成此操作后,我尝试运行压力测试脚本以每秒生成大约 500 个请求,在此负载下运行 5 分钟,看看它的行为方式。当我这样做时,在最初的几秒钟后,我开始间歇性地收到 jdbc 异常,如下所示。
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:431) ~[spring-orm-4.3.2.RELEASE.jar!/:4.3.2.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373) ~[spring-tx-4.3.2.RELEASE.jar!/:4.3.2.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:426) ~[spring-tx-4.3.2.RELEASE.jar!/:4.3.2.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:275) ~[spring-tx-4.3.2.RELEASE.jar!/:4.3.2.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.3.2.RELEASE.jar!/:4.3.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.2.RELEASE.jar!/:4.3.2.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ~[spring-tx-4.3.2.RELEASE.jar!/:4.3.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.2.RELEASE.jar!/:4.3.2.RELEASE]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133) ~[spring-data-jpa-1.10.2.RELEASE.jar!/:na]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.2.RELEASE.jar!/:4.3.2.RELEASE]
这意味着无法获取 jdbc 连接。
注意:如果我删除嵌入式欠拖并再次将嵌入式 tomcat 添加到我的应用程序中,则相同的测试运行良好,没有任何与 jdbc 连接相关的异常。
我的底层Tomcat-jdbc-pool有100 db-connection。对于暗流,我尝试使用 100 个工作线程和 100 个 io 线程。
我还尝试使用HikariCP而不是默认的tomcat-jdbc-pooling。我尝试了 HikariCP,最大池大小 = 100 和连接超时 = 60000。再次嵌入Tomcat + HikariCP在这个压力测试下运行良好。但是嵌入式 Undertow+HikariCP 给出了类似的例外。
因此,当我在图片中引入Undertow时,发生了一些不同的事情。但我无法理解它。请注意,这些异常是间歇性的,但在使用 Undertow 时,在我的压力测试的每次运行中都会出现。
我通常会搜索此类问题。总的来说,我找不到如此常见的暗流婴儿床。
任何分析情况的帮助都将节省大量时间。
首先,您最好一次更改一个内容以减少潜在问题。
欠拖 - 100 个 IO 线程太多了。您可能应该坚持这里的默认值,即我相信每个内核 1 个 IO 线程。IO 线程的唯一工作是管理打开的连接并处理任何非阻塞工作。JDBC SQL 查询是阻塞的,因此您需要确保任何阻塞的端点都将请求分派给工作线程。你可以为此使用BlockingHandler,我不确定如何使用Spring来做到这一点。同样,100 个工作线程可能有点过分,默认值要低得多,我相信 20-30 范围。在切换到 HikariCP 之前,请确保这在您现有的连接池中正常工作。我建议将线程池保留为默认值以启动,并确保将线程池调度到工作线程。
HikariCP - 100个连接对于HikariCP来说也很多,除非你有大量非常非常长的运行查询。有关连接池大小调整的详细信息。
不要尝试同时更改两者。在这种情况下,将更难追踪正在发生的事情。