SpringBoot如何应用轻松上线

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 本文详细介绍了服务启动初期响应慢的问题及解决方案。首先,通过使用如`ewma`或`least_conn`等Ingress负载均衡算法,减少新启动Pod的请求量;其次,利用K8s探针实现应用预热,确保服务初始化后再接受用户请求;最后,针对Dubbo服务,介绍了其预热机制及线程池优化方案,并提供了Tomcat线程池、MySQL连接池及Redis连接池的预热示例。

背景

服务刚启动时,如果没有做任何优化的话,前面几分钟的请求,响应都会特别的慢。

下面,针对该问题,全方面介绍,如何解决!

Ingress 负载均衡

Ingress 负载均衡,可以考虑使用 ewma

nginx.ingress.kubernetes.io/load-balance=ewma

ewma 算法可以简单描述为:响应时间越长,分配的请求越少,这样刚启动的 pod, 就只会被分配到少量的流量。

有的云厂商,可能不支持 ewma 算法,也可以考虑使用 least_conn, 即最少请求数。

ewma 更多的内容

应用预热 - 自调用

在大部分框架中,大部分都存在懒加载情况。开始加载时,一般会使用锁来阻止并发。

如果在 Pod 接受用户请求后,再初始化,则会导致前面的几次请求特别慢。

因此,我们有必要在用户请求进入 Pod 前,对程序执行初始化。

初始化懒加载的代码,最简单的方式是在 Pod 对外提供服务前,进行自调用。

在 K8s 中,允许 Pod 定义 启动探针、就绪探针、存活探针。

当 K8s 就绪探针通过后,Pod 就可以对外提供服务了。

简单的说,我们可以等待程序完成自调用后,再通过就绪探针的探测。

大致的流程如下:

程序的自调用流程如下:

提高 cpu 上限

自调用的目的主要是为了提前初始化,而不是为了让 JIT 进行编译优化。(不排除有的服务,需要通过大量的自调用,来让 JIT 进行提前的编译优化。)

因为 Mock 过多的请求,会影响服务启动时间,也会影响 Pod 扩容。

在 Pod 启动后,接收请求的前几分钟,CPU 都会特别的高,从而影响用户线程。有比较大的方面是 JIT 的 C1, C2 线程会消耗大量的 CPU。

对于该问题,可以考虑设置更高的 resource.limits.cpu 来避免此问题。

K8s 探针更多信息

Dubbo 预热

Consumer 在调用 Provider 时,本身已经存在预热逻辑。

即:刚启动的 Provider 权重会比较低,并随着时间的增长,权重最终会和其他 Provider 一致。也就是说,刚启动的 Provider 只会接收到少量的请求。

需要注意的是:不同的 Dubbo 版本该逻辑可能会不一样。笔者所在的公司,Dubbo 版本为 2.7.12

预热代码位置:

AbstractLoadBalance#getWeight(Invoker, Invocation)

上诉说的是 Dubbo 本身已有的预热逻辑。

Dubbo Provider 线程池预热

Provider 线程池,默认为 fixed, 可通过 SPI 机制,自定义线程池,并初始化一定数量线程。

服务暴露前预热 Provider

Dubbo 服务暴露触发时机: Spring 容器完成刷新,触发 ContextRefreshedEvent 事件。

代码位置:DubboBootstrapApplicationListener#onApplicationContextEvent(ApplicationContextEvent)

我们可以监听 ContextRefreshedEvent 事件,实现 Ordered 接口,在 DubboBootstrapApplicationListener 逻辑执行前,执行预热 Provider 逻辑。

常见线程池预热

Tomcat 线程池预热

具体的线程数,需要根据应用自行评估

ini

代码解读

复制代码


server.tomcat.min-SpareThreads=20

Mysql 连接池预热

java

代码解读

复制代码

private ApplicationContext ac;

