当前位置: 首页 > 知识库问答 >
问题:

java - SpringCloud微服务部署环境参数动态设置?

夹谷星河
2024-01-10

SpringCloud微服务运维最佳实践,如何动态定义各种启动参数?

笔者是一名Java服务端程序员,学习微服务后,在部署时发现过程复杂,且做的重复工作非常多,因此学习基本运维。目标是,使用Kubernetes和容器技术进行微服务编排和部署。

本文只讨论服务容器化,不涉及K8s和Jenkins相关内容。

问题概述

在服务容器化时,一些参数必须动态传入,以适应不同的部署环境。变化的参数包括:

  • 部署环境(开发环境、测试环境、预发环境、生成环境)
  • 服务版本(0.0.1、1.0.2、1.0.1-beta)
  • 服务发现(部署时将服务注册到注册中心如Nacos)

我的Java项目(Example)由多个微服务构成:如Example-core,Example-auth,Example-gateway等。以Example-auth这个微服务作为切入点,打包为Docker容器的代码为:

# 使用官方的OpenJDK 17作为基础镜像FROM openjdk:17# 镜像环境变量:# 开发环境:dev# 测试环境:test# 预发环境:staging# 生产环境:prod, 默认生产环境ARG ENVIRONMENT=prod# Jar包的版本,默认0.0.1-SNAPSHOTARG JAR_VERSION=0.0.1-SNAPSHOT# 注册中心服务地址ARG SERVER_NAME=www.nacos-server.cn# 维护者MAINTAINER xlxing@bupt.edu.cn# 拷贝文件到Docker容器中COPY target/auth-${JAR_VERSION}.jar /app/auth-${JAR_VERSION}.jar# 暴露服务端口EXPOSE 8999# 容器启动项ENTRYPOINT ["java", "-jar", "/app/auth-${JAR_VERSION}.jar", "--spring.profiles.active=${ENVIRONMENT}", "--spring.cloud.nacos.discovery.ip=${SERVER_NAME}"]

在构建容器时可以动态传入参数(jar包版本为1.1.0,环境是dev,服务发现地址www.my-auth.cn,构建的容器命名为myapp/example:auth-dev-1.1.0):

docker build --build-arg JAR_VERSION=1.1.0 ENVIRONMENT=dev SERVER_NAME=www.my-auth.cn -t myapp/example:auth-dev-1.1.0 .

该内容产生了以下两个具体问题:

1. 如何动态获取JAR_VERSION

在构建项目时,仍然需要手动传入项目版本,实际上该信息存在于项目中,如该微服务auth的pom.xml文件:

    <artifactId>auth</artifactId>    <version>0.0.1-SNAPSHOT</version>    <name>auth</name>    <description>权限微服务</description>

理想情况是:后端程序员来定义项目的版本,而流水线只需要依赖项目即可。

但是在当前情况下:当auth项目的version变更时,构建Docker镜像的指令也需要同步变化。该问题可以总结为,构建容器时如何从项目中获取JAR_VERSION?

docker build --build-arg JAR_VERSION=1.1.0 ENVIRONMENT=dev SERVER_NAME=www.my-auth.cn -t myapp/example:auth-dev-1.1.0 .

2. 如何自动获取宿主机的SERVER_NAME

微服务启动时,将该服务注册到Nacos上,声明自己的服务地址。当部署到具体的服务器上时,该地址才被绑定,如auth服务可以部署在server-a上,也可以部署到server-b上。如何在运行时确定服务地址而不是构建时

补充内容:
auth服务的配置文件

spring:  application:    name: auth  # Nacos配置  cloud:    nacos:      server-addr: www.nacos-server.cn      # 服务发现      discovery:        cluster-name: BEIJING        # 设置为非临时实例        ephemeral: true        # 设置命名空间        namespace: e35500e1-2441-4001-b60f-3f7d55bxxxxx      # 配置中心      config:        file-extension: yaml # 文件后缀名        namespace: e35500e1-2441-4001-b60f-3f7d55bxxxxx        group: DEFAULT_GROUPdubbo:  # 将Dubbo注册到Nacos中,这样可供消费者直接使用  application:    name: dubbo-auth  protocol:    name: dubbo    port: -1  registry:    address: nacos://www.nacos-server.cn?namespace=228df068-54b7-405e-9e32-72c759d79ed9    group: DEV_DUBBO_GROUP

