快如闪电的扩容:秒级启动,弹性伸缩让您无忧

本文涉及的产品
函数计算FC,每月15万CU 3个月
日志服务 SLS,月写入数据量 50GB 1个月
云原生 API 网关,700元额度,多规格可选
简介: 快如闪电的扩容:秒级启动,弹性伸缩让您无忧


快速扩容:秒级启动,弹性伸缩

服务器秒级启动

阿里云的ACK可以做到秒级启动,文档说明:通过kubectl快速搭建魔方游戏

华为云的云容器引擎 CCE可以做到秒级启动,访问链接:https://www.huaweicloud.com/product/cce.html

服务秒级启动

服务启动没有相关的产品,大多数情况都很难做到真正的秒级启动,通常都是对其进行优化,提供访问速度。

Spring Boot应用程序可以使用Spring Boot内置的Tomcat服务器快速启动,但它并不支持秒级启动。然而,对于需要秒级启动的场景,可以考虑使用以下几个方案:

升级JDK的版本

高版本的jdk做了很多优化,能提升服务启动的速度,例如jdk21版本优化了虚拟线程提升并发、新的垃圾回收器更强劲,更好的算法、更高效的工具或更新的类库版本,都有助于提高应用程序的性能和启动速度。

通过将应用程序打包成WAR文件并部署到已经启动的Tomcat服务器上来实现秒级启动

这种方式可以使用Spring Boot的maven插件将应用程序打包成WAR文件,并将WAR文件部署到Tomcat服务器中。这样做可以节省启动服务器的时间,但仍然需要一定的时间来完成新应用程序的部署和启动。当你将WAR文件部署到Tomcat服务器上时,Tomcat会自动将该WAR文件解压缩到一个文件夹中,并在服务器上自动创建一个应用程序上下文。应用程序上下文是指虚拟Web应用程序的目录,其中存放了Web应用程序的资源文件,包括JSP文件、HTML文件、Servlet类文件等。一旦应用程序上下文被创建,Tomcat就会将该应用程序注册到Servlet容器中,以便于处理客户端请求。客户端可以通过Web浏览器访问应用程序上下文,访问应用程序中的不同资源。因此,当WAR文件部署到Tomcat服务器上时,Tomcat会自动将应用程序注册到Servlet容器中,并开始处理客户端发来的请求,从而实现对应用程序接口的访问。

使用Spring Boot的maven插件将应用程序打包成WAR文件非常简单,只需要在pom.xml文件中添加以下配置:

<packaging>war</packaging>
<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <version>2.5.2</version>
      <executions>
        <execution>
          <goals>
            <goal>repackage</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>
使用Spring Cloud Function和云原生技术来构建无服务器应用程序,可以实现秒级启动

Spring Cloud Function是可以部署在云平台上的无状态函数式服务框架,可以将Spring Boot应用程序转换为无服务器函数。这种方式可以使用AWS Lambda或Google Cloud Functions等云原生平台。Spring Cloud Function是一款基于Spring Framework构建的,支持编写无服务器Lambda函数的工具,使用它可以让开发人员轻松地将Spring应用程序转换为无服务器Lambda函数。

Spring Cloud Function使用了几种技术来缩短应用程序启动时间

1、预热机制 预热机制可以缩短Lambda函数的启动时间。在函数被调用前,Lambda使用一个空白的容器(Cold Start)启动,这是因为为了避免资源浪费,AWS将容器变成了实例(Instance)而不是台机器。当函数被第一次调用时,AWS会立即触发容器的启动,这个过程叫做冷启动(Cold Start)。预热机制可以在函数被调用之前自动启动一个Lambda函数,并将其保持为热状态,从而避免了冷启动的成本。在每次函数调用之前,该函数将被预先热一段时间,这个时间的长度可以通过配置控制。

2、功能模块化 将应用程序划分为模块,每个模块都相对独立,可以独立部署和运行。在无服务器环境下,可以使用这种方式来降低应用程序的启动时间。因为只有需要的模块被加载,所以可以减少应用程序的启动时间。

3、JVM缓存 在无服务器环境中,由于Lambda函数的生命周期非常短,一旦函数执行完成,Lambda函数就会被销毁。为了加快应用程序的启动时间,可以使用JVM缓存技术。JVM缓存存储应用程序已经编译的代码和类文件,当函数需要被调用时,只需要从JVM缓存中加载类文件和代码,而不需要重新编译代码和加载类文件,从而大大缩短了应用程序的启动时间。

实现秒级启动的步骤
将应用程序划分为可独立部署和运行的模块

一个大型的应用程序往往包含很多个子模块,例如用户管理、订单管理、库存管理等等。为了实现秒级启动,我们可以将应用程序划分为可独立部署和运行的模块。每个模块都可以独立部署和运行,不会对其他模块造成影响。这样,当需要更新或调整某个模块时,只需要重新部署该模块,而不需要重新部署整个应用程序。这样可以大大减少部署时间和启动时间。

使用JVM缓存技术,预热机制和功能模块化来缩短Lambda函数的启动时间。

Lambda函数的启动时间包括3个部分:加载Lambda函数代码、初始化JVM运行时环境和执行Lambda函数。为了缩短Lambda函数的启动时间,我们可以采用以下方法:

一、使用JVM缓存技术

JVM缓存技术可以让JVM在运行时缓存Lambda函数的代码和资源,避免重复加载和初始化,从而加快Lambda函数的启动速度。

JVM缓存技术是利用ClassLoader缓存机制实现的。ClassLoader是Java程序运行中负责加载类、资源的组件,ClassLoader负责将类、资源加载到JVM中。Lambda函数的代码和资源也是由ClassLoader加载到JVM中的。

JVM缓存技术的原理是,当JVM第一次加载Lambda函数时,ClassLoader会将Lambda函数的代码和资源缓存到内存中。当下次使用同一Lambda函数时,ClassLoader会从缓存中获取Lambda函数的代码和资源,从而避免了重复加载和初始化。

虽然缓存可以提高启动速度,但是过度依赖缓存也会导致代码可维护性、可扩展性等方面的问题。因此,在使用JVM缓存技术时,应该把控好缓存的范围和适用场景,避免过度依赖缓存。

在使用JVM缓存技术时,也要注意避免内存泄漏的问题。如果缓存的对象没有及时释放,就会导致内存占用过高,从而影响系统的性能和稳定性。因此,在使用JVM缓存技术时,要注意及时释放缓存对象。

由于Lambda函数和方法引用本质上是代码和资源的引用,因此,在使用JVM缓存技术时,也要注意避免序列化问题。如果Lambda函数或方法引用被序列化后再反序列化,就可能导致代码和资源的丢失,从而导致程序出错。

二、预热机制

预热机制可以在启动Lambda函数之前,提前加载和初始化一些常用的类和库,从而避免在执行Lambda函数时进行加载和初始化,从而加快Lambda函数的启动速度。虽然Lambda是无服务器计算,但是启动Lambda函数的过程并不是从零开始,而是需要一些时间来加载和初始化Lambda函数。这通常是由于需要加载和初始化一些依赖项(如库、框架和类),这些依赖项与Lambda函数的执行代码相关联。这个过程被称为“启动延迟”。

启动延迟是Lambda函数的一个重要因素,因为它可以影响Lambda函数的性能和可扩展性。一个启动较慢的Lambda函数会导致更多的人等待请求的响应,这会影响用户体验。同时,如果您的Lambda函数处理大量请求,您可能需要扩展使用多个实例,而如果每个实例都需要花费很长时间来初始化,那么这个过程就会变得非常低效。因此,需要一种机制来减少启动延迟。

在实施预热机制之前,您需要确定哪些库和类是最常用的,并将它们列为预热列表。预热列表应该基于Lambda函数的实际使用情况,以及预热后能够显着减少启动时间的类和库。您还需要考虑预热过程对Lambda函数的内存使用和执行时间的影响。