private void preheatDataSource() {
    Map<String, DataSource> map = ac.getBeansOfType(DataSource.class);
    if (CollectionUtils.isEmpty(map)) {
        return;
    }

    for (Map.Entry<String, DataSource> entry : map.entrySet()) {
        DataSource source = entry.getValue();
        if (source instanceof DruidDataSource) {
            DruidDataSource druidDataSource = (DruidDataSource) source;
            int initialSize = druidDataSource.getInitialSize();
            if (initialSize > 0) {
                try {
                    druidDataSource.fill(initialSize);
                } catch (Exception e) {
                }
            }
        }
    }
}

Redis 连接池预热

java

代码解读

复制代码

private ApplicationContext ac;

private void preheatRedis() {
    Map<String, RedisConnectionFactory> map = ac.getBeansOfType(RedisConnectionFactory.class);
    if (CollectionUtils.isEmpty(map)) {
        return;
    }

    for (Map.Entry<String, RedisConnectionFactory> entry : map.entrySet()) {
        RedisConnectionFactory connectionFactory = entry.getValue();
        List<RedisConnection> connections = new ArrayList<>(3);
        for (int i = 0; i < 3; i++) {
            connections.add(RedisConnectionUtils.getConnection(connectionFactory));
        }

        for (RedisConnection connection : connections) {
            RedisConnectionUtils.releaseConnection(connection, connectionFactory, false);
        }
    }
}

转载来源:https://juejin.cn/post/7374986809476923403

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
JavaScript 前端开发 NoSQL
如何免费将springboot+vue项目部署上线(云服务器+宝塔面板)
如何免费将springboot+vue项目部署上线(云服务器+宝塔面板)
686 0
|
Java 应用服务中间件 Linux
7、SpringBoot2.0如何打包部署上线(七)
1、打包一般分为两种;一种是打包成jar包直接执行,另一种是打包成war包放到tomcat服务器下。
160 0
7、SpringBoot2.0如何打包部署上线(七)
|
小程序 Java 网络安全
Spring Boot配置HTTPS,解决微信小程序上线问题
由于微信小程序在体验版和上线版本,需要用https连接,所以你需要申请一个域名,并为这个域名申请证书。怎么利用acme.sh免费申请证书在上篇文章有提到利用acme.sh免费建立https连接,这里就记录一下Spring Boot中配置HTTPS,再利用Docker进行部署。
382 0
|
运维 Java 测试技术
spring boot2.0项目如何开发、调试、打包到最后的投产上线(一)
有很多网友会时不时的问我,spring boot项目如何测试,如何部署,在生产中有什么好的部署方案吗?这篇文章就来介绍一下spring boot 如何开发、调试、打包到最后的投产上线。   
273 0
|
存储 数据采集 JSON
基于springboot+redis+国际化+定时任务的疫情项目【已上线】
这是我自己做的一套疫情实时数据项目,有地图、折线图、表格 该项目涵盖了大部分springboot项目实际开发所必需的技术 因为爬取的页面官网做了变更,所以会有一些小问题,需要自行处理。
339 0
基于springboot+redis+国际化+定时任务的疫情项目【已上线】
|
云安全 JavaScript 前端开发
初次使用阿里云将springBoot结合Vue项目部署上线
前后分离SpringBoot结合Vue,通过jar包打包方式,部署到阿里云服务器上线。
|
10天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的服装商城管理系统
基于Java+Springboot+Vue开发的服装商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的服装商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
32 2
基于Java+Springboot+Vue开发的服装商城管理系统
|
10天前
|
前端开发 JavaScript Java
SpringBoot项目部署打包好的React、Vue项目刷新报错404
本文讨论了在SpringBoot项目中部署React或Vue打包好的前端项目时,刷新页面导致404错误的问题,并提供了两种解决方案:一是在SpringBoot启动类中配置错误页面重定向到index.html,二是将前端路由改为hash模式以避免刷新问题。
52 1
|
8天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的大学竞赛报名管理系统
基于Java+Springboot+Vue开发的大学竞赛报名管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的大学竞赛报名管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
23 3
基于Java+Springboot+Vue开发的大学竞赛报名管理系统
|
9天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的蛋糕商城管理系统
基于Java+Springboot+Vue开发的蛋糕商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的蛋糕商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
21 3
基于Java+Springboot+Vue开发的蛋糕商城管理系统
下一篇
无影云桌面