<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBoot 打包部署最佳實(shí)踐

          共 8611字,需瀏覽 18分鐘

           ·

          2021-09-23 14:29


          spring boot介紹

          Spring Boot目前流行的java web應(yīng)用開發(fā)框架,相比傳統(tǒng)的spring開發(fā),spring boot極大簡化了配置,并且遵守約定優(yōu)于配置的原則即使0配置也能正常運(yùn)行,這在spring中是難以想象的。spring boot應(yīng)用程序可以獨(dú)立運(yùn)行,框架內(nèi)嵌web容器,使得web應(yīng)用程序可以像本地程序一樣啟動和調(diào)試,十分的方便,這種設(shè)計(jì)方式也使得spring boot應(yīng)用程序非常適合容器化進(jìn)行大規(guī)模部署。生態(tài)方面,spring boot提供了非常豐富的組件,目前流行的java web框架基本都有spring boot版本,生態(tài)十分龐大,是目前java web開發(fā)最好的方案。


          spring boot部署問題

          Springboot應(yīng)用程序有兩種運(yùn)行方式

          以jar包方式運(yùn)行

          以war包方式運(yùn)行

          兩種方式應(yīng)用場景不一樣,各有優(yōu)缺點(diǎn)


          jar包運(yùn)行

          通過maven插件spring-boot-maven-plugin,在進(jìn)行打包時,會動態(tài)生成jar的啟動類org.springframework.boot.loader.JarLauncher,借助該類對springboot應(yīng)用程序進(jìn)行啟動。


          優(yōu)點(diǎn)

          本地?zé)o需搭建web容器,方便開發(fā)和調(diào)試。

          因?yàn)樽詭eb容器,可以避免由于web容器的差異造成不同環(huán)境結(jié)果不一致問題。

          一個jar包就是全部,方便應(yīng)用擴(kuò)展。

          借助容器化,可以進(jìn)行大規(guī)模的部署。


          缺點(diǎn)

          應(yīng)用過于獨(dú)立,難以統(tǒng)一管理。

          數(shù)據(jù)源無法通過界面進(jìn)行管理。

          應(yīng)用體積過大。

          修改web容器相關(guān)配置較為困難,需要借助代碼實(shí)現(xiàn)。


          war包運(yùn)行

          以war包方式運(yùn)行,通過maven插件spring-boot-maven-plugin進(jìn)行相關(guān)配置后,最終生成一個可運(yùn)行在tomcat,weblogic等java web容器中的war包。


          優(yōu)點(diǎn)

          可以借助web容器管理界面對應(yīng)用進(jìn)行管理。

          可以管理JNDI數(shù)據(jù)源。


          web容器配置較為靈活,配置和程序分離。

          應(yīng)用體積較小,甚至可以借助web容器的包管理功能(比如weblogic Library)進(jìn)一步減小應(yīng)用大小。


          缺點(diǎn)

          本地需要搭建web容器,對本地環(huán)境要求更高點(diǎn),學(xué)習(xí)成本也響應(yīng)更高。

          調(diào)試較為困難,需要借助web容器。


          無法兼容所有web容器(比如spring boot2.x無法運(yùn)行在weblogic 11g上)。


          部署較為困難(比如和weblogic有較多的類沖突)

          在實(shí)際的項(xiàng)目中,并沒有哪一種方式是最好的,根據(jù)客戶不同的需求制定不同的部署方案,比如有些客戶比較看中管理功能,要求數(shù)據(jù)源和tomcat相關(guān)配置必須由管理員進(jìn)行管理,那么選擇war包方式,有些客戶希望借助容器化進(jìn)行大規(guī)模部署,那么jar方式更適合。不管選擇哪種方式,在部署時都會遇到下面的問題

          如果需要打war包,那么不僅是pom文件需要修改,應(yīng)用程序也要做相應(yīng)的改動,改動完后,應(yīng)用程序就無法本地運(yùn)行,需要打完包后將配置信息修改回來,這樣不僅麻煩,還容易出錯。


          不管是war包還是jar包,如何管理不同環(huán)境的配置文件,保證不會出錯,雖然spring boot有提供spring.profiles.active配置設(shè)置不同的環(huán)境,但一方面需要人為修改配置文件,只要是人為的就有可能出錯,另一方面,客戶有時出于安全考慮不會提供生產(chǎn)環(huán)境配置信息,那么這時候就無法指定prifiles.active。


          如何將多個spring boot模塊打包在一起。


          jar包需要配合容器化才能發(fā)揮出最大的優(yōu)勢,如果沒有容器,spring boot jar包就是一個玩具,隨處運(yùn)行的jar包,缺少統(tǒng)一管理,是達(dá)不到生產(chǎn)的要求,那么如果從jar包到容器也是一個問題。


          早期碰到這些問題,都是人工解決,不僅效率十分低下,部署一次都需要十幾分鐘,而且很容易出錯,一百次出錯一次算是概率低了,但是生產(chǎn)出錯一次都是重大事件,所以我們也在思考如何通過自動化解決以上問題,如何將開發(fā)和部署分離,開發(fā)人員只關(guān)心開發(fā),開發(fā)完提交代碼,打包和部署都是后臺透明的完成。以下就是我們的解決方案。


          打包war包打包問題解決

          spring boot打war包的步驟如下

          在pom.xml中將打包方式改為war。

          <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> ... war ...
          設(shè)置spring-boot-starter-tomcat范圍為provided
          org.springframework.boot spring-boot-starter-tomcat provided
          修改spring boot的啟動類,繼承SpringBootServletInitializerpublic class DemoApplication extends SpringBootServletInitializer{ @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(DemoApplication.class); }}

          每打包一次都要修改pom.xml和啟動類,打包完再修改回來,十分的繁瑣,因?yàn)?,我們提出以下整改方?/span>


          從pom.xml復(fù)制一個pom-war.xml文件,將pom-war.xml修改為war包配置

          在根目錄下(除了src目錄外都可以)復(fù)制一份啟動類的代碼,修改為war包的配置方式。


          編寫shell腳本進(jìn)行打包。


          shell腳本打包過程為

          1. 備份當(dāng)前啟動類的java代碼。
          2. 將war包啟動類的代碼替換掉當(dāng)前啟動類的代碼。
          3. maven指定pom-war.xml文件進(jìn)行打包。
          4. 打包結(jié)束后恢復(fù)啟動類文件。

          以下就是參考腳本
          app-war.sh#!/usr/bin/env bash
          v1=src/main/java/com/definesys/demo/DemoApplication.javav2=war/DemoApplication.javav3=war/DemoApplication-bak.java
          cp -rf $v2 $v1
          mvn clean package -Dmaven.test.skip=true -f war-pom.xml
          #recoverycp -rf $v3 $v1

          通過預(yù)先配置好pom文件和啟動類文件,開發(fā)人員只要運(yùn)行app-war.sh腳本無需修改任何文件即可生成war包。


          更優(yōu)的方案

          以上方案pom文件和啟動類文件都需要預(yù)先準(zhǔn)備好,未實(shí)現(xiàn)完全的自動化,通過優(yōu)化方案做到完全自動化。


          腳本可以通過find命令搜索以*Application.java結(jié)尾的文件,作為啟動類文件,讀取文件名獲取類名,通過字符串替換方式動態(tài)生成war包啟動類文件。

          在pom.xml中用注釋設(shè)置好錨點(diǎn),腳本通過替換錨點(diǎn)動態(tài)生成pom.xml文件。

          如果不希望通過錨點(diǎn)實(shí)現(xiàn),可以借助更高級的腳本語言,比如python對xml進(jìn)行解析,再動態(tài)生成xml。


          多模塊打包

          這里的多模塊指的是maven中的多模塊,項(xiàng)目工程中的代碼多模塊,一個項(xiàng)目按功能劃分模塊后,在創(chuàng)建工程時一般也按照功能層面上的模塊進(jìn)行創(chuàng)建,這樣避免一個模塊代碼過于龐大,也利于任務(wù)的分工,但打包卻更麻煩了。

          每個模塊都是獨(dú)立的spring boot程序,整合到一個包的時候會出現(xiàn)多個啟動類,多個配置文件沖突的問題。

          每個模塊有引用相同的依賴,依賴包版本升級后,需要每個pom文件都做修改。


          通過優(yōu)化項(xiàng)目結(jié)構(gòu)解決以上問題

          父項(xiàng)目的pom指定spring boot的依賴和公共的依賴。

          創(chuàng)建一個spring boot的子項(xiàng)目,作為啟動項(xiàng)目,我們稱為start項(xiàng)目。

          其余子項(xiàng)目為普通的java maven項(xiàng)目,parent設(shè)置為第一步創(chuàng)建的spring boot父項(xiàng)目。


          start項(xiàng)目的pom引用其他子項(xiàng)目的依賴。

          本地調(diào)試可以直接運(yùn)行start的啟動類,ide會自動編譯其他模塊并引用。

          打包可以在父項(xiàng)目上進(jìn)行install后再進(jìn)入start項(xiàng)目進(jìn)行打包,腳本參考如下

          mvn clean installcd startmvn clean package
          目錄結(jié)構(gòu)如下
          .├── pom.xml├── role│ ├── pom.xml│ └── src│ ├── main│ │ ├── java│ │ │ └── com│ │ │ └── definesys│ │ │ └── demo│ │ │ └── controller│ │ │ └── RoleController.java│ │ └── resources├── start│ ├── pom.xml│ ├── src│ │ ├── main│ │ │ ├── java│ │ │ │ └── com│ │ │ │ └── definesys│ │ │ │ └── demo│ │ │ │ └── DemoApplication.java│ │ │ └── resources│ │ │ └── application.properties└── user ├── pom.xml └── src └── main ├── java │ └── com │ └── definesys │ └── demo │ └── controller │ └── UserController.java └── resources
          start項(xiàng)目包含包含啟動類和配置文件,pom文件引用其余子項(xiàng)目。
          start pom.xml
          <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
          blog0915 com.definesys.demo 1.0-SNAPSHOT
          4.0.0 start

          com.definesys.demo user 1.0.0

          com.definesys.demo role 1.0.0




          org.springframework.boot spring-boot-maven-plugin


          父項(xiàng)目parent為spring boot,引用spring boot相關(guān)依賴和各個子項(xiàng)目公共的依賴

          父項(xiàng)目 pom.xml

          <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 pom
          user role start


          org.springframework.boot spring-boot-starter-parent 2.1.2.RELEASE


          com.definesys.demo blog0915 1.0-SNAPSHOT


          org.springframework.boot spring-boot-starter-web

          所有非start的子項(xiàng)目需要指定版本號并且父項(xiàng)目都設(shè)為根目錄項(xiàng)目。

          子項(xiàng)目 pom.xml

          <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">        blog0915        com.definesys.demo        1.0-SNAPSHOT    4.0.0    role    1.0.0

          所有子項(xiàng)目的包路徑前綴必須一樣,并且以start項(xiàng)目作為基本路徑。


          配置文件問題

          spring boot提供spring.profiles.active指定配置文件,但生產(chǎn)環(huán)境有時候客戶出于安全考慮不提供配置信息給開發(fā)人員,而是預(yù)先將配置文件上傳到服務(wù)器指定路徑,程序需要在運(yùn)行時去引用該配置文件,如果運(yùn)行環(huán)境是kubernetes,則會提供一個config map作為配置文件,這時候就要求spring boot程序讀取外部配置文件。


          這里討論的是線上環(huán)境配置文件方案,本地調(diào)試參考子模塊打包相關(guān)內(nèi)容,可以將配置文件統(tǒng)一寫在start項(xiàng)目中。


          jar包外部配置文件讀取

          jar運(yùn)行可以通過指定參數(shù)spring.config.location引用外部文件,命令參考如下:

          java -jar start-1.0-SNAPSHOT.jar --spring.config.location=/Users/asan/workspace/config

          config目錄存放properties配置文件

          可以通過配合spring.profiles.active參數(shù)可以指定目錄下配置文件,如:

          java -jar start-1.0-SNAPSHOT.jar --spring.profiles.active=prod --spring.config.location=/Users/asan/workspace/config

          則會讀取/Users/asan/workspace/config/appliction-prod.properties文件作為配置文件。


          war包外部配置文件讀取

          以tomcat為例,需要在tomcat啟動時指定-Dspring.config.location參數(shù),可以設(shè)置服務(wù)器環(huán)境變量CATALINA_OPTS達(dá)到目的??梢跃庉嬘脩?prifile文件

          export CATALINA_OPTS=/Users/asan/workspace/config

          同樣,也可以通過-Dspring.profiles.active指定配置文件名稱。


          容器化

          spring boot借助容器化,可以如虎添翼,發(fā)揮出更大的威力,也只有通過容器化,才能體會到spring boot開發(fā)的高效。通過以上的介紹,你可以很順利的打好一個jar包或者war包,那么可以通過編寫dockerfile文件進(jìn)行鏡像的構(gòu)建。spring boot在構(gòu)建鏡像時有兩個地方需要考慮時區(qū)問題,基礎(chǔ)鏡像的時區(qū)默認(rèn)是UTC,比北京時間早8小時,需要指定鏡像時區(qū)。


          配置文件問題,需要指定外部配置文件(根據(jù)項(xiàng)目具體情況選擇)。

          app-jar-dockerfile.DockerfileFROM openjdk:8-jdk-alpine
          MAINTAINER definesys.com
          VOLUME /tmpADD start-1.0-SNAPSHOT.jar app.jarRUN echo "Asia/Shanghai" > /etc/timezoneEXPOSE 8080ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","--spring.config.location=/Users/asan/workspace/config","/app.jar"]app-war.dockerfile.DockerfileFROM tomcat
          MAINTAINER definesys.com
          ENV CATALINA_OPTS -Dspring.config.location=file:/middleware/config/ADD start-1.0-SNAPSHOT.war /usr/local/tomcat/webapps/app.jarRUN echo "Asia/Shanghai" > /etc/timezoneEXPOSE 8080

          EOF部署

          早期我們采用的是以下部署過程


          首先構(gòu)建測試環(huán)境的鏡像,上傳到鏡像倉庫,應(yīng)用重新部署。
          接著構(gòu)建UAT環(huán)境的鏡像,上傳到鏡像倉庫,應(yīng)用重新部署。
          最后構(gòu)建生產(chǎn)環(huán)境的鏡像,上傳到鏡像倉庫,應(yīng)用重新部署。

          每一次發(fā)布都是一個新的鏡像,但這種方式有個問題就是如何保證前一個環(huán)境驗(yàn)證沒問題,后一個環(huán)境就一定沒問題,因?yàn)閮蓚€鏡像是不一樣的,雖然可能兩次構(gòu)建都是基于同一版本代碼,但因?yàn)槭侵匦聵?gòu)建,中間可能因?yàn)楦鞣N原因,如maven包版本更新等,無法保證兩次構(gòu)建就是完全一樣的鏡像。因此我們優(yōu)化了構(gòu)建的流程,如下:

          所有的環(huán)境都是用同一個鏡像,環(huán)境之間只有配置文件不同,文件通過configmap或者外部配置文件方式進(jìn)行掛載,這樣保證了配置文件沒問題的前提下,每個環(huán)境的程序一定是一樣的。

          jenkins自動打包部署

          打包和部署在本地進(jìn)行也是有問題的,本地jdk版本取決于個人電腦,甚至有黑客污染jdk導(dǎo)致編譯的class文件自帶后門,個人電腦環(huán)境也是隨著用戶不同操作可能改變,構(gòu)建出來的包不能保證是穩(wěn)定的包。因此需要一個遠(yuǎn)程服務(wù)器用于打包和部署,能夠?qū)崿F(xiàn)從源碼到鏡像過程。jenkins是一個基于java開發(fā)的持續(xù)集成工具,通過配置插件和編寫腳本實(shí)現(xiàn)程序從代碼到制品再到線上運(yùn)行的過程。jenkins在spring boot開發(fā)中主要完成了以下工作。

          通過gitlab插件實(shí)現(xiàn)源代碼的獲取。
          基于以上介紹的腳本,實(shí)現(xiàn)從源碼到制品的過程。
          通過docker工具實(shí)現(xiàn)從制品到鏡像的過程。
          通過kubectl工具,實(shí)現(xiàn)從鏡像到上云的過程。

          jenkins在構(gòu)建鏡像時需要借助docker工具,但jenkins本身也是有docker版本的,所以就面臨著docker in docker的問題,這里選擇的方案是用二進(jìn)制文件安裝jenkin而非鏡像方式,雖然喪失了docker的便利性,但可以簡化docker方案,降低集成的復(fù)雜度。

          逆鋒起筆是一個專注于程序員圈子的技術(shù)平臺,你可以收獲最新技術(shù)動態(tài)、最新內(nèi)測資格BAT等大廠的經(jīng)驗(yàn)、精品學(xué)習(xí)資料、職業(yè)路線副業(yè)思維,微信搜索逆鋒起筆關(guān)注!

          這 10 本書,提升你的財(cái)富思維,今天免費(fèi)送!
          螞蟻金服開源 增強(qiáng)版 Spring Boot 研發(fā)框架
          為什么阿里巴巴禁止使用存儲過程?
          你絕對沒見過的 7 種 for 循環(huán)優(yōu)化!
          全網(wǎng)最全 postman 使用教程!

          瀏覽 73
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲欧美另类在线观看 | 91视频人人爱 | 爱操逼综合 | 精品无码久久久久久久久不卡 | 国产无遮挡A片又黄又爽小直播 |