记springboot程序启动慢解决。
今天将程序发给别人后,别人立马说你这个启动很慢。
查看程序启动耗时分布
<!--启动耗时监测-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
management:
endpoints:
web:
exposure:
include: startup
修改启动类:
@SpringBootApplication
@MapperScan("com.huishi.mapper")
public class LljkApplication {
public static void main(String[] args) {
// SpringApplication.run(LljkApplication.class, args);
new SpringApplicationBuilder(LljkApplication.class)
.applicationStartup(new BufferingApplicationStartup(20480))
.run(args);
System.out.println("============启动成功");
}
}
然后发送POST请求到/actuator/startup接口就会返回程序启动的耗时分布,然后我发现是dataSource xxxDataMapper sqlSessionFactory这几个bean初始化时间太长了,有30几秒,这一看就知道是和数据库源有关。
由于是启动很慢,所以猜测是程序启动时在创建数据库连接池的时,需要创建指定数量的数据库连接慢导致的。
建立数据库连接流程
MySQL服务器收到来自客户端的tcp连接请求后,服务器会根据客户端IP到host_cache查询是否存在有效的解析记录,如果有直接创建成功。
没有或HOST_VALIDATED为NO,就会对IP进行DNS解析,首先通过IP解析出主机名,再将主机名进行解析出IP,将这两次IP进行比对,如果一样,则解析成功,并将HOST_VALIDATED设为YES。如果解析失败,判断失败的原因是永久的还是临时的,如果是永久的,则HOST的值依旧为NULL,且将HOST_VALIDATED的值设置为YES,后续连接不再进行解析,如果该原因是临时的,则HOST_VALIDATED依旧为NO,后续连接会再次进行DNS解析。
查看host_cache表
mysql> select * from performance_schema.host_cache\G
*************************** 1. row ***************************
IP: 192.168.31.47 #连接到服务器的客户端IP地址
HOST: NULL #客户端DNS解析出的主机名,null代表未知
HOST_VALIDATED: NO #是否执行了DNS解析,如果值为YES则主机列将用作与IP相对应的主机名,以便可以避免对DNS的其他调用;如果值为NO则每次连接尝试都会尝试DNS解析,直到最终以有效结果或永久错误完成解析
SUM_CONNECT_ERRORS: 0 #被视为“阻塞”的连接错误数,仅统计协议握手错误,并且仅统计HOST_VALIDATED=YES的主机
COUNT_HOST_BLOCKED_ERRORS: 0 #以下为各种连接方式失败的计数
COUNT_NAMEINFO_TRANSIENT_ERRORS: 0
COUNT_NAMEINFO_PERMANENT_ERRORS: 1
COUNT_FORMAT_ERRORS: 0
COUNT_ADDRINFO_TRANSIENT_ERRORS: 0
COUNT_ADDRINFO_PERMANENT_ERRORS: 0
COUNT_FCRDNS_ERRORS: 0
COUNT_HOST_ACL_ERRORS: 0
COUNT_NO_AUTH_PLUGIN_ERRORS: 0
COUNT_AUTH_PLUGIN_ERRORS: 0
COUNT_HANDSHAKE_ERRORS: 0
COUNT_PROXY_USER_ERRORS: 0
COUNT_PROXY_USER_ACL_ERRORS: 0
COUNT_AUTHENTICATION_ERRORS: 17
COUNT_SSL_ERRORS: 0
COUNT_MAX_USER_CONNECTIONS_ERRORS: 0
COUNT_MAX_USER_CONNECTIONS_PER_HOUR_ERRORS: 0
COUNT_DEFAULT_DATABASE_ERRORS: 0
COUNT_INIT_CONNECT_ERRORS: 0
COUNT_LOCAL_ERRORS: 0
COUNT_UNKNOWN_ERRORS: 0
FIRST_SEEN: 2020-12-18 10:30:03 #客户端第一次尝试连接的时间戳
LAST_SEEN: 2020-12-18 14:50:41 #客户端看到最新的连接尝试的时间戳
FIRST_ERROR_SEEN: 2020-12-18 10:30:03 #第一次连接错误的时间戳
LAST_ERROR_SEEN: 2020-12-18 14:46:37 #最近一次连接错误的时间戳
1 row in set (0.00 sec)
参数 host_cache_size与skip_name_resolve 的作用
host_cache_size:控制主机缓存的数量,设置为0时,禁用主机缓存,每次服务器连接时,服务器都会进行DNS查找,相比skip-host-cache来说,host_cache_size更加灵活,可以随时变更或禁用。
skip_name_resolve:检查客户端连接时是否进行DNS解析IP主机名,默认是关闭的,则MySQL服务器会在检查客户端连接时解析主机名。若开启,则跳过这个DNS解析的过程,就只用IP ;在这种情况下,授权表中的所有列值都必须是 IP地址。
有些时候DNS 解析延迟或者网络环境不稳定的情况下,可以设置这个配置从而跳过DNS解析的过程,加快数据库连接速度。
解决方式
因为我们程序在启动时,需要创建不止一条数据库连接,有时需要创建多个数据库连接放入数据库连接池,然而每条都进行DNS解析就导致速度很慢,可以直接跳过。
在mysql的配置文件my.ini中增加以下配置:
[mysqld]
skip-name-resolve
开启这个配置后,就不能基于主机进行授权了,一般IP是多变的,但是主机名是不变的,所以基于主机HOST授权只需授权一次。开启这个配置需要基于IP进行授权。