程序为什么慢?P1——启动时刻

67 阅读2分钟

欢迎来到啾啾的博客🐱。
记录学习点滴。分享工作思考和实用技巧,偶尔也分享一些杂谈💬。
有很多很多不足的地方,欢迎评论交流,感谢您的阅读和评论😄。

为什么程序启动慢?

框架初始化,如扫描配置文件、组件、AOP代理创建、Bean创建与注入等;
资源初始化,数据库连接池、线程池,消息队列、Redis连接等;
还有就是一些定义的初始化任务等……

  • 硬件性能差
    如果服务器以90%CPU负载启动程序,程序肯定快不了。

所以,可以通过以下手段提升启动速度。

  • 减少不必要的初始化
    没用的组件、依赖该删删
  • 异步不是立即要用的初始化
    异步执行一些非阻塞的初始化任务,比如初始化缓存、业务任务。

为什么程序启动后的方法调用特别慢?

首先,我们需要明白JVM的加载机制。

image.png JVM懒加载+编译解释导致方法第一次运行时较多次运行成为热点代码后是会慢不少。

一般来说可以通过预热(Warm-up)解决这个问题。在程序启动时,对用户最常访问、对性能最敏感的核心业务路径和方法进行预热。 要注意不要过度预热,不是所有代码都值得预热。

为什么Feign|OpenFeign第一次调用别的服务特别慢?

Feign和OpenFeign底层都是Http,属于TCP/IP协议,所以需要通过三次握手建立可靠信道。 同时,一般使用Feign|OpenFeign都是服务实例间调用,常配合Ribbon|LoadBalancer 使用,所以需要获取注册表用于调用。

这个问题的解决方法还是预热。

然后Ribbon可以配置ribbon.eager-load.enabled=true,这样程序启动后会获取实例列表。

LoadBalancer默认配置spring.cloud.loadbalancer.cache.enabled=true,会启动LoadBalancer的服务实例缓存。当这个缓存启用时,LoadBalancer在第一次为一个服务选择实例后,会将获取到的服务实例列表缓存起来(默认缓存时间TTL是35秒,可以通过 spring.cloud.loadbalancer.cache.ttl 配置)。后续对该服务的请求会优先从缓存中获取实例列表,直到缓存过期才会再次去服务注册中心拉取。