拓展问题:使用K8s和容器在分布式环境下部署微服务项目最佳实践?

其中涉及到很多配置相关的问题,缺乏一个系统性的文章探讨如何部署和运维。

一些尝试:

  1. 我有两台服务器A和B,我在部署前已经计划将auth服务部署到B上,因此构建时参数SERVER_NAME=B,构建好的容器无法直接在其他服务器上启动。
    一条可行的方法是,在构建容器时不指定SERVER_NAME,在docker run时动态传入参数。
    ARG SERVER_NAME=www.nacos-server.cn 改为ENV SERVER_NAME=www.nacos-server.cn
  2. JAR_VERSION目前是手动更改。

共有1个答案

司徒高寒
2024-01-10

SpringCloud微服务部署环境参数动态设置

对于你的问题,有几种可能的解决方案。首先,对于JAR_VERSION的动态获取,一种可能的方法是使用Maven的属性。你可以在pom.xml文件中定义一个属性,然后在构建Docker镜像时使用这个属性。例如:

在pom.xml中:

<project>    ...    <properties>        <version>0.0.1-SNAPSHOT</version>    </properties>    ...</project>

然后在Dockerfile中:

FROM openjdk:17ARG JAR_VERSION=${version}...COPY target/auth-${JAR_VERSION}.jar /app/auth-${JAR_VERSION}.jar...

这样,当你在构建Docker镜像时,Maven会自动替换${version}为实际的版本号。

至于如何自动获取宿主机的SERVER_NAME,一种可能的方法是使用环境变量。你可以在部署时设置环境变量,然后在你的程序中读取这个环境变量。例如,你可以在Docker run时设置环境变量:

docker run -e SERVER_NAME=www.my-auth.cn -t myapp/example:auth-dev-1.1.0 .

然后在你的Java程序中读取这个环境变量:

String serverName = System.getenv("SERVER_NAME");

这样,你可以在部署时动态地设置服务器地址,而不需要修改Dockerfile或程序代码。

 类似资料:
  • 在开展实验之前,我们需要根据不同的平台提前安装相关依赖的软件包,具体需要的软件包如下: Rust 工具链 Rust 版本管理工具:rustup Rust 软件包管理工具:cargo Rust 编译器:rustc 等等 虚拟机软件:QEMU (版本至少支持 RISC-V 64) 具体安装的方法在不同平台上安装方式类似,但也有细微差别,后面会有具体说明。 安装 QEMU 根据不同平台,我们分为下面 3

  • 我想部署我的微服务的几个实例,它们使用特定的端口,但使其可伸缩,并且不在任务定义/dockerfile中修复端口。我的微服务可以监听环境变量或命令行中提供的端口。

  • PWA 项目必须部署在 HTTPS 环境上才能够生效,主要是因为 Service Worker 只会在 HTTPS 环境下才能注册成功,我们不用担心在本地开发的时候 Service Worker 是否生效的问题,因为 Service Worker 在 localhost 和 127.0.0.1 的 host 下是能够注册成功的,这样可以确保我们在本地调试工作是能够顺利进行的。我们这里讲述的是如何部

  • 我目前正在开发一个云备份解决方案,其中涉及到多达8个在spring-boot中开发的微服务,并使用mongo DB atlas作为持久层。 微服务包括Netflix ZUUL API网关和Netflix Eureka作为服务发现机制。微服务被要求彼此进行明显的对话。 对微服务进行了对接。到目前为止,我已经使用docker-compose文件将它们部署到EC2实例中,该文件列出了使用docker网络

  • 我正在尝试开发一个Spring Cloud微服务,并使用Elastic Beanstalk部署到AWS cloud中。当我搜索部署选项时,我发现了Beanstalk的部署环境。我有一点困惑。我可以在不启动EC2机器的情况下使用Elastic Beanstalk部署我的微服务吗? 在这里,我只接近弹性豆茎服务。使用弹性Beanstalk部署微服务而不启动EC2是可能的吗? 我是AWS世界的初学者。