Spring Boot应用程序五种部署方式(翻译)

翻译自 Deploying Spring Boot Applications

原作者 Murat Artim

可以使用各种方法将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 创建为Maven项目,插件就会自动添加到pom.xml中。

1
2
3
4
5
6
7
8
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

要将应用程序打包在单个 jar 文件中,需要在项目目录下运行maven命令 mvn package。这将把应用程序打包到一个可执行的jar文件中,该文件包含所有依赖项(包括嵌入式servlet容器 ,如果它是一个Web应用程序)。要运行 jar 文件,请使用以下标准JVM命令 java -jar <jar-file-name>.jar

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

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

在pom.xml文件中,通过 <packaging> war </ packaging> 指定为WAR包。这会将应用程序打包成WAR文件(而不是JAR)。在第二步,将Tomcat(servlet容器)依赖关系的范围设置为provided(以便它不会部署到WAR文件中):

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId
<scope>provided</scope>
</dependency>

通过继承 SpringBootServletInitializer 并重写 configure 方法来初始化 Tomcat 所需的 Servlet 上下文,如下所示:

1
2
3
4
5
6
7
8
9
10
@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);
}
}

要将应用程序打包到 war 文件中,请在项目目录下运行标准maven命令mvn clean package。这将生成可以部署到 servlet 容器中的 WAR 包。要在现有 Tomcat 容器中运行应用程序,请将生成的 WAR 文件复制到 tomcat/webapps/目录。

3. 在Docker容器中部署

在将应用程序部署到Docker容器之前,我们首先要将应用程序打包在 JAR 文件中。之前已经解释了这个过程,因此我假设我们有一个jar文件。

在第一步,我们需要构建一个容器镜像。为此,我们首先在项目根目录中创建一个Dockerfile文件,如下所示:

1
2
3
4
5
6
7
8
# 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"]

请注意,在上面的代码片段中,我们假设应用程序 JAR 文件“demoApp.jar”位于项目的 target 目录下。我们还假设嵌入式 servlet 端口是8080(这是 Tomcat 的默认情况)。

我们现在可以使用以下命令构建Docker镜像(Dockerfile所在的位置):

1
docker image build -t demo-app:latest .

其中 -t 是要构建的镜像的名称和标记。构建镜像后,我们可以通过以下方式创建和运行容器:

1
docker container run -p 8080:8080 -d --name app-container demo-app

其中-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 块。请注意,可以在此处找到所有Nginx-Java配置

1
2
3
4
5
6
location /app1 {
proxy_pass http://localhost:8080;
}
location /app2 {
proxy_pass http://localhost:9000;
}

基于此,来自 http://localhost/app1/的请求将被定向到 /http://localhost:8080/,来自 http://localhost/app2/ 的请求将被定向到 /http://localhost:9000/

负载均衡

如果您正在运行 Spring Boot 应用程序的多个实例,则可以启用 Nginx 以应用负载均衡。例如,如果我们在端口8080,8081和8082上运行3个 app1 实例。我们可以在这些服务器之间进行负载均衡,如下所示:

打开文件 /etc/ngnix/sites-available/default 并在文件顶部添加以下内容(在服务器内容之前):

1
2
3
4
5
6
# configure load-balancing 配置负载均衡
upstream backend {
server localhost:8080;
server localhost:8081;
server localhost:8082;
}

修改 app1 的 proxy_pass 参数,如下所示:

1
2
3
location /app1 {
proxy_pass http://backend;
}

基于此,来自 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应用程序设置单个服务器端口和根上下文路径:

1
2
server.port=8082
server.servlet.context-path=/search-service

然后我们将生成的 jar 包部署在单独的 Docker 容器中(之前也有解释)。

例如,我们部署了四个 Spring Boot 应用程序; 一个“分析服务”实例和三个“搜索服务”实例。搜索服务的三个实例将由Nginx负载均衡。我们的基本架构如下所示:

我们基于默认配置创建 Nginx 配置文件 nginx.conf 。我们为每个服务添加负载均衡和代理信息,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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; }

基于此,来自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 ,如下所示:

1
2
3
4
5
6
7
8
# 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;"]

我们为 Nginx Web 服务器构建一个Docker镜像,如下所示:

1
docker image build -t custom-nginx:latest .

构建所有Docker镜像后,可以通过在以下 docker-compose.yml 文件上运行docker-compose up命令来部署所有系统:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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

以上,我们演示了部署 Spring Boot 应用程序的五种方法。选择哪种部署方式要基于整体架构以及目标平台的要求,例如安全性和可用资源。

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2015-2023 高行行
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信