预热Lambda函数是一个在启动Lambda函数之前运行的进程。该进程加载和初始化预热列表中的类和库,并执行一些预热任务,以确保它们已经准备好了。预热任务可以包括调用一些函数,设置变量和对象实例等。

预热结果应该被缓存,以便当Lambda函数需要使用它们时可以快速获取。缓存可以在内存中完成,这样可以减少磁盘I/O和网络请求,从而提高性能。您可以使用AWS Lambda的环境变量来存储预热结果,或者将它们存储在Lambda函数的本地文件系统上。

当Lambda函数启动时,它可以从缓存中获取预热结果,并直接使用它们,从而避免在执行过程中加载和初始化。这样可以大大减少Lambda函数的启动时间,提高性能和可扩展性。

实施预热机制需要以下步骤:

1、创建预热脚本

预热脚本是用来加载和初始化预热列表中的类和库的代码。该脚本应该在Lambda函数启动之前运行,并将预热结果缓存到环境变量或本地文件系统中。您可以使用Python、Node.js和其他支持的语言来编写预热脚本。

2、将预热脚本打包到Lambda函数中

将预热脚本打包到Lambda函数中,以便在Lambda函数启动时自动运行。您可以使用AWS CLI或AWS Lambda Console来上传Lambda函数。

3、设置Lambda函数的环境变量

将预热结果缓存到Lambda函数的环境变量中,以便在Lambda函数启动时直接使用。您可以使用AWS Lambda Console或AWS CLI来设置环境变量。

4、在Lambda函数中使用预热结果

Lambda函数可以从环境变量中获取预热结果,并直接使用它们,从而避免在执行过程中加载和初始化。您可以使用Python、Node.js和其他支持的语言来访问环境变量。

三、功能模块化

将Lambda函数按照功能模块划分,分别加载和初始化,从而避免加载和初始化整个Lambda函数的代码和资源,从而加快Lambda函数的启动速度。以下是按模块分离Lambda函数的最佳实践和建议:

  1. 将Lambda函数分成尽可能小的模块。每个模块应该只包含必要的代码和资源。
  2. 为每个模块创建单独的ZIP文件。这可以避免不必要的资源消耗并提高启动速度。
  3. 在Lambda函数的初始化代码中,加载所有必要的模块。这将确保只加载必要的代码和资源。
  4. 在需要时(例如,处理请求时),再加载其他模块。这将确保仅加载必要的代码和资源。
  5. 最小化使用外部依赖项。每个依赖项都需要加载和初始化,这会增加Lambda函数的启动时间。
  6. 对于大型Lambda函数,考虑使用AWS Lambda的可扩展性和高可用性功能。这将确保Lambda函数可以在需要时自动扩展,并提供更好的性能和可靠性。
使用无服务器架构来运行应用程序

无服务器架构可以让应用程序在云端运行,无需管理服务器和基础架构,从而大大缩短部署时间和启动时间。当需要扩展应用程序时,只需要增加云资源,而不需要购买和配置服务器。

无服务器架构(Serverless Architecture),也被称为函数即服务(Function as a Service, FaaS),是一种新的云计算模型,它让应用程序在云端运行,无需管理服务器和基础架构,从而大大缩短部署和启动时间,降低了运维成本,提高了应用程序的可扩展性和弹性。

与传统的基于虚拟机或容器的云计算模型不同,无服务器架构将服务的代码运行部分和基础设施的管理部分进行了分离。在传统的模型中,开发人员需要对服务器的配置、监控和维护进行管理,而在无服务器架构中,这些都是由云服务提供商(如AWS、Azure和Google Cloud等)来管理的。这使得开发人员可以专注于应用程序的开发,而不必担心基础架构的管理和维护。

无服务器架构的基本特点包括:

(1)事件驱动:无服务器架构基于事件驱动的编程模型,应用程序的代码仅在需要处理事件(如HTTP请求)时才被执行。这种编程模型可以让应用程序具有高度的弹性和可伸缩性,可以自动地扩展和收缩应用程序的资源。

(2)按需计费:无服务器架构的计费模式是按照实际的使用量来计费的。也就是说,只有当应用程序被执行时,才会进行计费,这可以大大降低应用程序的成本。

(3)无服务器管理:开发人员无需管理服务器和基础架构,不需要安装、配置和维护操作系统、Web服务器和数据库等组件。这样可以大幅降低了开发人员的工作量,同时也降低了出错的可能性。

(4)高可用性:无服务器架构具有高度的可靠性和弹性,可以自动地将应用程序的实例分布在多个数据中心,并自动处理服务器故障和其他问题。这种方式大幅提高了应用程序的可用性和可靠性。

无服务器架构的工作原理可以简述为:

(1)应用程序开发人员编写代码,将其上传到无服务器平台上。

(2)无服务器平台根据应用程序的事件驱动模型,将应用程序代码分解为函数。

(3)无服务器平台将这些函数存储在云环境中,并提供API接口,以便应用程序可以调用这些函数。

(4)当应用程序需要处理事件时,它将发送请求到无服务器平台,请求执行相应的函数。

(5)无服务器平台根据请求执行相应的函数,并返回结果给应用程序。

(6)无服务器平台根据应用程序的负载自动扩展和收缩函数的实例,并根据需要调整资源。

无服务器架构的基本组件包括:

(1)函数:函数是无服务器架构中最基本的组件,它是应用程序代码的基本单位。函数通常只完成一个简单的操作,并以无状态的方式运行。无服务器平台可以自动地为函数分配资源,并执行多个函数实例来处理请求。

(2)触发器:触发器是无服务器架构中的事件源,它会触发函数的执行。触发器可以是各种事件源,包括HTTP请求、消息队列、定时器和文件上传等。触发器可以自动地调用函数,无需手动配置。

(3)API网关:API网关是无服务器架构中的API中间件,它负责为应用程序提供外部访问的接口。API网关可以接受HTTP请求,并将请求转发给相应的函数处理。API网关还可以进行请求身份验证和授权,以确保应用程序的安全性。

(4)数据存储:数据存储是无服务器架构中的持久层,它可以为应用程序提供数据的存储和检索能力。数据存储可以是关系型数据库(如MySQL和PostgreSQL)或NoSQL数据库(如MongoDB和DynamoDB)等。

(5)日志和监控:日志和监控是无服务器架构中的管理工具,它可以提供应用程序的运行日志、性能指标和错误报告等。日志和监控还可以帮助开发人员优化应用程序的性能,并及时处理错误和故障。

函数的生命周期是指函数从创建到销毁的整个过程。无服务器架构中的函数生命周期可以分为以下几个阶段:

(1)创建:函数是在开发人员上传代码之后创建的。当代码被上传到无服务器平台时,无服务器平台将会自动地分解代码为多个函数,并将其存储在云环境中。

(2)部署:函数被部署到云环境中,并分配所需的资源(例如CPU、内存和网络带宽)。函数的部署可以根据应用程序的负载自动地进行扩展和收缩。

(3)执行:当应用程序需要执行函数时,它会向无服务器平台发送请求。无服务器平台会根据请求自动分配函数实例,并执行函数。函数可以访问应用程序的数据存储和其他服务。

(4)日志和监控:当函数执行时,无服务器平台会记录函数的运行日志和性能指标,并生成报告和警报。开发人员可以使用这些日志和监控数据来优化函数的性能,并快速处理错误和故障。

(5)销毁:当函数不再需要时,它会被销毁。无服务器平台会自动地回收函数的所有资源,并将其从云环境中删除。

使用AWS Lambda、Azure Functions、Google Cloud Functions等云服务提供商来托管应用程序

