背景
Spring Cloud 服务默认在web server(如tomcat embedded sever)启动后立即进行服务注册,接入流量。启动后初始的服务请求执行较慢,可达到数秒,造成服务消费者超时出错或其它问题。
可以看到请求第一次很慢,因为需要初始化RibbonClient,这个是延迟加载。
饥饿加载
### Ribbon 配置
ribbon:
# 饥饿加载
eager-load:
# 是否开启饥饿加载
enabled: true
# 饥饿加载的服务
clients: service-hi
再看下结果,可以看到在启动时,就会初始化。
接下来做下简单分析。
可以看到RibbonAutoConfiguration#ribbonApplicationContextInitializer
会用于初始化Ribbon的上下文。
来到RibbonApplicationContextInitializer
,初始化ribbon的上线文是在spring上下文准备好的时候。
这个时候会有什么问题么,上次说到服务注册是在WebServerInitialized event,这个event是在ApplicationReadyEnvent之前的,ribbon client创建时,仍然可能有请求发过来,不能及时处理。服务调用还涉及到连接池、线程池的初始化,无法在实际请求之前预热处理。
改造
- 思路
通过改进Spring Cloud服务注册机制,提供服务预热扩展点,方便业务根据自身服务特点进行预热处理,预热完成后,再进行服务注册,接入流量。保证服务发布期间服务响应时间稳定,服务消费者不受影响。
代码
代码已放到github
核心代码如下:
- 复写了
NacosAutoServiceRegistration
方法,调用start方法为空方法,默认不去做初始化,即服务注册。
测试
- 加一个配置
2. 启动项目,可以看到做了初始化,访问之后时间变短了。