性能-Spring Boot-服务器响应时间

时间:2018-10-04 14:07:54

标签: spring spring-mvc spring-boot tomcat tomcat8

我的Spring Boot应用程序有一个奇怪的行为:

  • 前端/客户端-角度6
  • 后端-春季启动-春季MVC-嵌入式tomcat-Linux

重新启动后端后,对控制器的第一次调用大约需要5秒钟,随后的相同请求仅需50毫秒。在90%的情况下,这种情况是可以重现的,有时甚至是第一次通话都很快。

我敢肯定,问题出在服务器而不是客户端上。在浏览器上,我看到TTFB时间(到第一个字节的时间)增加到5秒。以下请求对TTFB只需10毫秒。

使用服务器上的监视工具(应用程序动态),我可以收集如此缓慢的服务器调用,而在调用图上,我可以看到:

GridPane

需要4916ms。我想这就是我的瓶颈。但是我不知道如何解决。

我已经尝试过的:

  • 从hikaricp切换到apache tomcat jdbc连接池
  • 将弹簧靴从2.0.0升级到2.0.5
  • 将Java升级到1.8.0_181
  • 属性spring.jpa.tomcat.testOnBorrow = true
  • 属性spring.jpa.tomcat.validationQuery =选择1

一切都不会影响服务器延迟。

更新

由于多次扫描war文件而浪费了时间。

org.apache.catalina.webresources.CachedResource.validateResource 正在检查我们是否有战争文件( isPackedWarFile ),并且此检查返回false。即使是战争文件。对于这种行为,我有一个解决方法。我将 tomcat.resource.cache-tt 设置为较高的值。

但是现在 org.apache.catalina.webresources.Cache.getResource 具有 noCache 方法。在这种方法中, class jar 文件被排除在缓存之外。这就是再次扫描 war 文件的原因。

扫描整个war文件大约需要5秒钟。这个突破是世界突破的停顿。而且此扫描绝对是不必要的,因为war文件不会爆炸,因此其内容也无法更改。

更新

如果将war文件放入tomcat安装中,一切都会很快。嵌入式的tomcat就是问题所在。

4 个答案:

答案 0 :(得分:1)

我想您已经做过,但是如果没有,请看看https://wiki.apache.org/tomcat/HowTo/FasterStartUp并实施那里建议的修复程序。

要在嵌入式tomcat中禁用扫描,请在https://github.com/spring-projects/spring-boot/issues/1610

的注释中提出建议

如果以上建议均不能帮助您解决延迟问题,则可能的解决方法是在服务器启动时发出第一个请求(并从那里触发延迟)。

@SpringBootApplication
public class Application implements CommandLineRunner {

    @Autowired
    private RestTemplate template;

    public static void main (String args[]){
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String... strings) throws Exception {
        // do an initial request from here to trigger scanning the war
        template.exchange(...);
    }

}

这样,您的客户将不再经历5秒的延迟。我知道这是一种黑客行为,因此,如果您找到一种更清洁的方法,请改用它。

答案 1 :(得分:1)

我面临类似的问题,即CPU使用率高和响应延迟。 org.apache.catalina.webresources.JarWarResourceSet:getArchiveEntries扫描战争文件大约需要5秒钟。在扫描过程中,没有任何请求得到处理。

我已将Spring boot version1.4.2.RELEASE更新为1.5.12.RELEASE,从而解决了此问题。确实,似乎问题在于嵌入式Tomcat在更高版本中已得到解决。

答案 2 :(得分:0)

使用可执行文件 JAR (而不是WAR)与嵌入式Tomcat一起运行可以为我解决此问题。这是recommended way,可以加快从可执行归档文件中加载资源的速度。

  1. 您可以拥有one Spring Boot project and deploy to both JAR or WAR
  2. 我必须从WAR切换到JAR才能获得更好的性能,并且在freemarker中使用JSP taglib时遇到了问题。这是a way to solve that issue when using JSP taglibs

答案 3 :(得分:-1)

您所描述的是重新启动对使用大量数据库连接池的基础结构的典型影响。

  • 第一个请求:打开物理连接(100ms至2-3秒),进行一些初始化(取决于DB),执行SQL(每个查询不同),返回池(<1ms)
  • 第二个请求:从池中提取(<1ms),执行SQL(每个查询不同),返回到池中(<1ms)

根据您的数据,我最好的猜测是前两个步骤很慢,直到数据库池预热为止,您将遇到一些非常缓慢的查询。 可能的改进是:

  • 配置一个预热期,在此期间,池将执行自动初始化,而Tomcat尚未响应
  • 在数据库端检查在创建连接时进行了什么操作,在应用程序端检查是否必须设置连接的配置