ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于阿里云云效实现Ruoyi-Cloud微服务自动化部署CI/CD实践

基于阿里云云效实现Ruoyi-Cloud微服务自动化部署CI/CD实践 1. 从手动“搬砖”到云端“流水线”为什么我们需要自动化部署每次在本地打包好一个微服务然后手动上传到服务器再登录服务器执行一堆命令看着日志滚动心里是不是总有点发虚尤其是在发布ruoyi-cloud这种包含多个模块的微服务架构时这种重复、繁琐且容易出错的手工操作简直就是对开发效率和系统稳定性的双重考验。我经历过不止一次因为手滑传错了包或者忘了重启某个服务导致线上功能异常半夜被叫起来回滚。这种痛相信很多搞后端的朋友都懂。所以当项目复杂度上来之后搭建一套自动化部署流水线就不再是“锦上添花”而是“雪中送炭”的必需品了。它的核心价值就是把我们从重复的体力劳动中解放出来把部署这个动作标准化、流程化、可视化。今天要聊的就是如何利用阿里云的云效平台为经典的ruoyi-cloud微服务项目打造一条全自动的CI/CD流水线。简单来说我们的目标就是代码一提交自动完成构建、测试、打包、部署到服务器的全过程实现真正的“一键发布”。ruoyi-cloud作为一个基于Spring Cloud Alibaba的流行开源微服务框架其模块多、依赖复杂的特点正是检验自动化部署方案的好场景。而阿里云云效作为阿里云官方的DevOps平台提供了从代码管理到应用交付的一站式服务与阿里云其他产品如ECS、容器服务的集成度非常高对于已经在使用阿里云生态的团队来说上手成本和后续维护成本都相对较低。接下来我们就一步步拆解如何将这两个“利器”结合起来。2. 部署蓝图与核心组件选型为什么是“云效 自有服务器”在开始动手之前我们先得把整个部署的蓝图和核心的技术选型定下来。很多人一提到自动化部署可能第一反应是Jenkins。确实Jenkins很强大插件生态丰富但它也需要我们自己维护一台或多台用于执行构建任务的“代理”服务器Agent包括安装Java环境、配置各种工具等前期搭建和后期维护都有一定成本。而云效的流水线可以理解为一种“托管式”的CI/CD服务。它提供了开箱即用的构建环境内置了Maven、JDK、Node.js、Docker等常用工具我们只需要关心流水线任务的编排逻辑无需操心底层环境的维护。这对于中小团队或者希望快速上手的项目来说尤其友好。我们的方案核心是代码托管在云效Codeup或其它Git仓库利用云效流水线进行构建和打包最终将生成的Jar包或Docker镜像部署到我们自己的阿里云ECS服务器上。这里就引出了几个关键组件和它们的分工云效流水线作为CI/CD的“大脑”和“指挥中心”负责监听代码变更、调度构建任务、执行部署脚本。云效代码仓库Codeup存放ruoyi-cloud的源代码流水线通过Webhook感知代码推送事件。构建环境云效提供的托管环境用于执行mvn clean package等构建命令。部署目标我们自有的阿里云ECS服务器集群。每个微服务如ruoyi-auth,ruoyi-system,ruoyi-gateway都将部署在独立的ECS实例上或者通过端口区分部署在同一台机器上。传输与执行媒介如何将构建产物Jar包从云效构建环境安全地传输到目标服务器并在服务器上执行启动命令这里我们选择最通用和直接的方式通过SSH连接。整个流程可以概括为开发者推送代码 - 触发云效流水线 - 流水线拉取代码、执行Maven构建 - 通过SSH将Jar包上传到指定服务器 - 通过SSH在服务器上执行重启服务的脚本。这个方案不依赖复杂的容器编排理解起来直观适合从传统部署方式过渡到自动化的团队。3. 前期准备配置好你的“战场”兵马未动粮草先行。在编排流水线之前我们需要在云效和服务器端做好一系列的基础配置。这些步骤看似琐碎但每一步都关乎后续流程能否顺畅跑通。3.1 阿里云ECS服务器环境初始化假设你已经购买了几台阿里云ECSCentOS 7.x 或 Alibaba Cloud Linux并分配了公网IP。我们需要在这些服务器上为微服务部署做好准备。首先是基础运行环境。Ruoyi-cloud项目需要Java运行环境。登录你的每一台部署服务器执行以下操作# 1. 安装JDK 8或11以JDK 11为例使用yum安装 sudo yum install -y java-11-openjdk-devel # 2. 验证安装 java -version # 3. 创建统一的应用部署目录。我习惯将所有的微服务都放在 /opt/apps 下每个服务一个子目录。 sudo mkdir -p /opt/apps sudo chown -R $(whoami):$(whoami) /opt/apps # 将目录权限给当前用户避免后续sudo操作 # 4. 准备服务管理脚本。在 /opt/apps 下为每个服务创建如 ruoyi-auth 的目录并在其中放置一个启动脚本 start.sh。 # 例如在 /opt/apps/ruoyi-auth 目录下创建 start.sh cd /opt/apps mkdir ruoyi-auth ruoyi-system ruoyi-gateway # 根据你的模块创建 # 编辑 ruoyi-auth 的 start.sh cat /opt/apps/ruoyi-auth/start.sh EOF #!/bin/bash APP_NAMEruoyi-auth.jar APP_PATH/opt/apps/ruoyi-auth/$APP_NAME LOG_PATH/opt/apps/ruoyi-auth/logs/ruoyi-auth.log # 查找并停止旧进程 PID$(ps -ef | grep $APP_NAME | grep -v grep | awk {print $2}) if [ -n $PID ]; then echo Stopping $APP_NAME (PID: $PID)... kill -15 $PID sleep 5 # 强制杀死如果优雅停止失败 if ps -p $PID /dev/null; then kill -9 $PID fi fi # 备份旧jar包可选建议保留最近几个版本 # cp $APP_PATH $APP_PATH.$(date %Y%m%d%H%M%S).bak # 启动新服务 nohup java -Xms512m -Xmx512m -jar $APP_PATH --spring.profiles.activeprod $LOG_PATH 21 echo $APP_NAME started. EOF # 赋予脚本执行权限 chmod x /opt/apps/ruoyi-auth/start.sh这个脚本做了几件事定义应用名和路径、优雅停止旧进程、以nohup方式后台启动新进程并指定生产环境配置同时将日志输出到文件。你需要为每个微服务都准备一个类似的脚本。其次配置服务器SSH密钥对用于云效流水线免密登录。这是自动化部署的关键。不要在流水线里直接写密码非常不安全。在其中一台服务器上或者在你的本地机器生成SSH密钥对ssh-keygen -t rsa -b 4096 -C “yunxiao-deploy-key” -f ~/.ssh/yunxiao_deploy执行后会生成两个文件yunxiao_deploy私钥和yunxiao_deploy.pub公钥。私钥是绝密绝对不能泄露。将公钥内容添加到所有目标部署服务器的~/.ssh/authorized_keys文件中。# 在目标服务器上执行 echo “你的公钥内容” ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys确保.ssh目录权限为700authorized_keys文件权限为600。注意一个更安全的做法是为云效流水线专门创建一个具有最小必要权限的系统用户如deployer而不是直接使用 root 或 ecs-user。然后用这个用户的home目录来配置SSH密钥和部署目录。这里为了简化演示使用了当前用户。3.2 云效平台基础配置现在我们把战场转移到阿里云云效平台https://devops.aliyun.com。第一步创建企业/项目。如果你还没有云效项目需要先创建一个。云效的组织结构一般是“企业-项目-应用”。我们可以在一个项目下管理整个ruoyi-cloud的流水线。第二步配置代码仓库。在云效中进入“代码管理”-“代码库”。你可以选择“导入代码库”将你的ruoyi-cloud项目Git地址导入到云效的Codeup中。这样做的好处是网络连通性好并且可以方便地配置代码扫描、门禁等高级功能。当然你也可以直接使用外部Git仓库如GitHub、Gitee云效同样支持。第三步也是至关重要的一步在云效中配置“主机组”。主机组就是你要部署的目标服务器列表。进入云效项目找到“流水线”-“主机组”管理。点击“新建主机组”给它起个名字比如 “ruoyi-cloud-prod”。在“添加主机”界面你需要填写服务器的公网IP、SSH端口默认22、以及刚才生成的私钥内容。主机IP你的ECS公网IP。端口22。登录账号你配置了公钥的那个用户名例如ecs-user或root。登录密码/密钥选择“私钥”然后将yunxiao_deploy文件的内容全部复制粘贴进去。点击“测试连接”如果显示“连接成功”说明配置正确。然后将所有需要部署的服务器都按此方式添加到这个主机组中。第四步配置“构建集群”。云效流水线默认使用共享的构建集群对于大多数Java项目来说足够了。如果你的项目有特殊环境需求比如需要特定版本的Maven或自定义工具可以申请开通“自定义构建集群”但这属于高级功能初期可以不用。至此我们的“战场”就准备好了。服务器在待命云效平台也知道了如何连接它们。接下来就是设计并组装流水线这个“自动化机器”了。4. 流水线核心阶段详解从代码到服务的旅程一条完整的云效流水线通常由多个“阶段”组成每个阶段包含一个或多个“任务”。对于ruoyi-cloud的部署我们可以设计四个核心阶段代码检出 - 构建打包 - 部署发布 - 结果通知。我们直接在云效的流水线编辑器中通过可视化拖拽的方式来配置。4.1 阶段一代码检出这个阶段的任务非常简单就是让流水线能拿到最新的代码。添加一个“代码源”任务。代码库选择你之前导入或配置好的ruoyi-cloud代码库。分支通常选择master或main作为发布分支。你也可以配置为监听特定分支的推送事件自动触发比如feature/*分支推送到dev环境。高级设置可以配置“Webhook触发”这样每次向该分支推送代码时流水线就会自动运行。这是实现CI持续集成的关键。4.2 阶段二构建打包这是流水线的“生产车间”。我们在这里完成Maven构建、单元测试可选、打包等操作。添加一个“构建”任务选择“Java Maven”构建模板。关键配置解析构建环境选择云效提供的默认Java环境如“Java 11 with Maven 3.6”。确保与你本地开发环境一致。构建命令这是核心。ruoyi-cloud是一个多模块项目根目录下有一个pom.xml。我们通常有两种构建策略整体构建在根目录执行mvn clean package -DskipTests。这会构建所有模块为每个模块生成独立的Jar包位于各自模块的target目录下。-DskipTests是为了加快构建速度如果你需要运行单元测试可以去掉。选择性构建如果你只修改了某个服务想只构建该服务可以使用mvn clean package -pl ruoyi-auth -am -DskipTests。-pl指定模块-am会同时构建该模块依赖的其他模块。 对于生产部署我建议使用整体构建确保所有模块的版本一致性。产物路径构建完成后我们需要指定哪些文件是“构建产物”以便在后续阶段使用。对于ruoyi-cloud每个微服务模块的Jar包就是产物。你可以使用通配符来指定**/target/*.jar这个路径会匹配所有模块target目录下的jar文件。云效会将这些文件打包成一个压缩包供下载或传递给后续任务。缓存配置这是一个提升构建速度的利器。Maven构建会下载大量依赖到本地仓库.m2目录。我们可以配置缓存路径~/.m2/repository。这样下一次流水线运行时就可以复用之前下载的依赖极大缩短构建时间。实操心得在构建命令中我强烈建议加上-Dmaven.test.skiptrue而不仅仅是-DskipTests。因为-DskipTests会跳过测试运行但可能还会编译测试代码。-Dmaven.test.skiptrue会跳过整个测试编译和执行阶段速度更快。对于追求快速反馈的CI流程这很实用。当然这取决于你对代码质量门禁的要求。4.3 阶段三部署发布这是最核心、也最需要精细操作的阶段。我们需要将上一步构建出的多个Jar包分别上传到对应的服务器并执行重启脚本。由于我们有多个服务、多台服务器这个阶段通常会包含多个并行的“部署”任务。以部署ruoyi-auth服务到服务器A为例添加一个“部署”任务选择“主机部署”模板。选择主机组选择我们之前创建的 “ruoyi-cloud-prod” 主机组。你可以通过“主机标签”功能更精细地控制将任务下发到哪台具体的主机。例如给服务器A打上标签auth-host然后在任务中指定只部署到带有该标签的主机。下载制品在“上传前准备”或“下载制品”步骤中选择上游“构建”阶段产生的制品。我们需要从中筛选出ruoyi-auth模块的Jar包。云效的制品下载后会放在一个临时目录比如$WORKSPACE。 这里有个技巧由于我们上传的是匹配**/target/*.jar的所有jar包它们会被平铺在一个目录里。我们需要写一个简单的Shell脚本根据文件名来区分并复制到目标位置。部署脚本这是部署任务的灵魂。我们需要编写一段Shell脚本完成以下操作找到ruoyi-auth.jar。通过SCP或直接复制的方式将其上传到目标服务器的/opt/apps/ruoyi-auth/目录覆盖旧的。在目标服务器上执行我们预先准备好的启动脚本start.sh。#!/bin/bash # 假设构建产物被下载到了当前目录 # 找到 ruoyi-auth 的jar包 AUTH_JAR$(find . -name ruoyi-auth*.jar -type f | head -n 1) if [ -z $AUTH_JAR ]; then echo “错误未找到 ruoyi-auth 的jar包” exit 1 fi # 定义目标服务器上的路径 REMOTE_USERecs-user REMOTE_HOST你的服务器A IP # 如果使用主机组这里可以用变量代替如 $HOST_IP REMOTE_DIR/opt/apps/ruoyi-auth/ REMOTE_JAR_NAMEruoyi-auth.jar echo “正在上传 $AUTH_JAR 到 $REMOTE_HOST:$REMOTE_DIR...” # 使用scp上传这里利用了云效主机组配置的SSH密钥无需额外密码 scp -o StrictHostKeyCheckingno $AUTH_JAR $REMOTE_USER$REMOTE_HOST:$REMOTE_DIR$REMOTE_JAR_NAME if [ $? -eq 0 ]; then echo “上传成功。” else echo “上传失败” exit 1 fi echo “在远程服务器上执行部署脚本...” # 通过ssh执行远程命令 ssh -o StrictHostKeyCheckingno $REMOTE_USER$REMOTE_HOST “cd $REMOTE_DIR chmod x start.sh ./start.sh” # 可以增加一个健康检查确保服务启动成功 sleep 10 if ssh -o StrictHostKeyCheckingno $REMOTE_USER$REMOTE_HOST “curl -s http://localhost:8080/actuator/health | grep -q ‘UP’”; then echo “服务健康检查通过。” else echo “警告服务健康检查未通过请查看日志。” fi关键点解析-o StrictHostKeyCheckingno这个参数在自动化脚本中很重要它避免了SSH首次连接时提示“Are you sure you want to continue connecting? (yes/no)”导致脚本中断。顺序问题在微服务架构中服务间有依赖关系。例如ruoyi-system可能依赖ruoyi-auth的服务发现。因此部署阶段的任务不应该是完全并行的。你需要设置任务间的依赖关系。通常先部署基础服务如认证中心、配置中心、注册中心再部署业务服务最后部署网关。在云效流水线编辑器中你可以通过拖拽任务之间的连线来设置“上游-下游”依赖。回滚策略一个健壮的流水线必须考虑回滚。你可以在部署脚本中在覆盖旧Jar包前先将其备份。如果健康检查失败则自动执行回滚脚本将备份的Jar包恢复并重启。云效流水线也支持“人工卡点”你可以在部署前设置一个“人工确认”阶段由负责人确认后再执行生产部署。4.4 阶段四结果通知无论构建部署成功还是失败我们都应该及时通知相关人员。云效流水线支持多种通知方式邮件通知配置收件人列表流水线结束后自动发送。钉钉/企业微信机器人这是更推荐的方式实时性更强。你可以在钉钉群中添加一个“自定义机器人”获取Webhook地址然后在云效的通知配置中填入。通知消息会包含流水线名称、执行结果成功/失败、触发人、持续时间等关键信息并可以直接点击链接跳转到流水线详情页查看日志。配置好通知后整个CI/CD的闭环就形成了代码推送 - 自动构建 - 自动部署 - 结果通知。团队所有成员都能及时感知集成状态。5. 高级配置与避坑指南让流水线更健壮基本的流水线跑通后我们还需要考虑一些进阶问题让整个流程更可靠、更高效。5.1 多环境管理开发、测试、生产一个项目通常有多个环境dev/test/staging/prod。我们不可能为每个环境都复制一条流水线。云效提供了“变量组”和“流水线参数”的功能来优雅地解决这个问题。使用变量组你可以创建名为“dev-config”、“prod-config”的变量组里面定义环境相关的变量如DEPLOY_HOST_GROUP: 部署主机组ID不同环境对应不同的主机组MAVEN_PROFILE:dev或prod对应Spring Boot的spring.profiles.activeNEXUS_REPO_URL: 不同环境的Maven私服地址如果需要在构建命令中使用变量在构建任务的“构建命令”中你可以引用这些变量。mvn clean package -DskipTests -P${MAVEN_PROFILE}这里-P是激活Maven的profile你需要在项目的pom.xml中配置好不同profile对应的配置如不同的数据库连接、注册中心地址。在部署脚本中使用变量同样在部署脚本中你可以用${DEPLOY_HOST}这样的变量来代表不同环境的目标服务器IP。运行时选择环境在流水线设置中可以添加“流水线参数”。例如添加一个名为“DEPLOY_ENV”的枚举类型参数选项为“dev”、“test”、“prod”。运行流水线时手动选择要部署的环境。流水线内部根据这个参数的值去关联对应的变量组。这样一条流水线就具备了部署到多环境的能力大大减少了维护成本。5.2 构建缓存与依赖加速Maven构建慢主要慢在下载依赖。除了使用云效的构建缓存还有几个优化点配置阿里云Maven镜像在云效的构建机中默认的Maven配置可能不是国内镜像。你可以在项目的根目录下放一个settings.xml文件或者在构建命令中直接指定镜像。mvn clean package -DskipTests -s settings.xml这个settings.xml里配置阿里云的Maven镜像仓库地址下载速度会快很多。使用云效“制品仓库”对于企业内部发布的二方库即自己公司其他团队提供的jar包可以推送到云效的制品仓库。然后在构建时优先从制品仓库拉取这比从公网拉取更稳定、更快。构建集群选择如果项目非常大依赖极多可以考虑申请更高规格的自定义构建集群更多CPU和内存或者启用“缓存共享”功能让同一个项目下的不同流水线可以共享缓存。5.3 部署过程中的常见“坑”与解决方案坑1服务端口冲突或启动失败。现象部署脚本显示执行成功但服务实际没起来或者健康检查失败。排查第一时间登录目标服务器查看应用日志。日志路径就在我们启动脚本里定义的LOG_PATH。tail -f /opt/apps/ruoyi-auth/logs/ruoyi-auth.log常见原因端口被占用上一个进程没有成功杀死。可以在启动脚本的“停止旧进程”部分加强逻辑比如循环检查直到进程消失。配置文件错误application-prod.yml中的数据库、Redis、Nacos等连接信息配置错误。确保不同环境的配置文件正确且构建时激活了正确的profile。依赖服务未就绪例如ruoyi-system启动时ruoyi-auth认证中心或Nacos注册中心还没启动完成。这就需要我们在流水线中合理安排部署顺序并增加服务间就绪等待的逻辑比如在脚本里用curl循环检查依赖服务的健康端点。坑2Jar包上传成功但启动脚本权限不足。现象SSH执行远程命令失败提示Permission denied。解决确保远程服务器上的部署目录和启动脚本对执行SSH命令的用户有读写和执行权限。在我们的脚本里已经通过chmod x start.sh来赋予执行权。如果还是不行检查整个路径的权限。坑3流水线构建成功但部署阶段卡住或超时。现象部署任务长时间处于“执行中”最后超时失败。排查检查云效“主机组”中该服务器的连接状态是否正常。登录云效构建日志查看部署脚本的输出通常错误信息会在这里显示。可能是网络问题或者目标服务器负载过高SSH连接缓慢。可以考虑在部署脚本的SSH命令中添加超时参数-o ConnectTimeout30。预防在部署脚本中对关键操作如scp, ssh增加明确的成功/失败判断通过$?并输出清晰的日志。坑4多模块构建如何精准获取目标Jar包现象构建产物包含了所有模块的jar部署ruoyi-auth的脚本错误地拿到了ruoyi-system的jar。解决我们的示例脚本使用find . -name “ruoyi-auth*.jar”来查找这依赖于jar包名称的规范性。确保你的pom.xml中每个模块的finalName配置正确或者使用artifactId作为jar包名前缀。一个更稳健的做法是在构建阶段利用云效的“构建物上传”功能为每个模块的jar包打上明确的标签或存放到不同的制品路径在部署阶段直接按标签下载。6. 从Jar包到Docker容器演进之路我们上述的方案是基于直接部署Jar包到虚拟机。这是一种经典且直接的方式。但随着云原生的发展将应用容器化Docker部署正成为主流。云效流水线同样能很好地支持Docker。演进思路构建阶段不再只是生成Jar包而是构建Docker镜像。在构建命令中加入Docker构建步骤需要构建环境安装Docker。# 在构建阶段增加步骤 mvn clean package -DskipTests # 假设每个模块根目录都有Dockerfile docker build -t registry.cn-hangzhou.aliyuncs.com/your-namespace/ruoyi-auth:${BUILD_ID} ./ruoyi-auth docker push registry.cn-hangzhou.aliyuncs.com/your-namespace/ruoyi-auth:${BUILD_ID}部署阶段任务类型变为“Kubernetes部署”如果你用K8s或者“主机部署”但执行Docker命令。脚本变为ssh userhost “docker pull your-image:tag docker stop ruoyi-auth-container docker rm ruoyi-auth-container docker run -d --name ruoyi-auth-container -p 8080:8080 your-image:tag”优势环境一致性更好部署更轻量只需拉取镜像更容易实现滚动更新和回滚。是否要立即采用Docker取决于团队的运维能力和技术规划。对于刚接触自动化部署的团队我建议先从简单的Jar包部署开始把CI/CD的主流程跑通解决“有无问题”。当团队熟悉了整个自动化流程后再向容器化演进就会水到渠成。最后我想说的是搭建这条流水线不是一劳永逸的。它需要随着项目的发展而迭代。比如加入代码质量扫描SonarQube、自动化测试、安全扫描等阶段。但最重要的是迈出第一步先让代码能够自动、可靠地跑到服务器上。当你第一次看到代码推送后几分钟内服务就自动更新完毕那种解放双手的成就感会让你觉得之前所有的折腾都是值得的。
返回列表