V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
shayang888
V2EX  ›  Java

springboot 启动后,第一次的接口请求总是很慢,后面速度就很快,怎么解决?

  •  1
     
  •   shayang888 · 2019-11-19 14:07:59 +08:00 · 14266 次点击
    这是一个创建于 1592 天前的主题,其中的信息可能已经有所发展或是发生改变。
    [ctor-http-nio-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
    [ctor-http-nio-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
    

    启动的时候看了下,并没有这段日志,第一次请求接口的时候,访问了数据库然后就出现了这个,再次请求的时候也没有再出现了。

    现在问题就是第一次请求的时候因为这个造成速度特别慢,有啥办法可以解决吗

    第 1 条附言  ·  2019-11-19 16:53:13 +08:00
    @SpringBootApplication
    @RestController
    public class DemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    
        @GetMapping(path = "/test")
        public String test() {
            return "test";
        }
    }
    

    就这么一个随便的接口,访问的时候也是第一次请求慢,后面的都是秒返回,这到底是为啥?

    33 条回复    2020-05-19 14:36:08 +08:00
    ifreeky
        1
    ifreeky  
       2019-11-19 14:13:44 +08:00
    第一次请求需要获取数据库连接。
    shayang888
        2
    shayang888  
    OP
       2019-11-19 14:21:20 +08:00
    @ifreeky 是的,所以可不可以在 springboot 启动的同时就获取数据库连接呢?
    arraysnow
        3
    arraysnow  
       2019-11-19 14:26:34 +08:00   ❤️ 9
    spring boot 默认配置三个深坑,一个比一个耗时
    1、dispatcherServlet 是懒加载的
    2、数据库链接是懒加载的
    3、linux 下真随机数生成器
    qiyuey
        4
    qiyuey  
       2019-11-19 14:26:37 +08:00
    业务侧预热,或者 DB 预连接,Druid 是支持的,别的不清楚了
    scukmh
        5
    scukmh  
       2019-11-19 14:31:55 +08:00
    linux 下真随机数生成器可否给个链接呢? google 没 google 到
    @arraysnow
    arraysnow
        6
    arraysnow  
       2019-11-19 14:34:57 +08:00
    @scukmh https://www.jianshu.com/p/5fe0e6fde941
    用伪随机数生成器,真随机数生成器的噪声收集要很久
    shayang888
        7
    shayang888  
    OP
       2019-11-19 14:47:29 +08:00
    @arraysnow 所以第二个没得解吗?
    gejun123456
        8
    gejun123456  
       2019-11-19 15:10:22 +08:00
    @shayang888 #7 可以把,在 springboot 启动的时候就去调用下数据库就好了把
    w292614191
        9
    w292614191  
       2019-11-19 15:49:08 +08:00
    启动时候初始化一个,
    spring.datasource.druid.initial-size=1
    这样,你可以观察启动日志,有个 database inited....
    arraysnow
        10
    arraysnow  
       2019-11-19 15:55:48 +08:00
    @shayang888 简单粗暴的方式 @PostContrust 里面"SELECT 1",让他在启动时候查一下数据库
    chendy
        11
    chendy  
       2019-11-19 16:18:32 +08:00   ❤️ 1
    对于 3 楼说的
    1. 设置 spring.mvc.servlet.load-on-startup=1
    2. 启动方法拿个 dao 的 bean,跑个小查询
    3. 加启动参数 -Djava.security.egd=file:/dev/./urandom
    shayang888
        12
    shayang888  
    OP
       2019-11-19 16:20:08 +08:00
    @w292614191
    @gejun123456
    我更换成了 druid 的连接源,还是一样的,第一次请求慢
    troywinter
        13
    troywinter  
       2019-11-19 16:25:12 +08:00
    你们用 java 写服务,不预热???
    shayang888
        14
    shayang888  
    OP
       2019-11-19 16:43:40 +08:00
    @arraysnow
    @chendy
    我刚才试了下,即使不去和数据库交互,随便写个接口,也是第一次请求的时间长,后续短
    geying
        15
    geying  
       2019-11-19 16:51:19 +08:00
    Controller 第一次访问要实例化?
    shayang888
        16
    shayang888  
    OP
       2019-11-19 16:51:30 +08:00
    @arraysnow
    @chendy

    @SpringBootApplication
    @RestController
    public class DemoApplication {

    public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
    }

    @GetMapping(path = "/test")
    public String test() {
    return "test";
    }
    }
    就这一个随便的接口,也是第一次请求的时间长,后面就秒返回
    shayang888
        17
    shayang888  
    OP
       2019-11-19 16:52:12 +08:00
    @geying 怎么说?
    johnniang
        18
    johnniang  
       2019-11-19 16:57:54 +08:00 via Android
    https://spring.io/blog/2019/10/16/spring-boot-2-2-0

    不知道是不是因为懒加载的缘故。
    wysnylc
        19
    wysnylc  
       2019-11-19 17:00:01 +08:00
    @arraysnow #6 跟 spring boot 无关,是 jvm 的熵池问题
    chendy
        20
    chendy  
       2019-11-19 17:00:41 +08:00
    debug=true,看日志吧
    spring.mvc.servlet.load-on-startup=1 效果其实不大
    shayang888
        21
    shayang888  
    OP
       2019-11-19 17:04:49 +08:00
    @chendy
    2019-11-19 17:02:31.814 DEBUG 53080 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter : [17aa98db] HTTP GET "/test"
    2019-11-19 17:02:31.839 DEBUG 53080 --- [ctor-http-nio-3] s.w.r.r.m.a.RequestMappingHandlerMapping : [17aa98db] Mapped to com.example.demo.DemoApplication#test()
    2019-11-19 17:02:31.856 DEBUG 53080 --- [ctor-http-nio-3] o.s.w.r.r.m.a.ResponseBodyResultHandler : Using 'text/plain;charset=UTF-8' given [*/*] and supported [text/plain;charset=UTF-8, text/event-stream, text/plain;charset=UTF-8, */*]
    2019-11-19 17:02:31.857 DEBUG 53080 --- [ctor-http-nio-3] o.s.w.r.r.m.a.ResponseBodyResultHandler : [17aa98db] 0..1 [java.lang.String]
    2019-11-19 17:02:31.860 DEBUG 53080 --- [ctor-http-nio-3] o.s.core.codec.CharSequenceEncoder : [17aa98db] Writing "test"
    2019-11-19 17:02:31.877 DEBUG 53080 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter : [17aa98db] Completed 200 OK
    --------------------------------------------------------------
    2019-11-19 17:02:33.311 DEBUG 53080 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter : [17aa98db] HTTP GET "/test"
    2019-11-19 17:02:33.312 DEBUG 53080 --- [ctor-http-nio-3] s.w.r.r.m.a.RequestMappingHandlerMapping : [17aa98db] Mapped to com.example.demo.DemoApplication#test()
    2019-11-19 17:02:33.312 DEBUG 53080 --- [ctor-http-nio-3] o.s.w.r.r.m.a.ResponseBodyResultHandler : Using 'text/plain;charset=UTF-8' given [*/*] and supported [text/plain;charset=UTF-8, text/event-stream, text/plain;charset=UTF-8, */*]
    2019-11-19 17:02:33.312 DEBUG 53080 --- [ctor-http-nio-3] o.s.w.r.r.m.a.ResponseBodyResultHandler : [17aa98db] 0..1 [java.lang.String]
    2019-11-19 17:02:33.312 DEBUG 53080 --- [ctor-http-nio-3] o.s.core.codec.CharSequenceEncoder : [17aa98db] Writing "test"
    2019-11-19 17:02:33.315 DEBUG 53080 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter : [17aa98db] Completed 200 OK

    2 次的时间明显不一样,第一次花了 60 多 ms,第二次直接 3ms 就完成了
    shayang888
        22
    shayang888  
    OP
       2019-11-19 17:05:48 +08:00
    @wysnylc
    @johnniang
    你们都没遇到过这种情况吗?
    wysnylc
        23
    wysnylc  
       2019-11-19 17:08:16 +08:00
    @shayang888 #22 你这就是 lazy 懒加载导致的,没别的的可能
    shayang888
        24
    shayang888  
    OP
       2019-11-19 17:16:00 +08:00
    @wysnylc 那请问怎么解决呢
    arraysnow
        25
    arraysnow  
       2019-11-19 17:20:45 +08:00
    @shayang888 11 楼告诉你了
    wysnylc
        26
    wysnylc  
       2019-11-19 17:25:28 +08:00
    @shayang888 #24 熵池问题:https://blog.csdn.net/wysnxzm/article/details/98482143
    spring 第一次访问慢问题:https://www.cnblogs.com/haitao-fan/p/10319920.html
    数据库的你自己找配置属性吧我忘了,上面的同学已经给你点名了问题,希望你学会用百度
    chendy
        27
    chendy  
       2019-11-19 17:52:52 +08:00
    几十毫秒的差距而已…
    并发请求的话你会看到很多个几十毫秒,应该是 tomcat 内部的一些预热逻辑
    自己预热 /无视 即可
    luopengfei14
        28
    luopengfei14  
       2019-11-19 19:54:33 +08:00 via iPhone
    在 @postconstructs 注解,
    在该注解的方法中发起一次数据库查询。
    这样等 springboot 启动完后,数据库连接池已经建立好了。
    之前我们项目是在这个方法获取动态的项目配置数据。
    Caballarii
        29
    Caballarii  
       2019-11-19 20:17:22 +08:00
    搞半天搞 1,2,说不定直接动 3 就好了
    vjnjc
        30
    vjnjc  
       2019-11-20 00:34:43 +08:00
    @chendy #11 的第三点给错了吧,原贴#3 的真随机数是 /dev/random。/dev/urandom 更快但是更假。
    shitcode
        31
    shitcode  
       2020-04-07 20:21:24 +08:00
    urandom 试了没卵用,启动时预热有效果。
    Ahy
        32
    Ahy  
       2020-05-19 14:35:47 +08:00
    hello 最后怎么解决的呢? 有什么解决方案么?
    Ahy
        33
    Ahy  
       2020-05-19 14:36:08 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2796 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 15:02 · PVG 23:02 · LAX 08:02 · JFK 11:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.