Java 弹簧靴冷起动

Java 弹簧靴冷起动,java,spring,spring-boot,openshift,Java,Spring,Spring Boot,Openshift,我有一个SpringBoot应用程序,它运行在openshift集群中的docker容器中。在稳定状态下,有N个应用程序实例(假设N=5),请求的负载平衡到这N个实例。一切运行正常,响应时间较低(总吞吐量约为60k,响应时间约为5ms) 每当我添加一个新实例时,响应时间会短暂增加(高达~70毫秒),然后恢复正常 我能做些什么来避免这种冷启动?在发送流量之前,我尝试通过连续拨打约100个curl电话来预热应用程序,但这没有帮助 我需要更好的高并发预热脚本吗?有没有更好的方法来处理这个问题 谢谢首先

我有一个SpringBoot应用程序,它运行在openshift集群中的docker容器中。在稳定状态下,有N个应用程序实例(假设N=5),请求的负载平衡到这N个实例。一切运行正常,响应时间较低(总吞吐量约为60k,响应时间约为5ms)

每当我添加一个新实例时,响应时间会短暂增加(高达~70毫秒),然后恢复正常

我能做些什么来避免这种冷启动?在发送流量之前,我尝试通过连续拨打约100个curl电话来预热应用程序,但这没有帮助

我需要更好的高并发预热脚本吗?有没有更好的方法来处理这个问题


谢谢

首先,我会尝试启用并比较结果。将总体性能与默认的C1和C2 JIT编译器进行比较——您可能需要针对您的工作负载运行一些测试。基本上,运行Java应用程序时需要设置以下选项:

-XX:+UnlockExperimentalVMOptions-XX:+EnableJVMCI-XX:+UseJVMCompiler

另外,确保您使用了Spring Boot的执行器健康检查URL(/exactor/health)。否则,您的集装箱在准备服务之前可能会收到流量

就绪探测确定容器是否已准备好服务 请求。如果就绪探测使容器失败,则端点 控制器确保容器的IP地址已从中删除 所有服务的端点。准备就绪探针可用于向客户发送信号 端点控制器,即使容器正在运行 不应接收来自代理的任何流量。设置就绪检查 配置模板.spec.containers.readinessprobe的节 吊舱配置


最后,让NGINX或其他反向代理缓存您的响应也有帮助。

如果您的应用程序在向其提供请求时运行正常,但仍然存在响应速度慢的问题,则应尝试启用分层编译

-XX:CompileThreshold -XX:TieredCompilation
通常,VM使用解释器来收集输入编译器的方法的分析信息。在分层方案中,除了解释器之外,客户机编译器还用于生成方法的编译版本,这些方法收集有关自身的分析信息


由于编译后的代码比解释后的代码快得多,因此程序在分析阶段的执行性能更好。

我们的微服务也面临类似的问题,为了预热,我们添加了一个组件

ApplicationStartup implements ApplicationListener<ApplicationReadyEvent> 
ApplicationStartup实现ApplicationListener
在应用程序中,在应用程序启动后立即调用服务,这对我们很有用。 使用此解决方案,可以保证负载中使用的所有类都将在每个实例中的实例启动后立即加载,并且不需要外部脚本来进行调用。 外部脚本也有问题,我们不能确定新实例在哪里处理调用

@Component
public class ApplicationStartup implements ApplicationListener<ApplicationReadyEvent> {

    @Autowired
    YourService yourService;

    @Override
    public void onApplicationEvent(final ApplicationReadyEvent event) {

        System.out.println("ApplicationReadyEvent: application is up");
        try {
            // some code to call yourservice with property driven or constant inputs 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


} 
@组件
公共类ApplicationStartup实现ApplicationListener{
@自动连线
你的服务你的服务;
@凌驾
ApplicationEvent上的公共无效(最终ApplicationReadyEvent事件){
System.out.println(“ApplicationReadyEvent:应用程序启动”);
试一试{
//使用属性驱动或常量输入调用服务的一些代码
}捕获(例外e){
e、 printStackTrace();
}
}
} 

在我的场景中,我模拟了100多个curl请求来初始化那些客户端池、预加载缓存或其他延迟加载的家伙

我在执行弹簧执行器健康检查端点的
预热助推器执行健康指示器执行此项工作

最后,在热身结束之前,Nginx(或其他负载平衡器)的任何healch检查都将获得5xx状态代码和body消息。状态更新后,应用程序初始化将不会花费任何流量时间

{
  "status": "DOWN",
  "details": {
    "warmup": {
      "status": "DOWN"
    },
    "diskSpace": {
      "status": "UP",
      "details": {
        "total": 536608768000,
        "free": 395195826176,
        "threshold": 10485760
      }
    }
  }
}

此外,
NGINX Plus
有一个付费功能,可以为您的兴趣做同样的事情。

这听起来更像是OpenShift配置问题。@chrylis您能详细说明一下吗?@Vikk,您也应该详细说明问题本身。你的申请是做什么的?我个人会尝试部署一个示例spring boot应用程序,并用它进行测试。如果同样的问题发生,那么它与openshift相关,可能是JVM/JIT预热时间。我猜是惰性类加载(对其而言,进行大量curl调用是一个良好的开端)或JIT优化(对其而言,仅调用关键代码100次是不够的)(默认值:
-xx:CompileThreshold=10000
afaik)。或者,根据应用程序实际执行的操作,可能需要预热缓存。您是否使用预部署的映像?每个实例的内存消耗是多少?是否可以增加每个节点和测试的总分配内存?