AWS Lambda、Azure Functions、Google Cloud Functions等云服务提供商提供了一种快速托管应用程序的方法。这些服务可以自动管理服务器和基础架构,而且还提供了很多高级功能,例如自动扩展、自动备份、自动恢复等等。使用这些云服务提供商可以大大加快应用程序的启动速度和运行效率。AWS Lambda、Azure Functions、Google Cloud Functions 都是云服务提供商,提供了一种快速托管应用程序的方法。它们可以自动管理服务器和基础架构,提供了很多高级功能,例如自动扩展、自动备份、自动恢复等等。

AWS Lambda 是由亚马逊公司提供的一种无服务器计算服务,可以让您运行代码而无需自己管理服务器。此服务可以自动扩展应用程序、自动备份和恢复,并支持多种编程语言和运行时。

Azure Functions 是由微软提供的一种无服务器计算服务,可以让您在云中运行代码而无需管理服务器。此服务支持多种编程语言和运行时。

Google Cloud Functions 是由谷歌提供的一种无服务器计算服务,可以让您在云中运行代码而无需管理服务器。此服务支持多种编程语言和运行时。

使用Spring Boot的DevTools模块支持应用程序的热重载,可以在不重新启动应用程序的情况下更新应用程序

Spring Boot的DevTools还提供了一些其他开发工具,例如自动重启功能,可以在修改代码后自动重启应用程序。这种方式虽然不能实现秒级启动,但可以在开发过程中提高开发效率。需要在Maven或Gradle依赖中添加以下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
</dependency>

自动重启功能的原理实现是非常简单的。在启用自动重启功能后,DevTools会在后台启动一个额外的进程,这个进程会监控应用程序的类文件和资源文件的变化。

当我们修改了类文件和资源文件后,DevTools会通知应用程序的主进程,告诉它需要重新启动。为了避免频繁的重启,DevTools还提供了一个延迟时间(默认为1秒),在这个时间内如果有更改则不会重启,否则会启动一个新的进程来代替原来的应用程序进程。

当应用程序重启时,DevTools会重新加载所有的类文件和资源文件,确保应用程序的状态保持不变。这个过程类似于一个完整的应用程序启动过程,包括Spring的启动过程和应用程序的初始化过程。

自动重启功能的优点是显而易见的。它可以让我们在开发过程中快速验证更改,提高开发效率。在少量代码修改的情况下,重启的时间可以做到秒级。

但是自动重启功能也有一些缺点。首先,重启应用程序需要一定的时间,如果代码修改比较频繁,反复重启会浪费大量的时间。其次,重启应用程序可能会导致应用程序状态的丢失,例如内存中的变量和缓存等。因此,在开发过程中,我们应该尽量避免在应用程序运行时修改代码。

弹性伸缩

创建专用网络VPC

安全组

创建云服务器

打包部署

Java环境
#下载jdk17
wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz
#安装上传工具 以后使用命令 rz  选中文件进行上传
yum install -y lrzsz
#解压
tar -xzvf jdk-17_linux-x64_bin.tar.gz
#移动到指定位置; 记住全路径: /opt/user/jdk-17.0.8
mv jdk-17.0.8 /opt/user/jdk-17.0.8
#配置环境变量   /opt/jdk-17.0.2
vim /etc/profile
#在最后加入下面配置,注意修改 JAVA_HOME位置为你自己的位置
export JAVA_HOME=/opt/user/jdk-17.0.8
export PATH=$JAVA_HOME/bin:$PATH
#使环境变量生效
source /etc/profile
#验证安装成功
java -version

启动项目

测试能否访问

开机启动任意服务

作为基础服务器,需要配置开机自启服务,方便后面自动伸缩以这台服务器为主,扩容服务器能实现开机运行java服务。

1. 制作服务文件
cd /usr/lib/systemd/system
vim springbootapp.service
#内容如下
[Unit]
Description=springbootapp
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
ExecStart=/opt/app/app-start.sh
ExecStop=/opt/app/app-stop.sh
PrivateTmp=true
[Install]
WantedBy=multi-user.target
2. 制作启动脚本
vim app-start.sh

内容如下

#!/bin/sh
export JAVA_HOME=/opt/jdk-17.0.2
export PATH=$JAVA_HOME/bin:$PATH
nohup java -Xms2048m -Xmx2048m -Xss1m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -jar /opt/app/app.jar > /opt/app/app.log 2>&1 & --spring.profiles.active=prod
echo $! > /opt/app/app-service.pid
3. 制作停止脚本
vim app-stop.sh

内容如下

#!/bin/sh
PID=$(cat /opt/app/app-service.pid)
kill -9 $PID
4. 增加执行权限
chmod +x app-start.sh
chmod +x app-stop.sh
5. 设置开机启动
systemctl daemon-reload
systemctl status springbootapp
systemctl enable springbootapp

关闭开机自启动

systemctl disable springbootapp

立即执行启动服务脚本

systemctl start springbootapp

立即执行关闭服务脚本

systemctl stop springbootapp
创建镜像

继续创建多台云服务器

负载均衡

直接通过负载均衡的ip访问服务的8888端口

测试一下

创建弹性伸缩

通常还需要配置目标追踪规则才能实现扩容。

如果我配置的期望值是1台服务器,那么过一段时间没有负载就会直接把你创建的实例给删除了,仅保留一台。

redis的报警规则

白名单

这里设置和云服务器的一样,可以在同一个网络访问,其他ip即便知道用户名密码和主机ip也无法访问。


🔔如果您需要转载或者搬运这篇文章的话,非常欢迎您私信我哦~

相关文章
|
存储 人工智能 缓存
[大厂实践] 无停机迁移大规模关键流量 (上)
[大厂实践] 无停机迁移大规模关键流量 (上)
126 0
|
4月前
|
Prometheus Kubernetes 监控
在K8S中,当Pod业务量比较大时候,如何实现水平伸缩和扩容?
在K8S中,当Pod业务量比较大时候,如何实现水平伸缩和扩容?
|
7月前
|
弹性计算 负载均衡 关系型数据库
弹性伸缩优势
弹性伸缩具有自动化、降成本、高可用、灵活智能以及易审计等优势。
58 6
|
7月前
|
弹性计算 运维 关系型数据库
如何利用弹性伸缩降低成本
利用弹性伸缩降低成本
62 3
|
7月前
|
弹性计算 运维 Cloud Native
阿里云云原生弹性方案,用弹性解决集群资源利用率难题
本文主要介绍了通过弹性,实现成本优化,解决集群资源利用率难题。
92782 8
|
7月前
|
弹性计算 Kubernetes 大数据
阿里云弹性扩容方案选择
阿里云弹性扩容方案选择
|
存储 监控 安全
[大厂实践] 无停机迁移大规模关键流量 (下)
[大厂实践] 无停机迁移大规模关键流量 (下)
99 0
|
存储 关系型数据库 MySQL
今日14点开播!打造智能无感、秒级弹性的Serverless数据库
2022年阿里云数据库在云栖大会宣布:All in Serverless。核心产品PolarDB、AnalyticDB、RDS均实现了Serverless能力。
今日14点开播!打造智能无感、秒级弹性的Serverless数据库
|
弹性计算 监控 负载均衡
创建简易弹性伸缩方案-介绍|学习笔记
快速学习创建简易弹性伸缩方案-介绍
创建简易弹性伸缩方案-介绍|学习笔记
|
SQL 弹性计算 监控
精准容量、秒级弹性,压测工具 + SAE 方案如何成功突破传统大促难关?
本次课程介绍在 SAE 场景下,如何借助压测工具与 SAE 弹性能力来应对大促的实践。主要包含 3 部分要点:传统大促面临的挑战、SAE 大促方案以及快速压测验证。
精准容量、秒级弹性,压测工具 + SAE 方案如何成功突破传统大促难关?