Spring Boot 應用程序五種部署方式

翻譯自 Deploying Spring Boot Applications[1]


原作者 Murat Artim[2]


翻譯水平有限,有些地方可能翻譯的不太準確,敬請諒解,也歡迎在評論區提出修改建議

可以使用各種方法將 Spring Boot 應用程序部署到生產系統中。在本文中,我們將通過以下 5 種方法來部署 Spring Boot 應用程序:

  • 使用 Java Archive (JAR) 作為獨立應用程序進行部署
  • 將 Web Application Archive (WAR) 部署到 servlet 容器中
  • 在 Docker 容器中部署
  • 部署在 NGINX Web 服務器後面 - 直接設置
  • 部署在 NGINX Web 服務器後面 - 容器化設置


1. 使用 Java Archive (JAR) 作為獨立應用程序進行部署

Spring Boot 應用程序可以輕鬆打包到 JAR 文件中,並作為獨立應用程序進行部署。這是通過 spring-boot-maven-plugin 這個插件完成的。一旦 Spring 項目通過

Spring Initializr[3] 創建為 Maven 項目,插件就會自動添加到 pom.xml 中。

<code><build>
<plugins>
<plugin>
<groupid>org.springframework.boot/<groupid>
<artifactid>spring-boot-maven-plugin/<artifactid>
/<plugin>
/<plugins>
/<build>/<code>

要將應用程序打包在單個 jar 文件中,需要在項目目錄下運行 maven 命令 mvn package。這將把應用程序打包到一個可執行的 jar 文件中,該文件包含所有依賴項(包括嵌入式 servlet 容器 ,如果它是一個 Web 應用程序)。要運行 jar 文件,請使用以下標準 JVM 命令 java -jar <jar-file-name>.jar。/<jar-file-name>


2. 將 Web Application Archive (WAR) 部署到 servlet 容器中

可以將 Spring Boot 應用程序打包到 WAR 文件中,以部署到現有的 servlet 容器(例如 Tomcat,Jetty 等)中。可以按如下方式完成:

在 pom.xml 文件中,通過 <packaging> war packaging> 指定為 WAR 包。這會將應用程序打包成 WAR 文件(而不是 JAR)。在第二步,將 Tomcat(servlet 容器)依賴關係的範圍設置為 provided(以便它不會部署到 WAR 文件中):/<packaging>

<code><dependency>
<groupid>org.springframework.boot/<groupid>
<artifactid>spring-boot-starter-tomcat/<artifactid> <scope>provided/<scope>
/<dependency>/<code>

通過繼承 SpringBootServletInitializer 並重寫 configure 方法來初始化 Tomcat 所需的 Servlet 上下文,如下所示:

<code>@SpringBootApplication
public class DemoApp extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(DemoApp.class);
}
public static void main(String[] args) {
SpringApplication.run(DemoApp.class, args);
}
}/<code>

要將應用程序打包到 war 文件中,請在項目目錄下運行標準 maven 命令mvn clean package。這將生成可以部署到 servlet 容器中的 WAR 包。要在現有 Tomcat 容器中運行應用程序,請將生成的 WAR 文件複製到tomcat/webapps/目錄。


3. 在 Docker 容器中部署

在將應用程序部署到 Docker 容器之前,我們首先要將應用程序打包在 JAR 文件中。之前已經解釋了這個過程,因此我假設我們有一個 jar 文件。

在第一步,我們需要構建一個容器鏡像。為此,我們首先在項目根目錄中創建一個 Dockerfile 文件,如下所示:

<code># latest oracle openjdk is the basis 將最新的oracle openjdk作為基礎
FROM openjdk:oracle
# copy jar file into container image under app directory 將jar文件複製到容器鏡像的app目錄
COPY target/demoApp.jar app/demoApp.jar

# expose server port accept connections 暴露服務端口接收連接
EXPOSE 8080
# start application 運行應用程序
CMD ["java", "-jar", "app/demoApp.jar"]/<code>

請注意,在上面的代碼片段中,我們假設應用程序 JAR 文件“demoApp.jar”位於項目的 target 目錄下。我們還假設嵌入式 servlet 端口是 8080(這是 Tomcat 的默認情況)。

我們現在可以使用以下命令構建 Docker 鏡像(Dockerfile 所在的位置):

<code>docker image build -t demo-app:latest ./<code>

其中 -t 是要構建的鏡像的名稱和標記。構建鏡像後,我們可以通過以下方式創建和運行容器:

<code>docker container run -p 8080:8080 -d --name app-container demo-app/<code>

其中-p將主機端口(映射)到容器端口(在這種情況下,兩者都是 8080)。選項-d(detach)是指在後臺運行容器,- name指定容器的名稱。


4. 部署在 NGINX Web 服務器後面 - 直接設置

為實際生產配置 servlet 容器(例如 Tomcat 或 Jetty )(即在端口 80 上運行,沒有 root 用戶和使用 SSL)可能不是直接的(但可行)。因此,建議在 Spring Boot 應用程序前使用 Web 服務器(如 Nginx)。這可以通過兩種方式完成: 直接設置或容器設置。在本節中,我們將演示直接設置。

在直接設置中,我們直接在 localhost 上運行 Nginx Web 服務器和 Spring Boot 應用程序(當然在不同的端口上)。我們讓 Ngnix 代理 REST 請求到 Spring Boot 應用程序。為了這:

1.通過 sudo apt-get install nginx 在 Linux 上安裝 Nginx Web 服務器

2.使用文本編輯器打開文件/etc/ngnix/sites-available/default

3.比如說,我們有兩個 Spring Boot 應用程序需要代理。可以用以下內容替換文件中的 location 塊。請注意,可以在此處[4]找到所有 Nginx-Java 配置

<code>location /app1 {
proxy_pass http://localhost:8080;
}
location /app2 {
proxy_pass http://localhost:9000;
}/<code>

基於此,來自 http://localhost/app1/的請求將被定向到 /http://localhost:8080/,來自 http://localhost/app2/的請求將被定向到 /http://localhost:9000/。


4.1 負載均衡

如果您正在運行 Spring Boot 應用程序的多個實例,則可以啟用 Nginx 以應用負載均衡。例如,如果我們在端口 8080,8081 和 8082 上運行 3 個 app1 實例。我們可以在這些服務器之間進行負載均衡,如下所示:

打開文件 /etc/ngnix/sites-available/default 並在文件頂部添加以下內容(在服務器內容之前):

<code># configure load-balancing 配置負載均衡
upstream backend {
server localhost:8080;
server localhost:8081;
server localhost:8082;
}/<code>

修改 app1 的 proxy_pass 參數,如下所示:

<code>location /app1 {
proxy_pass http://backend;
}/<code>

基於此,來自 http://localhost/app1/ 的請求將被定向到 /http://localhost:8080/,/http://localhost:8081/或 /http://localhost:8082/的其中之一。


5. 部署在 NGINX Web 服務器後面 - 容器化設置

在容器化設置中,我們將 Nginx Web 服務器和所有 Spring Boot 應用程序部署在單獨的 Docker 容器上。我們讓 Nginx(在自己的容器中運行)向 Spring Boot 應用程序容器代理 REST 請求。

我們首先將所有 Spring Boot 應用程序打包在 jar 文件中(之前已經解釋過)。此時,請注意通過向 application.properties(或 application.yml)文件添加以下代碼來為每個 Spring Boot 應用程序設置單個服務器端口和根上下文路徑:

<code>server.port=8082
server.servlet.context-path=/search-service
/<code>

然後我們將生成的 jar 包部署在單獨的 Docker 容器中(之前也有解釋)。

例如,我們部署了四個 Spring Boot 應用程序; 一個“分析服務”實例和三個“搜索服務”實例。搜索服務的三個實例將由 Nginx 負載均衡。我們的基本架構如下所示:


Spring Boot 應用程序五種部署方式

我們基於默認配置創建 Nginx 配置文件 nginx.conf 。我們為每個服務添加負載均衡和代理信息,如下所示:

<code>http {

upstream backend {
server search-service-1:8080;
server search-service-2:8081;
server search-service-3:8082;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
server_name _;
location /search-service {
proxy_pass http://backend/search-service;
}
location /analysis-service {
proxy_pass http://analysis-service:8083/analysis-service;
}
}
}
events { worker_connections 1024; }/<code>

基於此,來自http://localhost/search-service/的請求將被定向到 http://search-service-1:8080/search-service/, /http://search-service-2:8081/search-service/和 http://search-service-3:8082/search-service/,來自 http://localhost/analysis-service/ 的請求將被定向到 http://analysis-service:8083/analysis-service/。

創建配置文件(nginx.conf)後,我們將在 Docker 容器中部署 Nginx Web 服務器。為此,我們創建一個 Dockerfile ,如下所示:

<code># latest nginx 最新的nginx
FROM nginx
# copy custom configuration file 複製自定義配置文件
COPY nginx.conf /etc/nginx/nginx.conf
# expose server port 暴露服務端口
EXPOSE 80
# start server 開啟服務
CMD ["nginx", "-g", "daemon off;"]/<code>

我們為 Nginx Web 服務器構建一個 Docker 鏡像,如下所示:

<code>docker image build -t custom-nginx:latest ./<code>

構建所有 Docker 鏡像後,可以通過在以下 docker-compose.yml 文件上運行docker-compose up命令來部署所有系統:

<code>version: '3.7'
services:
nginx_server:
image: custom-nginx
ports:
- '80:80'
networks:
- demo-network
depends_on:
- "search-service-1"
- "search-service-2"
- "search-service-3"
- "analysis-service"
search-service-1:
image: search-service-1
ports:
- '8080:8080'
networks:
- demo-network
search-service-2:
image: search-service-2
ports:
- '8081:8081'
networks:
- demo-network
search-service-3:
image: search-service-3
ports:
- '8082:8082'
networks:
- demo-network
analysis-service:
image: analysis-service
ports:
- '8083:8083'
networks:
- demo-network
networks:
demo-network:

name: demo-network/<code>

以上,我們演示了部署 Spring Boot 應用程序的五種方法。選擇哪種部署方式要基於整體架構以及目標平臺的要求,例如安全性和可用資源。

[1] Deploying Spring Boot Applications: https://medium.com/swlh/deploying-spring-boot-applications-15e14db25ff0

[2] Murat Artim: https://medium.com/@muratartim_5366

[3] Spring Initializr: https://start.spring.io/

[4] 此處: https://www.nginx.com/resources/wiki/start/topics/examples/javaservers/


分享到:


相關文章: