日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

译:Spring Boot 自动伸缩

發(fā)布時間:2025/4/9 64 豆豆
生活随笔 收集整理的這篇文章主要介紹了 译:Spring Boot 自动伸缩 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原文鏈接:https://dzone.com/articles/spring-boot-autoscaler

作者:Piotr Mińkowski

譯者:helloworldtang

自動伸縮是每個人都想要的,尤其是在微服務(wù)領(lǐng)域。讓我們看看如何在基于Spring Boot的應(yīng)用程序中實現(xiàn)。

我們決定使用?Kubernetes、?PivotalCloudFoundry或?HashiCorp's Nomad等工具的一個更重要的原因是為了讓系統(tǒng)可以自動伸縮。當(dāng)然,這些工具也提供了許多其他有用的功能,在這里,我們只是用它們來實現(xiàn)系統(tǒng)的自動伸縮。乍一看,這似乎很困難,但是,如果我們使用?SpringBoot來構(gòu)建應(yīng)用程序,并使用?Jenkins來實現(xiàn)?CI,那么就用不了太多工作。

今天,我將向您展示如何使用以下框架/工具實現(xiàn)這樣的解決方案:

  • Spring Boot

  • Spring Boot Actuator

  • Spring Cloud Netflix Eureka

  • Jenkins CI

它是如何工作的

每一個包含?SpringBootActuator庫的?SpringBoot應(yīng)用程序都可以在?/actuator/metrics端點下公開?metric。許多有價值的?metric都可以提供應(yīng)用程序運行狀態(tài)的詳細(xì)信息。在討論自動伸縮時,其中一些?metric可能特別重要:?JVM、CPU?metric、正在運行的線程數(shù)和HTTP請求數(shù)。有專門的?Jenkins流水線通過按一定頻率輪詢?/actuator/metrics?端點來獲取應(yīng)用程序的指標(biāo)。如果監(jiān)控的任何?metric【指標(biāo)】低于或高于目標(biāo)范圍,則它會啟動新實例或使用另一個?Actuator端點?/actuator/shutdown來關(guān)閉一些正在運行的實例。在此之前,我們需要知道當(dāng)前有那些實踐在提供服務(wù),只有這樣我們才能在需要的時候關(guān)閉空閑的實例或啟動新的新例。?在討論了系統(tǒng)架構(gòu)之后,我們就可以繼續(xù)開發(fā)了。這個應(yīng)用程序需要滿足以下要求:它必須有公開的可以優(yōu)雅地關(guān)閉應(yīng)用程序和用來獲取應(yīng)用程序運行狀態(tài)?metric【指標(biāo)】的端點,它需要在啟動完成的同時就完成在Eureka的注冊,在關(guān)閉時取消注冊,最后,它還應(yīng)該能夠從空閑端口池中隨機(jī)獲取一個可用的端口。感謝?SpringBoot,只需要約五分鐘,我們可以輕松地實現(xiàn)所有這些機(jī)制。

動態(tài)端口分配

由于可以在一臺機(jī)器上運行多個應(yīng)用程序?qū)嵗?#xff0c;所以我們必須保證端口號不沖突。幸運的是,?SpringBoot為應(yīng)用程序提供了這樣的機(jī)制。我們只需要將?application.yml中的?server.port屬性設(shè)置為?0。因為我們的應(yīng)用程序會在?Eureka中注冊,并且發(fā)送唯一的標(biāo)識?instanceId,默認(rèn)情況下這個唯一標(biāo)識是將字段?spring.cloud.client.hostname,?spring.application.name和?server.port拼接而成的。

