微服务架构项目打包和部署的注意事项

项目源代码拿到了,在 IDEA 中对项目进行修改和功能测试也完成了,终于到了打包和部署的环节。其实打包和部署的步骤并不复杂,只需要在命令行中进入当前项目的顶级目录,之后执行 Maven 的打包命令即可。

命令如下:

mvn clean package '-Dmaven.test.skip'

经过一段时间的等待后,项目中的所有模块都按照 pom.xml 文件中的配置打包成功了,如图 1-46 所示。

image 2025 04 21 20 18 56 015
Figure 1. 图1-46 newbee-mall-cloud 项目的打包过程

用户微服务、购物车微服务、推荐微服务、商品微服务、订单微服务和两个网关服务实例都会被打包成一个可执行的 JAR 包,如 newbee-mall-cloud-user-web-0.0.1-SNAPSHOT.jar、newbee-mall-cloud-goods-web-0.0.1-SNAPSHOT.jar 等可执行文件。打包成功后,进入对应的 target 目录启动 JAR 包,即可启动不同的微服务实例。

执行的命令如下:

java -jar xxxx.jar

以启动商品微服务为例,进入 newbee-mall-cloud-goods-web/target 目录,执行 java-jarnewbee-mall-cloud-goods-web-0.0.1-SNAPSHOT.jar 命令即可启动商品微服务实例,启动过程及报错信息如图 1-47 所示。

image 2025 04 21 20 20 20 328
Figure 2. 图1-47 启动过程及报错信息

是的,没有成功,启动时报错:××.jar 中没有主清单属性。不止是商品微服务,网关服务实例也没有启动成功,报错内容相同。这就说明打出的包存在问题。

这是一个微服务架构的多模块项目,多模块项目中包含多个 Spring Boot 项目,用户微服务、购物车微服务、推荐微服务、商品微服务、订单微服务和两个网关服务实例其实都是 Spring Boot 项目。在这种多模块、多 Spring Boot 实例的项目中,需要在 pom.xml 文件中增加一些配置,否则打包后的 JAR 包就无法正常启动。

这里涉及一个知识点:使用 Maven 构建多个 Spring Boot 实例。这个知识点其实很少会碰到。我们平时开发的基本上是单个的 Spring Boot 项目,在打包时肯定不会遇到这个问题,而在做复杂架构下的项目时会遇到这个问题。解决办法不复杂,在对应的 pom.xml 文件中加入一些打包所需的 plugin 插件并指定对应实例的主启动类的全类名 。 打开用户微服务、购物车微服务、推荐微服务、商品微服务、订单微服务和两个网关服务实例所对应的 newbee-mall-cloud-×××-web 工程目录,并在各自的 pom.xml 文件中增加一些配置。下面以商品微服务和商城端的网关服务为例进行讲解。

打开 newbee-mall-cloud-goods-web 目录下的 pom.xml 文件,在原配置的基础上增加如下代码:

<build>
    <resources>
        <resource>
            <filtering>true</filtering>
            <directory>src/main/resources</directory>
        </resource>
    </resources>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>${java.version}</source>
                <target>${java.version}</target>
                <encoding>${project.build.sourceEncoding}</encoding>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <configuration>
                <encoding>${project.build.sourceEncoding}</encoding>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <mainClass>ltd.goods.cloud.newbee.NewBeeMallCloudGoodsService
                    Application</mainClass>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

增加打包所需的 plugin 插件,并指定商品微服务主启动类 NewBeeMallCloudGoodsServiceApplication 类的全类名。

打开 newbee-mall-cloud-gateway-mall 目录下的 pom.xml 文件,在原配置的基础上增加如下代码:

<build>
    <resources>
        <resource>
            <filtering>true</filtering>
            <directory>src/main/resources</directory>
        </resource>
    </resources>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>${java.version}</source>
                <target>${java.version}</target>
                <encoding>${project.build.sourceEncoding}</encoding>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <configuration>
                <encoding>${project.build.sourceEncoding}</encoding>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <mainClass>ltd.gateway.cloud.newbee.NewBeeMallCloudGateway
                    Application</mainClass>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

同样,增加打包所需的 plugin 插件,并指定网关服务层主启动类 NewBeeMall-CloudMallGatewayApplication 类的全类名。其他需要打包成 JAR 包模块下的 pom.xml 配置文件,也需要增加上述打包配置,这里就不再赘述了。

配置完成后,进入当前项目的顶级目录,执行 Maven 的打包命令。打包成功后,再次执行启动 JAR 包的命令,可以看到 JAR 包中没有主清单属性的问题已经不存在了,Jar 包可以顺利启动,一切正常,如图 1-48 所示。

项目打包和项目部署是两个步骤,得到各个微服务实例的可执行 JAR 包后,就可以进入部署环节了。不管是部署在服务器上,还是部署在本地,基本上都是在命令行执行 java -jar 命令。

下面是在 Linux 服务器上部署时的注意事项。

image 2025 04 21 20 28 34 083
Figure 3. 图1-48 newbee-mall-cloud项目打包和项目启动过程

启动命令:

java -jar newbee-mall-cloud-goods-web-0.0.1-SNAPSHOT.jar

这样启动的项目并没有在后台运行,一旦退出终端项目,基本上就跟着停掉了,可以在命令行前后分别添加 nohup 命令和 & 符号,这样就能够让项目一直在后台运行,并且项目的运行日志会输出到 nohup.out 文件中,此时的命令如下:

nohup java -jar newbee-mall-cloud-goods-web-0.0.1-SNAPSHOT.jar &

想要关闭这个项目,可以先查出它运行时的进程号,然后用 kill 命令关闭它。

想要部署服务集群,可以使用 --server.port 参数指定多个端口号。以部署商品微服务集群为例,执行的命令如下:

#启动时使用 application.properties 配置文件中配置的端口号 29010
nohup java -jar newbee-mall-cloud-goods-web-0.0.1-SNAPSHOT.jar &

#启动时自定义端口号
nohup java -jar newbee-mall-cloud-goods-web-0.0.1-SNAPSHOT.jar --server.port=29011 &

nohup java -jar newbee-mall-cloud-goods-web-0.0.1-SNAPSHOT.jar --server.port=29012 &

这样就可以部署一个微服务实例的集群了。启动后的 JAR 包实例会将自己注册到 NacosServer 中,在被其他微服务调用时也会根据负载均衡算法提供服务。

另外,如果服务器中的内存并不宽裕,启动过多的微服务实例就可能有些吃力。此时,可以在启动命令中添加 JVM 参数限制项目消耗的内存资源,执行的命令如下:

nohup java -jar -server -Xms128m -Xmx384m newbee-mall-cloud-goods-web-0.0.1-SNAPSHOT.jar &

至此,本章的内容介绍完毕。在后续章节中,笔者将结合编码介绍整个微服务架构项目从零到一的开发过程。