自动化运维|云原生架构下的产品自动化发布、快速部署和持续交付实战之路

news2024/11/17 14:27:25

自动化运维|云原生架构下的产品自动化发布、快速部署和持续交付实战之路。

1.背景介绍
CI/CD是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法。CI/CD 的核心概念是持续集成、持续交付和持续部署。作为一种面向开发和运维团队的解决方案,CI/CD 主要针对在集成新代码时所引发的问题(亦称:“集成地狱”)。CI/CD创建了一个可重复的、可靠的且可预见的发布流程,从而大大缩短了发布周期,不仅节省下了巨大的金钱成本,还节省了包括建立和维护这样一个发布系统所需要的时间投入。
在引入CI/CD技术之前,公司测试人员自动化打包主要依赖Jenkins实现,在配置任务的源码、构建触发器、构建环境、构建、构建后操作等步骤后,可以触发构建任务。相比传统的拉代码、运行命令打包、整理上传更新文件,重启服务等繁琐的操作,Jenkins任务构建这种方式在一定程度上节省了测试和研发人员的时间。但随着代码仓库数量的日益增长,以及Jenkins在公司内部使用程度越来越深,一些问题也逐渐暴露。例如:

每一套代码或服务都需要繁琐的job配置工作,且大部分是重复劳动。

研发人员和测试人员都在使用Jenkins,需要一定的学习成本。

缺少打包结果通知,不能及时获取打包结果。

构建完成后需要手动下载归档文件,并整理后创建更新任务。

公用测试环境,频繁更新重启服务(特别是封版期间)导致服务中断的问题。

为了解决以上问题,我们使用了Kubernetes 原生 CI/CD 构建框架Tekton和基于Kubernetes的声明式持续交付工具Argo CD,并将流水线接入项目管理平台Redmine,简化了代码打包步骤、降低了使用人员的学习成本、提供稳定的测试环境、自动粘贴归档文件下载链接、自动创建更新任务等,进一步提高了持续集成的效率。

  1. 系统设计
    流水线系统设计以项目管理平台为入口,Kubernetes为环境基础,使用Tekton完成CI部分功能,在构建完成后更新服务编排文件。Argo CD则负责持续监控应用状态,并更新应用。

在这里插入图片描述
2.1Kubernetes简介
Kubernetes是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署、规划、更新、维护的一种机制。

Kubernetes一个核心的特点就是能够自主的管理容器来保证云平台中的容器按照用户的期望状态运行着(比如用户想让apache一直运行,用户不需要关心怎么去做,Kubernetes会自动去监控,然后去重启,新建,总之,让apache一直提供服务),管理员可以加载一个微型服务,让规划器来找到合适的位置,同时,Kubernetes也系统提升工具以及人性化方面,让用户能够方便的部署自己的应用(就像canary deployments)。

2.2Tekton简介
Tekton 是一个基于 Kubernetes 的云原生 CI/CD 开源框架,属于 CD 基金会的项目之一。Tekton 通过定义 CRD 的方式,让用户以灵活的自定义流水线以满足自身 CI/CD 需求。

Tekton 最主要的四个概念为:Task、TaskRun、Pipeline 以及 PipelineRun。

Task: Task 为构建任务,是 Tekton 中不可分割的最小单位,正如同 Pod 在 Kubernetes 中的概念一样。在 Task 中,可以有多个 Step,每个 Step 由一个 Container 来执行。

Pipeline: Pipeline 由一个或多个 Task 组成。在 Pipeline 中,用户可以定义这些 Task 的执行顺序以及依赖关系来组成 DAG(有向无环图)。

PipelineRun: PipelineRun 是 Pipeline 的实际执行产物,当用户定义好 Pipeline 后,可以通过创建 PipelineRun 的方式来执行流水线,并生成一条流水线记录。

TaskRun: PipelineRun 被创建出来后,会对应 Pipeline 里面的 Task 创建各自的 TaskRun。一个 TaskRun 控制一个 Pod,Task 中的 Step 对应 Pod 中的 Container。当然,TaskRun 也可以单独被创建。

综上:Pipeline 由多个 Task 组成,每次执行对应生成一条 PipelineRun,其控制的 TaskRun 将创建实际运行的 Pod。

在这里插入图片描述
2.3Argo CD 简介
Argo CD 是一个为 Kubernetes 而生的,遵循声明式 GitOps 理念的持续部署(CD)工具,它的配置和使用非常简单,并且自带一个简单易用的 Dashboard 页面,并且支持多种配置管理/模板工具(例如 Kustomize、Helm、Ksonnet、Jsonnet、plain-YAML)。

Argo CD 被实现为一个 Kubernetes 控制器,它持续监控应用的实际状态,周期性地拉取 Git 仓库中的配置清单,并将实际状态与期望状态进行比较,如果实际状态不符合期望状态,就会更新应用的实际状态以匹配期望状态。

Argo CD的主要功能:

可搭配使用各种配置管理工具(如 ksonnet/jsonnet、Helm 和 kustomize)使应用程序与 Git 中定义的保持一致。

将应用程序自动部署到指定的目标环境。

持续监控已部署的应用程序。

基于 Web 和 CLI 的操作,以及应用程序可视化。

部署或回滚到 Git 仓库中提交的应用程序的任何状态(这也是使用 Git 进行版本管理的一大好处。

在这里插入图片描述
2.4项目管理平台Redmine
政通项目管理平台是流水线使用的入口系统,在同步保存Gitlab仓库、分支、CI/CD参数后,新增流水线任务时将参数传给Tekton。流水线任务执行时,会将当前流水线信息推送到项目管理平台。

流水线打包成功后会将归档路径推送到项目管理平台。

在这里插入图片描述
新增流水线时如果勾选了创建更新任务,也会在流水线打包成功后自动创建更新任务。
在这里插入图片描述
新增流水线时选择运行测试环境,则会通过Argo CD更新测试服务。
在这里插入图片描述
流水线运行异常时,会将相关信息推送到项目管理平台,方便排查问题。
在这里插入图片描述

  1. 流水线的使用
    下面以wizdom-urban-v14代码为例,介绍流水线打包如何使用。

(1)步骤一:Gitlab参数配置。
在这里插入图片描述
tekton_pipeline_enable:是否启用流水线,如true。

tekton_pipeline_name:流水线名称,如“执法-vue前端”。

tekton_pipeline_extra_params:新增流水线页面额外显示的参数,多个参数逗号分隔。可选值:npm_build_params(插件名)。

tekton_pipeline_before_hook:仅用于多app前端仓库,提交记录中src/pages/后面一级目录作为打包参数。如:hook_plugins_by_src_pages、hook_plugins_by_src_views。流水线构建中如果需要使用更多参数,可以配置以“tekton_hook_param_”为前缀的参数名,流水线任务预处理会判断并截取这样的参数。

(2)步骤二:Redmine同步配置管理–项目管理–gitlab同步,同步仓库、分支、变量。代码仓库会在代码提交后自动同步。变量只需要在修改后同步1次即可。

(3)步骤三:新增提测单项目管理平台任务处理完成以后,点击任务右上角“生成提测”功能按钮,从列出的根据提交记录查询的代码仓库和分支列表中,选择需要使用的流水线打包的代码仓库和分支。

在这里插入图片描述
(4)步骤四:新增流水线。以上步骤完成后,就来到了最关键最常用的新增流水线环节,在任务界面点击右上角“新增流水线”功能按钮,填写相关信息。

在这里插入图片描述

后台会根据提测单自动填充部分内容,如有调整,可手动修改。

参数说明如下:

选择流水线:根据提测单代码仓库自动选择流水线类型。

开始打包时发送通知:根据钉钉token给测试人员(成功或失败时)和对应的开发人员发送通知(失败时),一般默认都勾选。

是否生成更新任务:用于生成当前任务的子系统,提供给测试人员发更新使用。面向研发人员是隐藏状态。任务名称和内容自动生成,可以自行编辑。

是否运行测试环境:用于自动更新测试环境,默认不勾选,测试人员需要时勾选,结合“产品线”来判断更新哪一套环境。

测试环境目标版本(不填写时将在后端自动计算):运行测试环境的目标版本。

产品线:勾选运行测试环境后生效,用来判断更新哪一套测试环境。

归档类型:默认zip主代码分支:根据提测单自动生成。

项目代码分支:根据提测单自动生成。

数据库类型:默认为mysql。如果有oracle和dm时自行切换。

插件名:根据提测单自动生成,也可以手动填写,以逗号分隔。

归档的文件和路径(不含插件名对应的jar):主要是前端的文件,多个以逗号分隔。根据提测单自动生成,也可以手动修改。

额外归档的文件或路径:填写其他还需要打包时包含的文件或路径,多个以逗号分隔。

操作人:当前操作人,自动生成。

操作人钉钉token:当前操作人的钉钉token,自动生成,用来发送消息通知。

研发负责人(处理代码异常问题):根据“实际研发处理人”自动生成。为空时不显示此项。在流水线因代码问题打包失败时通知研发负责人。

大部分参数都不需要手动填写,只需要确认无误后点击创建,流水线任务即创建成功,等待流水线自动打包完成即可。打包完成或者因代码问题打包失败会通知操作人。

  1. 流水线任务处理流程
    我们从流水线的任务处理流程、流水线任务和步骤来说明流水线中的关键技术。

4.1任务接收
流水线任务是通过TektonTrigger接收的,Tekton Trigger是Tekton的一个组件,它可以从各种来源的事件中检测并提取需要信息,然后根据这些信息来运行TaskRun和PipelineRun,还可以将提取出来的信息传递给它们以满足不同的运行要求。其核心组件如下:

EventListener:事件监听器,是外部事件的入口 ,通常需要通过HTTP方式暴露,以便于外部事件推送,例如项目管理平台的新建流水线操作。

Trigger:指定当EventListener检测到事件发生时会发生什么,它会定义TriggerBinding、TriggerTemplate以及可选的Interceptor。

TriggerTemplate:用于模板化资源,根据传入的参数实例化Tekton对象资源,比如TaskRun、PipelineRun等。

TriggerBinding:用于捕获事件中的字段并将其存储为参数,然后会将参数传递给TriggerTemplate。

ClusterTriggerBinding:和TriggerBinding相似,用于提取事件字段,不过它是集群级别的对象。

Interceptor:拦截器,在TriggerBinding之前运行,用于负载过滤、验证、转换等处理,只有通过拦截器的数据才会传递给TriggerBinding。

在这里插入图片描述
Tekton Trigger在接收Redmine提交的流水线请求时,使用Interceptor验证请求、解析参数,包含了新增流水线请求RequestBody的值和根据代码仓库id查询的Gitlab代码仓库的CI/CD参数,根据参数值启动对应的PipelineRun,如智信h5打包的build-mobile-h5或build-mobile-h5-npm。

4.2任务执行
PipelineRun通过pipelineRef指定要运行的Pipeline,Pipeline中定义了多个Task,每个Task又包含一个或多个Step。 以wizdom-urban-v14代码的流水线为例,主要Task及其执行顺序如下:

在这里插入图片描述
copy-all-code:复制缓存的代码。

fetch-main-code:拉取主代码。

fetch-project-code:拉取项目定制代码。

profiles-resolve:解决profile定义问题,包括合并主框架代码和项目定制代码、解析要打包的profile、解决依赖定义问题。

maven-run:运行打包。

archive:打包结果归档。

dockerfile:处理war打包结构,生成DockerFile内容

docker-build:构建docker镜像,并将镜像推送到镜像仓库

fetch-argocd-app-code:拉取Argo CD配置文件代码仓库

branch-to-argocd-version:更新部署文件的镜像版本

mis-argocd-app:

push-argocd-app-code:将修改后的代码提交推送到Gitlab仓库。

argocd-task-sync-and-wait:触发Argo CD同步,并等待验证服务启动成功。

dingtalk-app-start-success:通知服务更新成功。

redmine-new-update-task:项目管理平台新建更新更新任务。

delete-files:删除临时文件。

message-dingtalk:构建结果通知钉钉通知。

message-dingtalk-without-task: 构建结果通知钉钉通知。

message-redmine:打包成功的推送redmine。

除了以上流水线打包的任务外,还在finally部分指定了多个最终任务(finally task),无论Tasks部分声明的常规任务执行成功还是报错,最终任务都会在常规任务执行完成后并行执行。

在这里插入图片描述
set-pipeline-run-status:更新项目管理平台任务状态。

notify-admin-onerror:固定错误通知管理员。

notify-pom-group-onerror:mvn打包失败发送给pom修正群。

notify-dev-onerror:mvn打包失败发送给研发通知。

redmine-comment-onerror:带有任务号的流水线推送打包错误内容到任务上。

redmine-comment-on-mvnerror:打包错误内容推送到任务上。

message-op-user-on-npmerror:打包错误内容消息给操作人。

message-op-user:消息通知操作人。

任务的执行顺序是根据runAfter来决定的,未声明runAfter的任务可以和其他任务并行执行。另外,只有when中声明的条件都满足时任务才会执行,否则会跳过。例如redmine-new-update-task任务,需要等待归档任务(archive)完成后才可能执行,并且只有当项目管理平台任务号不为空,且创建流水线任务时勾选了创建更新任务,才会在归档后创建项目管理平台更新任务。


name: redmine-new-update-task
  retries: 1
  taskRef:
    name: redmine
  runAfter:
    - archive
  when:
    - input: "$(params.issue_id)"
      operator: notin
      values: [ "" ]
    - input: "$(params.new_update_issue_flag)"
      operator: in
      values: [ "true" ]

4.3典型任务和步骤
Pipeline中的任务虽然看起来非常多,但是大部分是可复用的。另外,与Pipeline中声明的任务不同,Task中声明的步骤(step)是按照声明的顺序依次执行的。我们以典型的任务profiles-resolve为例来说明,任务步骤执行顺序如下:
在这里插入图片描述
各个步骤完成的内容为:

merge-code:合并主框架代码和项目定制代码。

profiles-resolve:解决profile定义不规范问题。

check-need-mvn:判断是否需要maven构建,后续任务需要使用,例如判断是否运行打包。

add-profiles-by-product:根据产品线追加profiles。

dependencies-fix:修复pom文件中传递依赖定义不完整问题。

war-exclude:排查war打包,只需要更新部分jar时,排斥war打包步骤能够加快打包速度。

fix-git-commit-id-plugin:解决git-commit-id-plugin插件问题。

fix-repository:由于内网maven镜像仓库地址有调整,修改pom中定义的maven镜像源。

fix-pom-commons-collections4:修复部分版本缺少commons-collections4。

profiles-resolve任务的很多额外步骤是为了解决代码代码不规范的问题,例如代码中profile定义不完整,直接执行maven clean package -P pluginName1,pluginName2,…时,往往不能成功。在profiles-resolve步骤中,通过多次循环补充当前profiles依赖的其他profiles。虽然直接修改代码也能解决这个问题,但是由于wizdom-urban-v14代码插件非常多,分支也非常多,改起来会相当耗时。并且由于插件之间依赖关系比较复杂,开发过程中难以维持正确的依赖关系定义。

4.4发布更新
由上文任务列表可知,服务更新其实也是包含在任务执行中的。我们借助Argo CD的自动同步和部署应用程序的优势,在打包完成后,制作docker镜像,并推送到镜像仓库。随后更新Argo CD部署文件代码,触发Argo CD同步,Argo CD检测到部署文件更新后,将自动与K8S交互,更新服务。K8S滚动更新的特性,能够在保证服务不中断的情况下完成升级。

总结起来,流水线的使用流程如下图:
在这里插入图片描述
5. 成果和计划
相比传统的Jenkins打包,流水线的优势在于:

省去了繁琐的构建任务配置,简化了启动流程的步骤。研发和测试只需要在任务平台上新增提测单,新增流水线即可,降低了学习成本。

利用了K8S滚动更新的特性,可以在服务不中断的情况下进行升级。

任务中灵活的脚本处理,能够在不改动代码的情况下,完成依赖修复,镜像仓库地址替换等。

任务中增加了异常处理,能够在打包失败时第一时间通知流水线操作人、研发处理人。并在项目管理平台任务重附上错误日志,便于即使排查解决问题。

流水线完成后自动发布归档文件下载链接,省去测试人员整理结果上传百度云的步骤,提高了工作效率。

自动创建更新任务,测试人员无需手动创建更新任务并粘贴更新文件下载链接。

截止目前,流水线平台已归纳支持12种类型的代码结构打包,主要包含了智云主框架、智云前端、智信前端、微服务、智云拆分代码、智信拆分代码等。项目管理平台接入流水线仅半年就完成了打包任务数3987,流水线任务总运行8140次。通过Argo CD管理一网统管、信息采集、城市大脑、基础平台、市政、执法、星桥、灵珑、社会治理、运管服10条产品线,共67套运行环境。

在这里插入图片描述
后续计划整合其它地区的服务器,全部虚拟化后,将各产品线测试环境全面接入流水线,研发、测试环境隔离互不干扰,做到可按需开启,定时关闭。利用流水线流程的易扩展性,接入单元测试、自动测试流程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/195478.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

只做笔记有必要买apple pencil吗?平价电容笔排行榜

如今国内的电容笔,牌子也越来越多了,苹果原装电容笔虽然性能不错,但价格也非常昂贵,一般人是买不起的。现在市面上有很多可以取代原来的苹果电容笔的平替电容笔。下面,我给大家推荐几款电容笔,好用而且价格…

Java 文件IO操作基础,File,FileInputStream,FileOutputStream

什么是文件 有个时候我们程序中的数据不会直接保存,一旦程序断电,数据将不会存在,如果我们想要我们程序中的数据永久的保存起来,所以,java的文件io显得非常重要。 什么是文件流 创建文件 如下相关的文件io方法 new F…

【教程】Wireshark抓取抖音直播的OBS推流地址和密钥

真不用花钱去买提取推流码的软件。。。自己提取很简单的。 简单记录一下,以备自己需要时候忘了怎么搞。 1、电脑开热点,手机连接热点; 2、电脑安装wireshark软件,并选择WLAN或者以太网接口; 3、wireshark筛选rtmpt&am…

Kubernetes持久化Events到sentry

背景 Kubernetes中的事件最终还是存储在etcd中,默认情况下只保存1个小时,由于etcd并不支持一些复杂的分析操作,默认Kubernetes只提供了非常简单的过滤方式,比如通过Reason、时间、类型等。同时这些事件只是被动的存在etcd中&…

CAPL(vTESTStudio) - DOIP - UDP发送_03

继UDP接收的介绍完成后,今天我们介绍下UDP发送的函数,这里我们将我自主开发的函数整体都会介绍个大家,一般能够完成大家日常脚本开发中90%以上使用发送UDP的数据函数,绝对干货满满。 UDP发送 一、参数定义 无论DoIP发送报文的UDP还是TCP函数,亦或是CAN、CANFDLIN的发送函…

Redux了解及应用(三)

React - redux 使用(由浅入深):https://blog.csdn.net/Jie_1997/article/details/128078971 这篇文章总结的很棒!!!了解redux及应用直接看这篇文章即可 备注:第五节的第三小节,容器…

学习驱动的复杂软件符号执行

原文来自微信公众号“编程语言Lab”:学习驱动的复杂软件符号执行搜索关注“编程语言Lab”公众号(HW-PLLab)获取编程语言更多技术内容!欢迎加入编程语言社区 SIG-编程语言测试,了解更多编程语言测试相关的技术内容。加入…

元宇宙:有人追捧,就会有人抵触

或许,直到现在,我们依然无法否认元宇宙即将对我们的生产和生活产生的深刻影响。即使是在它遭遇巨大的不确定性的大背景下,依然如此。 有人追捧,便有人抵触。元宇宙商用的止步不前,元宇宙技术的难以突破……几乎都是这…

为什么不进行穷举测试?

本章主要介绍不对所有可能性进行测试的原因,对于经理和测试人员,都应该了解测试是一种采样过程,需要了解采样给测试所带来的风险。 1、可进行测试的数目是无限的 如果不能查看代码内部逻辑,可输入的测试用例是无限的。当然还有在不…

第30章 分布式缓存强制删除触发器的触发调试

1 Services.Users.Caching.RoleCacheEventConsumer using Core.Caching; using Core.Domain.Users; using Services.Caching; namespace Services.Users.Caching { /// <summary> /// 摘要&#xff1a; /// 通过该类中的方法成员&#xff0c;在角色实体的1个实例…

Linux —— 文件系统概述、软硬链接与动静态库

目录 1.文件系统概述 1.1磁盘的基本存储结构 1.2磁盘的基本逻辑结构 1.3操作系统中的文件系统 1.4文件系统如何对磁盘进行管理 2.软链接、硬链接 2.1软链接 2.2硬链接 2.3目录的硬链接数 3.静态库和动态库 3.1静态库的制作 3.2静态库的使用 3.3动态库的制作 3.4动态…

年薪50k大佬带你五分钟学会接口自动化测试框架

今天&#xff0c;我们来聊聊接口自动化测试是什么&#xff1f;如何开始&#xff1f;接口自动化测试框架怎么做&#xff1f;自动化测试自动化测试&#xff0c;这几年行业内的热词&#xff0c;也是测试人员进阶的必备技能&#xff0c;更是软件测试未来发展的趋势。特别是在敏捷模…

分布式请求链路跟踪-SpringCloud Sleuth

文章目录1.概述1.1.为什么会出现这个技术&#xff1f; 需要解决哪些问题?1.2.是什么?1.3.如何解决问题?2.搭建链路监控步骤2.1.zipkin2.2.服务提供者2.3.服务消费者&#xff08;调用方&#xff09;2.4.测试1.概述 1.1.为什么会出现这个技术&#xff1f; 需要解决哪些问题?…

力扣刷题记录——1108. IP 地址无效化、1281. 整数的各位积和之差 次数 、1295. 统计位数为偶数的数字、1394. 找出数组中的幸运数

本专栏主要记录力扣的刷题记录&#xff0c;备战蓝桥杯&#xff0c;供复盘和优化算法使用&#xff0c;也希望给大家带来帮助&#xff0c;博主是算法小白&#xff0c;希望各位大佬不要见笑&#xff0c;今天要分享的是——《力扣刷题记录——1108. IP 地址无效化、1281. 整数的各位…

手撕排序算法(一)——插入排序

排序的概念及意义本章内容我们采用C语言完成代码。排序的概念我们先来了解一下基础概念&#xff1a;排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。稳定性&#xff1a;假定在待排序…

cin关闭流同步的利弊与cout的endl使用(超时问题)

重要&#xff1a;1&#xff1a;比如print&#xff0c;scanf&#xff0c;gets()&#xff0c;pus()&#xff0c;getchar()不要与cin&#xff0c;cout共用2&#xff1a;cout中不要使用endl每次使用endl&#xff0c;都要flush缓冲区&#xff0c;造成大量时间耗费。推荐cout <<…

springBoot国际化的一种方式

引言&#xff1a; 当我们的应用面向不同国家用户时&#xff0c;根据不同的locale返回不同的语言信息的国际化功能就显得有必要了。一般来说国际化主要表现在前端用户界面上&#xff0c;在现在前后端分离的背景下&#xff0c;前端页面的国际化交由前端代码独立完成&#xff1b;少…

只用两行代码做个表白二维码,赶快送给你心目中那个她吧♥(๑> ₃ <)♥

上一篇&#xff1a;教你一招完美解决 pptx 库安装失败的问题 今天有同事给我说&#xff1a;女朋友生日快到了&#xff0c;想用Python给她写个表白二维码&#xff0c;然后印在买的衣服上送给她。这么特别的生日礼物&#xff0c;博主还是第一次听到&#xff0c;不得不说&#xff…

Linux-make/Makefile

一、了解make/Makefile对于make/Makefile首先我们需要了解make是一条命令&#xff1b;Makefile是一个文件。make是一个命令&#xff0c;可以执行某条指令。这个我们理解&#xff0c;那Makefile是一个文件&#xff0c;那这个文件是干什么用的呢&#xff1f;这个文件内部一共包含…

SAP中新增销售科目配置分析实例

公司有一批呆滞维修用备件需要卖出&#xff0c;对应在系统内就需要做销售处理。但通常情况下&#xff0c;系统设计时没有考虑和配置备件销信也很正常。所以&#xff0c;处理时可能因为缺少配置做不下去。我需要解决配置问题&#xff0c;并做下可行性的测试。 首先考虑到的是末…