示例應(yīng)用程序的當(dāng)前配置如下所示。 可以看到,我通過將端口號替換為隨機(jī)生成的數(shù)字來改變了生成?instanceId字段值的模板。

  • spring:

  • ?application:

  • ? ?name: example-service

  • server:

  • ?port: ${PORT:0}

  • eureka:

  • ?instance:

  • ? ?instanceId: ${spring.cloud.client.hostname}:${spring.application.name}:${random.int[1,999999]}

  • 啟用?Actuator的?Metric

    為了啟用?SpringBootActuator,我們需要將下面的依賴添加到?pom.xml。

  • <dependency>

  • ? ?<groupId>org.springframework.boot</groupId>

  • ? ?<artifactId>spring-boot-starter-actuator</artifactId>

  • </dependency>

  • 我們還必須通過HTTP API將屬性?management.endpoints.web.exposure.include設(shè)置為?'*'來暴露?Actuator的端點。現(xiàn)在,所有可用的指標(biāo)名稱列表都可以在?/actuator/metrics端點中找到,每個指標(biāo)的詳細(xì)信息可以通過?/actuator/metrics/{metricName}端點查看。

    優(yōu)雅地停止應(yīng)用程序

    除了查看?metric端點外,?SpringBootActuator還提供了停止應(yīng)用程序的端點。然而,與其他端點不同的是,缺省情況下,此端點是不可用的。我們必須把?management.endpoint.shutdown.enabled設(shè)為?true。在那之后,我們就可以通過發(fā)送一個?POST請求到?/actuator/shutdown端點來停止應(yīng)用程序了。

    這種停止應(yīng)用程序的方法保證了服務(wù)在停止之前從?Eureka服務(wù)器注銷。

    啟用?Eureka自動發(fā)現(xiàn)

    Eureka是最受歡迎的發(fā)現(xiàn)服務(wù)器,特別是使用?SpringCloud來構(gòu)建微服務(wù)的架構(gòu)。所以,如果你已經(jīng)有了微服務(wù),并且想要為他們提供自動伸縮機(jī)制,那么?Eureka將是一個自然的選擇。它包含每個應(yīng)用程序注冊實例的IP地址和端口號。為了啟用?Eureka客戶端,您只需要將下面的依賴項添加到?pom.xml中。

  • <dependency>

  • ? ?<groupId>org.springframework.cloud</groupId>

  • ? ?<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>

  • </dependency>

  • 正如之前提到的,我們還必須保證通過客戶端應(yīng)用程序發(fā)送到?Eureka服務(wù)器的?instanceId的唯一性。在“動態(tài)端口分配”中已經(jīng)描述了它。

    下一步需要創(chuàng)建一個包含內(nèi)嵌?Eureka服務(wù)器的應(yīng)用程序。為了實現(xiàn)這個功能,首先我們需要在?pom.xml中添加下面這個依賴:

  • <dependency>

  • ? ?<groupId>org.springframework.cloud</groupId>

  • ? ?<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>

  • </dependency>

  • 這個?main類需要添加?@EnableEurekaServer注解。

  • @SpringBootApplication

  • @EnableEurekaServer

  • public class DiscoveryApp {

  • ? ?public static void main(String[] args) {

  • ? ? ? ?new SpringApplicationBuilder(DiscoveryApp.class).run(args);

  • ? ?}

  • }

  • 默認(rèn)情況下,客戶端應(yīng)用程序嘗試使用?8761端口連接?Eureka服務(wù)器。我們只需要單獨的、獨立的?Eureka節(jié)點,因此我們將禁用注冊,并嘗試從另一個?Eureka服務(wù)器實例中獲取服務(wù)列表。

  • spring:

  • ?application:

  • ? ?name: discovery-service

  • server:

  • ?port: ${PORT:8761}

  • eureka:

  • ?instance:

  • ? ?hostname: localhost

  • ?client:

  • ? ?registerWithEureka: false

  • ? ?fetchRegistry: false

  • ? ?serviceUrl:

  • ? ? ?defaultZone: http://localhost:8761/eureka/

  • 我們將使用?Docker容器來測試上面的自動伸縮系統(tǒng),因此需要使用?Eureka服務(wù)器來準(zhǔn)備和構(gòu)建?image。?Dockerfile和?image的定義如下所示。 我們可以使用命令?docker build-t piomin/discovery-server:2.0來進(jìn)行構(gòu)建。

  • FROM openjdk:8-jre-alpine

  • ENV APP_FILE discovery-service-1.0-SNAPSHOT.jar

  • ENV APP_HOME /usr/apps

  • EXPOSE 8761

  • COPY target/$APP_FILE $APP_HOME/

  • WORKDIR $APP_HOME

  • ENTRYPOINT ["sh", "-c"]

  • CMD ["exec java -jar $APP_FILE"]

  • 為彈性伸縮構(gòu)建一個?Jenkins流水線

    第一步是準(zhǔn)備?Jenkins流水線,負(fù)責(zé)自動伸縮。我們將創(chuàng)建?Jenkins聲明式流水線,它每分鐘運行一次。可以使用?triggers指令配置執(zhí)行周期,它定義了自動化觸發(fā)流水線的方法。我們的流水線將與?Eureka服務(wù)器和每個使用?SpringBootActuator的微服務(wù)中公開的?metric端點進(jìn)行通信。 測試服務(wù)的名稱是?EXAMPLE-SERVICE,它和定義在?application.yml文件?spring.application.name的屬性值(大寫字母)相同。被監(jiān)控的?metric是運行在Tomcat容器中的HTTP?listener線程數(shù)。這些線程負(fù)責(zé)處理客戶端的HTTP請求。

  • pipeline {

  • ? ?agent any

  • ? ?triggers {

  • ? ? ? ?cron('* * * * *')

  • ? ?}

  • ? ?environment {

  • ? ? ? ?SERVICE_NAME = "EXAMPLE-SERVICE"

  • ? ? ? ?METRICS_ENDPOINT = "/actuator/metrics/tomcat.threads.busy?tag=name:http-nio-auto-1"

  • ? ? ? ?SHUTDOWN_ENDPOINT = "/actuator/shutdown"

  • ? ?}

  • ? ?stages { ... }

  • }

  • 使用?Eureka整合?Jenkins流水線

    流水線的第一個階段負(fù)責(zé)獲取在?discovery服務(wù)器上注冊的服務(wù)列表。?Eureka發(fā)現(xiàn)了幾個HTTP API端點。其中一個是?GET/eureka/apps/{serviceName},它返回一個給定服務(wù)名稱的所有活動實例列表。我們正在保存運行實例的數(shù)量和每個實例?metric端點的URL。這些值將在流水線的下一個階段中被訪問。 下面的流水線片段可以用來獲取活動應(yīng)用程序?qū)嵗斜怼?stage名稱是?Calculate。我們使用HTTP請求插件?來發(fā)起HTTP連接。

  • stage('Calculate') {

  • steps {

  • ?script {

  • ? def response = httpRequest "http://192.168.99.100:8761/eureka/apps/${env.SERVICE_NAME}"

  • ? def app = printXml(response.content)

  • ? def index = 0

  • ? env["INSTANCE_COUNT"] = app.instance.size()

  • ? app.instance.each {

  • ? ?if (it.status == 'UP') {

  • ? ? def address = "http://${it.ipAddr}:${it.port}"

  • ? ? env["INSTANCE_${index++}"] = address

  • ? ?}

  • ? }

  • ?}

  • }

  • }

  • @NonCPS

  • def printXml(String text) {

  • return new XmlSlurper(false, false).parseText(text)

  • }

  • 下面是?Eureka?API對我們的微服務(wù)的示例響應(yīng)。響應(yīng)?content-type是?XML。?

    使用?SpringBootActuator整合?Jenkins流水線

    SpringBootActuator使用?metric來公開端點,這使得我們可以通過名稱和選擇性地使用標(biāo)簽找到?metric。在下面可見的流水線片段中,我試圖找到?metric低于或高于閾值的實例。如果有這樣的實例,我們就停止循環(huán),以便進(jìn)入下一個階段,它執(zhí)行向下或向上的伸縮。應(yīng)用程序的IP地址是從帶有?INSTANCE_前綴的流水線環(huán)境變量獲取的,這是在前一階段中被保存了下來的。

  • stage('Metrics') {

  • steps {

  • script {

  • def count = env.INSTANCE_COUNT

  • for(def i=0;i 100)

  • return "UP"

  • else if (value.toInteger() < 20)

  • return "DOWN"

  • else

  • return "NONE"

  • }

  • 關(guān)閉應(yīng)用程序?qū)嵗?/h2>

    在流水線的最后一個階段,我們將關(guān)閉運行的實例,或者根據(jù)在前一階段保存的結(jié)果啟動新的實例。通過調(diào)用?SpringBootActuator端點可以很容易執(zhí)行停止操作。在接下來的流水線片段中,首先選擇了?Eureka實例。然后我們將發(fā)送?POST請求到那個ip地址。 如果需要擴(kuò)展應(yīng)用程序,我們將調(diào)用另一個流水線,它負(fù)責(zé)構(gòu)建?fat JAR并讓這個應(yīng)用程序在機(jī)器上跑起來。

  • stage('Scaling') {

  • steps {

  • ?script {

  • ? if (env.SCALE_TYPE == 'DOWN') {

  • ? ?def ip = env["INSTANCE_0"] + env.SHUTDOWN_ENDPOINT

  • ? ?httpRequest url: ip, contentType: 'APPLICATION_JSON', httpMode: 'POST'

  • ? } else if (env.SCALE_TYPE == 'UP') {

  • ? ?build job: 'spring-boot-run-pipeline'

  • ? }

  • ? currentBuild.description = env.SCALE_TYPE

  • ?}

  • }

  • }

  • 下面是?spring-boot-run-pipeline流水線的完整定義,它負(fù)責(zé)啟動應(yīng)用程序的新實例。它先從?git倉庫中拉取源代碼,然后使用?Maven命令編譯并構(gòu)建二進(jìn)制的jar文件,最后通過在?java-jar命令中添加?Eureka服務(wù)器地址來運行應(yīng)用程序。

  • pipeline {

  • ? ?agent any

  • ? ?tools {

  • ? ? ? ?maven 'M3'

  • ? ?}

  • ? ?stages {

  • ? ? ? ?stage('Checkout') {

  • ? ? ? ? ? ?steps {

  • ? ? ? ? ? ? ? ?git url: 'https://github.com/piomin/sample-spring-boot-autoscaler.git', credentialsId: 'github-piomin', branch: 'master'

  • ? ? ? ? ? ?}

  • ? ? ? ?}

  • ? ? ? ?stage('Build') {

  • ? ? ? ? ? ?steps {

  • ? ? ? ? ? ? ? ?dir('example-service') {

  • ? ? ? ? ? ? ? ? ? ?sh 'mvn clean package'

  • ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ?}

  • ? ? ? ?}

  • ? ? ? ?stage('Run') {

  • ? ? ? ? ? ?steps {

  • ? ? ? ? ? ? ? ?dir('example-service') {

  • ? ? ? ? ? ? ? ? ? ?sh 'nohup java -jar -DEUREKA_URL=http://192.168.99.100:8761/eureka target/example-service-1.0-SNAPSHOT.jar 1>/dev/null 2>logs/runlog &'

  • ? ? ? ? ? ? ? ?}

  • ? ? ? ? ? ?}

  • ? ? ? ?}

  • ? ?}

  • }

  • 擴(kuò)展到多個機(jī)器

    在前幾節(jié)中討論的算法只適用于在單個機(jī)器上啟動的微服務(wù)。如果希望將它擴(kuò)展到更多的機(jī)器上,我們將不得不修改我們的架構(gòu),如下所示。每臺機(jī)器都有?Jenkins代理運行并與?Jenkins?master通信。如果想在選定的機(jī)器上啟動一個微服務(wù)的新實例,我們就必須使用運行在該機(jī)器上的代理來運行流水線。此代理僅負(fù)責(zé)從源代碼構(gòu)建應(yīng)用程序并將其啟動到目標(biāo)機(jī)器上。這個實例的關(guān)閉仍然是通過調(diào)用HTTP端點來完成。?

    你可以在我的文章在Docker容器上的運行Jenkins節(jié)點中找到更多關(guān)于運行?Jenkins代理的信息,并通過?JNLP協(xié)議將它們與?Jenkins?master聯(lián)系起來。假設(shè)我們已經(jīng)成功地在目標(biāo)機(jī)器上啟動了一些代理,我們需要對流水線進(jìn)行參數(shù)化,以便能夠動態(tài)地選擇代理(以及目標(biāo)機(jī)器)。 當(dāng)擴(kuò)容應(yīng)用程序時,我們必須將代理標(biāo)簽傳遞給下游流水線。

  • build job:'spring-boot-run-pipeline', parameters:[string(name: 'agent', value:"slave-1")]

  • 調(diào)用流水線具體由那個標(biāo)簽下的代理運行,是由"?${params.agent}"決定的。

  • pipeline {

  • ? ?agent {

  • ? ? ? ?label "${params.agent}"

  • ? ?}

  • ? ?stages { ... }

  • }

  • 如果有一個以上的代理連接到主節(jié)點,我們就可以將它們的地址映射到標(biāo)簽中。由于這一點,我們能夠?qū)?Eureka服務(wù)器獲取的微服務(wù)實例的IP地址映射到與?Jenkins代理的目標(biāo)機(jī)器上。

  • pipeline {

  • ? ?agent any

  • ? ?triggers {

  • ? ? ? ?cron('* * * * *')

  • ? ?}

  • ? ?environment {

  • ? ? ? ?SERVICE_NAME = "EXAMPLE-SERVICE"

  • ? ? ? ?METRICS_ENDPOINT = "/actuator/metrics/tomcat.threads.busy?tag=name:http-nio-auto-1"

  • ? ? ? ?SHUTDOWN_ENDPOINT = "/actuator/shutdown"

  • ? ? ? ?AGENT_192.168.99.102 = "slave-1"

  • ? ? ? ?AGENT_192.168.99.103 = "slave-2"

  • ? ?}

  • ? ?stages { ... }

  • }

  • 總結(jié)

    在本文中,我演示了如何使用?SpringBootActuato?metric來自動伸縮?SpringBoot應(yīng)用程序。使用?SpringBoot提供的特性以及?SpringCloudNetflixEureka和?Jenkins,您就可以實現(xiàn)系統(tǒng)的自動伸縮,而無需借助于任何其他第三方工具。本文也假設(shè)遠(yuǎn)程服務(wù)器上也是使用?Jenkins代理來啟動新的實例,但是您也可以使用?Ansible這樣的工具來啟動。如果您決定從?Jenkins運行?Ansible腳本,那么將不需要在遠(yuǎn)程機(jī)器上啟動?Jenkins代理。示例中用到的代碼可以在?GitHub上找到。

    轉(zhuǎn)載于:https://www.cnblogs.com/bigben0123/p/9802228.html

    總結(jié)

    以上是生活随笔為你收集整理的译:Spring Boot 自动伸缩的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。