重新启动 Spring Boot 应用程序后首次调用缓慢

Mar*_*ier 6 postgresql hibernate jackson spring-boot

我们有一个使用 Postgres、Hibernate、Jackson 和 Spring Data Rest 的 React - Spring Boot 应用程序。

每次应用程序重新启动后,第一次调用后路由到达我们的一个后端服务器的时间很长(超过 4 秒)。随后每次调用同一路由到达每个服务器的时间都在 100 毫秒以内。

我们的目标是保证我们的用户在每次重新部署后都不会受到这些缓慢调用的影响。

我们正在考虑在每次部署后自动触发调用,以便应用程序“预热”并且我们的客户不会有长时间的调用。

由于负载均衡器后面有多个后端服务器,我们希望直接从后端而不是客户端触发这些调用。

我们想更好地了解会发生什么,以便我们更有效地做到这一点:它可以是 Hibernate 吗?Spring 懒加载 bean?杰克逊?

休眠 L2 缓存未激活。

我们希望每次都具有相同的快速响应时间(< 100 毫秒),而不是最初的 4 秒调用。

g3o*_*rg3 5

我们遵循@willermo 的回答以及来自另一个论坛的一些提示的快速更新使我们朝着解决问题的正确方向前进。

我们使用-verbose:class标志记录了类加载,这清楚地表明问题在于类在第一次调用时被延迟加载。

为了预加载这些类,我们使用 anApplicationRunner来触发应用程序启动时的调用,正如@willermo 所建议的那样;这使我们能够确定性地预热负载均衡器后面的所有服务器,并对每个服务器进行一次调用。

有几个额外的障碍很容易解决:

  • 添加ApplicationRunner破坏了我们所有的测试,所以我们不得不从测试配置文件中排除它。
  • 我们不想保留这些“假”调用对 DB 的影响,因此我们将它们封装在我们最终回滚的事务中。

这是我们的最终解决方案:

@Component
@Profile("!test")
public class AppStartupRunner implements ApplicationRunner {

  // [Constructor with injected dependencies]

  @Transactional
  @Override
  public void run(ApplicationArguments args) throws Exception {
    // [Make the calls]
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();    
  }
}

Run Code Online (Sandbox Code Playgroud)