写点什么

20231225 介绍一个我解决过的难题

作者:Luke
  • 2023-12-25
    北京
  • 本文字数:1855 字

    阅读完需:约 6 分钟

20231225 介绍一个我解决过的难题

【清楚描述一个你解决过的问题/难题,包括产生的背景和关键要素,你解决的方案及价值,字数不少于 800 字】


引言

在软件开发中,自动化部署已经成为了提高效率的重要手段。大部分情况下,开发者将本地的代码修改推送到远程代码仓库后,利用持续集成工具进行构建并自动部署到远程服务器。然而,对于一个拥有多个微服务的团队,如何在一个代码仓库中根据不同路径实现代码的自动部署和发布,成了一个具有挑战性的问题。

产生背景

将本地的代码在构建后,推送到远程代码仓库后,自动地部署到远程服务器上面。这可能是大部分开发人员都会经历到的日常场景,随着持续构建、部署工具的不断成熟,这种自动部署,也成为了一种比较常见的开发实践方法。然而,我们却遇到了一个难题:一个代码仓库,根据路径(path)不同, 对应部署多个微服务。


大部分微服务架构的项目,都是倡导独立服务对应着独立团队、以及独立代码库的实践,无论是 GitLab CI 还是 Jenkins 的 WebHooks 部署方式,也都是遵循着一个代码仓库,通过一到多个 Pipline 部署到一个服务或一组服务器上面。而我们的团队,将所有代码部署在同一个代码仓库中(且根据部门的权限划分和管理规则,短期内无法进行拆分),要将一个代码仓库的不同模块代码,自动化地部署、发布到不同微服务上,这对我们来说不悌是一个小小的挑战。


关键要素

为了解决这个问题,我们考察了几种方案,最终选择通过 GitLab 的 WebHook 触发 Jenkins 的分发器任务,再根据提交代码的路径来触发不同的 Jenkins 子任务。


以下是解决此问题的三个关键要素:

  1. GitLab WebHook 配置:每当代码合并时,触发 Jenkins 作业

  2. Jenkins 分发任务:配置一个单独的作业作为分发器,根据提交代码的路径触发不同的子任务

  3. Jenkins 子任务:构建并部署实际的代码模块到目标服务器


解决方案

我解决这个问题的核心方案,就是基于不同的文件来触发不同的 Jenkins Job。通过在 Jenkins Job 配置中使用文件路径或文件名模式来实现路径对应 Jenkins 子任务的模式。


例如,对于 bugetctl 模块,在分发器配置中设置 groovy 脚本,匹配 bugetctl/** 模式,这样只有当 bugetctl 目录下的文件发生更改时才会触发该 Job。同样地,对于 assets 模块,设置 assets/** 作为路径,下面是我编写的分发器脚本:


import hudson.model.*  import jenkins.model.*    // 触发流水线脚本  def triggerPipeline(path, jobName) {      // 获取 Jenkins 实例  	def jenkins = currentBuild.rawBuild.project          // 获取提交的代码路径      def changedFiles = currentBuild.changeSets.each { changeSet ->          changeSet.items.each { entry ->              if (entry.path.startsWith(path)) {                  // 触发指定的 Jenkins 子任务                  def job = jenkins.getItemByFullName(jobName, AbstractProject)                  if (job != null) {                      println("Triggering job: " + jobName)                      job.scheduleBuild2(0)                  } else {                      println("Job not found: " + jobName)                  }              }          }      }  }    // 根据提交代码的路径触发不同的 Jenkins 子任务  def submittedPaths = [      "/fusion-fms-account-engine-api/",      "/fusion-fms-assets-api/",      "/fusion-fms-budgetctl-api/",      "/fusion-fms-costallocat-api/",      "/fusion-fms-reports-api/",      "/fusion-fms-sys-api/"  ]  def baseJobName = "fms-platform/fms-dev/fms-api-dev/"  def jobSuffixes = [      "fms-account-engine-api-dev",      "fms-assets-api-dev",      "fms-budgetctl-api-dev",      "fms-costallocat-api-dev",      "fms-reports-api-dev",      "fms-sys-api-dev"  ]    submittedPaths.eachWithIndex { path, index ->      triggerPipeline(path, baseJobName + jobSuffixes[index])  }
复制代码


通过以上脚本工具,我成功将一个代码库部署到了不同的服务上面。


价值

通过以上脚本工具,我们成功地将一个代码库部署到了不同的服务上。这大大提高了代码的部署效率,降低了人工干预的风险,确保了软件的高质量交付。


收获

解决问题时,可以先从自己的影响圈想办法(别老盯着那些限制,先想想自己能做什么改变)。有时候,在看似僵化的管理限制中,我们也能找到不少突破口。别那些客观的限制拖住我们前进的脚步,要相信“事在人为”哦。

用户头像

Luke

关注

三分手艺、七分工具 2017-10-17 加入

还未添加个人简介

评论

发布
暂无评论
20231225 介绍一个我解决过的难题_Luke_InfoQ写作社区