SpringCloud服務啓動後,接口第一次請求很慢的優化歷程
症狀概述
服務啓動後,請求任意接口,都很慢,響應時長達到2秒
而再次進行請求,響應很快,響應時長毫秒級。
初步診斷
很可能耗時資源在第一次接收到請求時才進行初始化
確定病因
上圖爲第一次請求時打印的日誌,由此可知第一次請求時初始化了DataSource、Redis、Servlet
還有個網上找到的Ribbon優化,默認client是懶加載,第一次請求才會進行初始化,所以這裏也會影響,需要進行優化
對症下藥
DataSource
DataSourceConfig配置類中修改:應用啓動時,進行初始化
@org.springframework.context.annotation.Bean(name = "dataSource",initMethod = "init",destroyMethod = "close")
public DruidDataSource dataSource() throws SQLException {
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(this.driverClassName);
ds.setUrl(this.url);
ds.setUsername(this.username);
ds.setPassword(this.password);
ds.setInitialSize(this.initialSize.intValue());
ds.setMinIdle(this.minIdle.intValue());
ds.setMaxActive(this.maxActive.intValue());
ds.setMaxWait(this.maxWait.longValue());
ds.setTimeBetweenEvictionRunsMillis(this.timeBetweenEvictionRunsMillis.longValue());
ds.setMinEvictableIdleTimeMillis(this.minEvictableIdleTimeMillis.longValue());
ds.setValidationQuery(this.validationQuery);
ds.setTestWhileIdle(this.testWhileIdle.booleanValue());
ds.setTestOnBorrow(this.testOnBorrow.booleanValue());
ds.setTestOnReturn(this.testOnReturn.booleanValue());
ds.setFilters(this.filters);
ds.init();
return ds;
}
DispatcherServlet
當值爲0或者大於0時,表示容器在應用啓動時就加載並初始化這個servlet
在配置文件上添加:
spring.mvc.servlet.load-on-startup=100
初始化Redis
像我這裏使用的是codis,封裝了一個工具類,第一次調用時會初始化
所以Redis工具類初始化方法上加 @PostConstruct
被@PostConstruct修飾的方法會在服務器加載Servlet的時候運行
Ribbon
Ribbon進行客戶端負載均衡的Client並不是在服務啓動的時候就初始化好的,而是在調用的時候纔會去創建相應的Client
所以第一次調用的耗時不僅僅包含發送HTTP請求的時間,還包含了創建RibbonClient的時間
飢餓加載
ribbon.eager-load.enabled=true
ribbon.eager-load.clients=member-api,activity-api