基于docker的Jenkin的服务平台搭建

项目拓扑图

项目环境: jenkins-2.440 sonarqube-9.9.4 apache-maven-3.9.6 gitlab-ce-12.4.2 java17 docker20

harbor.v2.6.0 centos7.9

项目目的: 模拟企业构建一个流行的持续集成和持续部署环境,可以更轻松地创建和管理构建环境,实现自动化构建和部署应用程序的目标,同时基于docker就更灵活

项目步骤: 

一. 安装gitlab服务器,作为代码托管服务器

二. 配置jenkin服务器,作为CICD工具

三. 配置harbor作为镜像仓库,方便镜像的上传与拉取

四. 配置sonarqube实现对代码的审查功能

五. 将jenkins中的pipline文件配置,以及其他配置集合起来

六. 改进,设置jenkins的slave节点,实现分流

1. 安装gitlab,作为代码托管服务器

1.1 安装相关依赖

yum -y install policycoreutils openssh-server openssh-clients postfix

1.2 启动ssh服务&设置为开机启动

systemctl enable sshd && sudo systemctl start sshd

1.3 关闭防火墙,防止通信受阻

systemctl stop firewalld && systemctl disable firewalld

1.4 官方下载gitlab rpm包,并且安装

wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el6/gitlab-ce-12.4.2-ce.0.el6.x
86_64.rpm
rpm -ivh gitlab-ce-12.4.2-ce.0.el6.x86_64.rpm

1.5. 更改gitlab配置文件,监听地址和端口(防止端口冲突)

vi /etc/gitlab/gitlab.rb
external_url 'http://192.168.118.181:82'
nginx['listen_port'] = 82

1.6. 重新加载配置文件,重新启动gitlab,并且查看网页

gitlab-ctl reconfigure
gitlab-ctl restart

1.7 添加组,创建用户,创建项目

添加My-group组,设为私有

在组里面中创建项目

创建用户

创建密码

将plf用户添加到组里面去,设置为owner权限

2. 安装jenkins,作为持续集成工具

2.1 安装jdk17,jenkins需要依赖jdk

wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.rpm
rpm -ivh jdk-17_linux-x64_bin.rpm

安装目录为: /usr/lib/jvm/jdk-17-oracle-x64/bin/java

2.2 下载jenkins,并且安装

wget https://get.jenkins.io/redhat/jenkins-2.452-1.1.noarch.rpm
rpm -ivh jenkins-2.452-1.1.noarch.rpm

2.3 更改jenkins配置文件(将启动用户改为root)

vim /usr/lib/systemd/system/jenkins.serviceUser=root
Group=root

2.4 重新加载配置文件,并且启动

systemctl daemon-reload
systemctl restart jenkins

2.5 登录jenkins网站,进行相关配置

初始配置密码  cat /var/lib/jenkins/secrets/initialAdminPassword

2.6 安装Role 角色管理插件,实现对项目的更细颗粒度管理

2.7 开启全局角色安全配置

2.8 创建相关角色,分配权限

创建rolebase角色,分配全局登录权限

创建项目角色role1,分配匹配到的项目的所有权限

2.9 创建用户,为用户分配相关角色

创建plf用户

将用户分配角色,rolebase和role1,实现登录功能以及对项目的管理

用plf用户进行登录,只可以看到My.用户开头的项目

2.10 安装git插件以及凭证插件,以及git工具

 安装git

yum install -y git

安装git插件以及crendiential

2.11 在gitlab服务器和jenkins设置ssh免密登录,以及凭证设置

[root@jenkins ~]# ssh-keygen -t rsa
[root@jenkins ~]# ssh-copy-id root@192.168.118.181

在gitlab ui界面中也要设置上传 公钥

在jenkins上设置ssh gitlab的凭证,将jenkins私钥添加进去,进行SSH验证

在My_pro项目中进行配置 git服务器 以及 凭证

进行构建,测试是否成功

2.12 安装maven工具

下载maven,并且安装

wget https://dlcdn.apache.org/maven/maven-3/3.9.6/binaries/apache-maven-3.9.6-bin.tar.gz
tar -xvf apache-maven-3.9.6-bin.tar.gz

移动到/opt/maven 目录,并且加入环境变量中

mv apache-maven-3.9.6/* /opt/mavenvim /etc/profile
export MAVEN_HOME=/opt/maven
export PATH=$PATH:$MAVEN_HOME/binsource /etc/profilemvn -v 查看版本

2.13 在jenkins中配置指定maven和jdk的路径

配置环境变量

2.14 设置maven本地仓库,更改aliyun镜像地址

mkdir /root/repo
vi /opt/maven/conf/settings.xml#将repo 仓库改
/root/repo/#添加aliyun私服地址
http://maven.aliyun.com/nexus/content/groups/public/

2.15 Git hook自动触发构建

#轮询SCM性能不佳

开启流水线中的 webhook触发器

默认gitlab不支持,所以gitlab上也要进行配置开启,允许webhook服务

并且还要配置,webhook指向的jenkins项目地址

最后 关闭认证过程,gitlab的

最后测试,认证成功

2.16 构建邮箱触发通知

开启网易发送邮件功能,保存授权密码 VLMQSHORTMDCAKVD

在jenkins配置邮件服务器相关参数

 配置网易邮件凭证

进行测试,邮箱构建成功

设置邮件发送模板

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title>
</head><body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4"offset="0">
<table width="95%" cellpadding="0" cellspacing="0"style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif"><tr><td>(本邮件是程序自动下发的1,请勿回复!)</td></tr><tr><td><h2><font color="#0000FF">构建结果 - ${BUILD_STATUS}</font></h2></td></tr><tr><td><br /><b><font color="#0B610B">构建信息</font></b><hr size="2" width="100%" align="center" /></td></tr><tr><td><ul><li>项目名称&nbsp;:&nbsp;${PROJECT_NAME}</li><li>构建编号&nbsp;:&nbsp;第${BUILD_NUMBER}次构建</li><li>触发原因:&nbsp;${CAUSE}</li><li>构建日志:&nbsp;<a href="${BUILD_URL}console">${BUILD_URL}console</a></li><li>构建&nbsp;&nbsp;Url&nbsp;:&nbsp;<a href="${BUILD_URL}">${BUILD_URL}</a></li><li>工作目录&nbsp;:&nbsp;<a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li><li>项目&nbsp;&nbsp;Url&nbsp;:&nbsp;<a href="${PROJECT_URL}">${PROJECT_URL}</a></li></ul></td></tr><tr><td><b><font color="#0B610B">Changes Since LastSuccessful Build:</font></b><hr size="2" width="100%" align="center" /></td></tr><tr><td><ul><li>历史变更记录 : <a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a></li></ul> ${CHANGES_SINCE_LAST_SUCCESS,reverse=true, format="Changes for Build #%n:<br />%c<br />",showPaths=true,changesFormat="<pre>[%a]<br />%m</pre>",pathFormat="&nbsp;&nbsp;&nbsp;&nbsp;%p"}</td></tr><tr><td><b>Failed Test Results</b><hr size="2" width="100%" align="center" /></td></tr><tr><td><prestyle="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">$FAILED_TESTS</pre><br /></td></tr><tr><td><b><font color="#0B610B">构建日志 (最后 100行):</font></b><hr size="2" width="100%" align="center" /></td></tr><tr><td><textarea cols="80" rows="30" readonly="readonly"style="font-family: Courier New">${BUILD_LOG, maxLines=100}</textarea></td></tr>
</table>
</body>
</html>
3 安装SonarQube实现代码审查

3.1 安装postsql且创建sonar数据库(当前的sonarqube已经不支持,mysql)

sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-6-x86_64/pgdg-redhat-repo-latest.noarch.rpm
sudo yum install -y postgresql15-server
sudo service postgresql-15 initdb
sudo chkconfig postgresql-15 on
sudo service postgresql-15 startsystemctl enable postgresql-15
systemctl start postgresql-15
[root@jenkins conf]# su postgres
bash-4.2$ psql
psql (15.6)
Type "help" for help.postgres=# create database sonar;

3.2 安装sonarqube(java版本为17)

https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-9.9.4.87374.zip

下载完成后上传到linux服务器中

[root@jenkins ~]# unzip sonarqube-9.9.4.87374.zip
[root@jenkins ~]# mv sonarqube-9.9.4.87374/* /opr/sonar

准备环境并且配置相关配置

[root@jenkins opt]# useradd sonar   #创建sonar用户配置用于启动sonar
[root@jenkins opt]# chmod -R sonar:sonar sonar #将文件权限的所属都改为sonar[root@jenkins opt]# vim sonar/conf/sonar.properties
sonar.jdbc.username=postgres   #设置为数据库的账户和密码;默认postsql就会生成postgres和密码
sonar.jdbc.password=postgressonar.jdbc.url=jdbc:postgresql://localhost/sonar 
#设置连接的数据库的地址和数据库

 启动sonar使用sonar用户启动

su sonar /opt/sonar/bin/linux-x86-64/sonar.sh start

启动成功,访问 192.168.118.182:9000 (端口可以在配置文件中更改)https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-9.9.4.87374.zip

3.3 Sonar和Jenkins整合实现代码审查

首先在jenkins中安装sonarqube scanner的插件

在安装sonarscanner的软件

在jenkins中配置sonarqube服务器的环境

获取token并且配置sonarqube凭证 squ_d631e058089b8927f2da702ce55b178bcd4eb149

4. Harbor仓库搭建

4.1 首先先安装Docker并且启动docker

yum install -y epel-release
yum install -y yum-utils
yum-config-manager     --add-repo     https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo
yum install -y docker-ce docker-ce-cli containerd.io
systemctl start docker
cat >>/etc/docker/daemon.json <<EOF
{"registry-mirrors":["https://reg-mirror.qiniu.com"]}
EOF
systemctl daemon-reload
systemctl restart docker

4.2 下载harbor压缩包,并且安装

wget https://github.com/goharbor/harbor/releases/download/v2.10.2/harbor-offline-installer-v2.10.2.tgztar -xvf harbor-offline-installer-v2.10.2.tgz

更改配置文件,设置为本机ip地址

vim /opt/harbor/harbor.yml

4.3 启动harbor 安装文件,下载相关镜像

4.3 进行访问 harbor 

4.4 添加用户,创建项目,分配角色

5 准备测试服务器,并且将jenkins进行联动

5.1 在测试机器上安装docker,初始化环境

5.2 编写dockerfile文件,进行镜像的构建

#FROM java:8
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 9001
ENTRYPOINT ["java","-jar","/app.jar"]

5.3 编写sonar文件,进行审查

# must be unique in a given SonarQube instance
sonar.projectKey=My_pro
# this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1.
sonar.projectName=My_pro
sonar.projectVersion=1.0# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
# This property is optional if sonar.modules is set.
sonar.sources=.
sonar.exclusions=**/test/**,**/target/**
sonar.java.binaries=.sonar.java.source=17
sonar.java.target=17
#sonar.java.libraries=**/target/classes/**# Encoding of the source code. Default is default system encoding
sonar.sourceEncoding=UTF-8

5.3 编写jenkins流水线脚本,实现代码的拉取,审查,编译,打包,上传,部署

//git凭证ID
def git_auth = "5011e58f-4eef-4a0b-abf3-141adc28972b"
//git的url地址
def git_url = "git@192.168.118.181:itheima/tensquare_back.git"
//镜像的版本号
def tag = "latest"
//Harbor的url地址
def harbor_url = "192.168.118.184:85"
//镜像库项目名称
def harbor_project = "tensquare"
//Harbor的登录凭证ID
def harbor_auth = "9b338fcd-6db0-43df-be49-667f8f736299"
node{stage('拉取代码'){checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])}stage("代码审查"){def scannerHome = tool 'sonar-scanner'//引用当前JenkinsSonarQube环境withSonarQubeEnv('sonarqube') {sh """cd ${project_name}${scannerHome}/bin/sonar-scanner"""}}stage('编译,工程,上传镜像'){sh 'mvn -f ${project_name} clean package dockerfile:build'def imageName="${project_name}:${tag}"sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"withCredentials([usernamePassword(credentialsId: '9b338fcd-6db0-43df-be49-667f8f736299', passwordVariable: 'password', usernameVariable: 'username')]) {sh "docker login -u ${username} -p ${password} ${harbor_url}"sh "docker push ${harbor_url}/${harbor_project}/${imageName}"sh "echo 镜像上传成功"}}}

jenkin参数化构建,拉取代码过程,可能有不同的master分支参数,设置参数

编译项目,打标签,并且上传镜像

def imageName="${project_name}:${tag}"sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"

(因为要登录harbor可能会设计到账户和密码,采取harbor的凭证ID)

5.4 在测试机上向harbor仓库拉去镜像,并且部署到机器上

 sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deploy.sh $harbor_url  $harbor_project $project_name $tag $port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])

上传脚本到部署机器上  /opt/jenkins_shell/deploy.sh

#! /bin/sh
#接收外部参数
harbor_url=$1
harbor_project_name=$2
project_name=$3
tag=$4
port=$5imageName=$harbor_url/$harbor_project_name/$project_name:$tagecho "$imageName"#查询容器是否存在,存在则删除
containerId=`docker ps -a | grep -w ${project_name}:${tag}  | awk '{print $1}'`
if [ "$containerId" !=  "" ] ; then#停掉容器docker stop $containerId#删除容器docker rm $containerIdecho "成功删除容器"
fi#查询镜像是否存在,存在则删除
imageId=`docker images | grep -w $project_name  | awk '{print $3}'`if [ "$imageId" !=  "" ] ; then#删除镜像docker rmi -f $imageIdecho "成功删除镜像"
fi# 登录Harbor
docker login -u eric -p Harbor123456 $harbor_url# 下载镜像
docker pull $imageName# 启动容器
docker run -di -p $port:$port $imageNameecho "容器启动成功"

同时要设置ssh免密通道,将jenkins服务器上的公钥发送到测试机上

ssh-copy-id root@192.168.118.184

同时在jenkins中相关ssh配置,实现远程发送shell命令

6 进行代码上传,测试流程是否成功

6.1 将相关的配置放入到项目目录下

6.2 配置gitlab服务器地址

6.3 进行代码的上传

6.4 进行jenkins的构建

6.5 构建成功,进行访问,并且查看相关的日志输出

6.6 代码审查结果查看

6.7 邮件发送通知查看 

6.8 harbor查看相关的镜像是否上传成功

7. 改进,增加jenkins的slave节点

7.1 开启代理程序的TCP端口

7.2 新建节点

7.3 在slave 服务器上启动节点

curl -sO http://192.168.118.182:8888/jnlpJars/agent.jar
java -jar agent.jar -url http://192.168.118.182:8888/ -secret 80ae1fbe59ce71730735814ad979f55d82b7b5da3d088ac759c4cf2837bbe361 -name slave1 -workDir "/root/jenkins"

运行结果,显示成功

7.4 在jenkins中的pipline脚本中指定slave节点,即可指定slave运行

node('slave') {stage('check out') { checkout([$class: 'GitSCM', branches: [[name: '*/master']], 
doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], 
userRemoteConfigs: [[credentialsId: '68f2087f-a034-4d39-a9ff-1f776dd3dfa8', url: 
'git@192.168.66.100:itheima_group/tensquare_back_cluster.git']]])}
}

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

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

相关文章

Week7-LeetCode

2923.找到冠军(简单) 法1&#xff1a; class Solution:def findChampion(self, grid: List[List[int]]) -> int:Winner 0n len(grid)loser [0 for _ in range(n)] for i in range(n):for j in range(n):if grid[i][j] 1 and i ! j:loser[j] 1for index in range(n):i…

Ubuntu 微调训练ChatGLM3大语言模型

Ubuntu 微调训练ChatGLM3大语言模型 LLaMA Factory 的 LoRA 微调提供了 3.7 倍的加速比&#xff0c;同时在广告文案生成任务上取得了更高的 Rouge 分数。结合 4 比特量化技术&#xff0c;LLaMA Factory 的 QLoRA 微调进一步降低了 GPU 显存消耗。 https://github.com/hiyouga…

累加(C语言)

一、题目&#xff1b; 二、N-S流程图&#xff1b; 三、运行结果&#xff1b; 四、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int i 0;int j 0;int n 5;int result 0;int sum 0;//运算&#…

在 AOSP / Android 类原生系统上解决 Wifi 连接警告问题

自 Android 5.0 起&#xff0c;谷歌引入了Captive Portal的机制&#xff0c;用于检测 WiFi网络认证是否正常。由于众所周知的原因&#xff0c;我们在中国大陆并无法访问谷歌的网络&#xff0c;这在某些情况下会导致一些问题&#xff0c;例如&#xff1a;在中国大陆使用一些类原…

数据挖掘与数据分析

目录 数据挖掘与数据分析 一&#xff0e;数据的本质 二&#xff0e;什么是数据挖掘和数据分析 三&#xff0e;数据挖掘和数据分析有什么区别 案例及应用 1. 基于分类模型的案例 2. 基于预测模型的案例 3. 基于关联分析的案例 4. 基于聚类分析的案例 5. 基于异常值分析…

牛客-小乐乐与欧几里得

目录 题目 描述 输入描述&#xff1a; 输出描述&#xff1a; 示例1 示例2 解题 题目 描述 小乐乐最近在课上学习了如何求两个正整数的最大公约数与最小公倍数&#xff0c;但是他竟然不会求两个正整数的最大公约数与最小公倍数之和&#xff0c;请你帮助他解决这个问题。 …

进程控制第二弹(进程程序替换)

文章目录 代码现象基本原理多进程版本实例基本原理 使用所有的替换方法&#xff0c;并且认识函数的参数含义execlexecvexeclp、execvpexecvpe 总结 代码现象 #include<stdio.h> #include<unistd.h> int main() { printf("testexec begin! ...\…

数据安全全面防护

what 通过采用各种有效技术和管理措施来保护网络系统的正常运行&#xff0c;从而保证数据的可用性&#xff0c;机密性&#xff0c;完整性。 ---网络安全防护体系建设三同步--规划 建设 运行 数据安全的三大基本特征 可用性 数据在需要时可用且可访问&#xff0c;为实现可用…

学习JavaEE的日子 Day39 注解,反射

Day39 注解 1.什么是注解 理解&#xff1a;给程序员和程序解释代码信息 2.注解与注释的区别 注释&#xff1a;对程序员解释代码信息 注解&#xff1a;对程序和程序员解释代码信息 3.注解的所用 可以作用于包、类、方法、属性上&#xff0c;给他们添加额外的信息&#xff0c;可…

Fastadmin解决异步高并发大并发阻塞超时问题

官方连接​​​​​​https://guzzle-cn.readthedocs.io/zh_CN/latest/quickstart.html?highlightgetasync 使用guzzle 实现&#xff0c;需要先引用。安装请自行解决。 use GuzzleHttp\Client; use GuzzleHttp\Promise; /*** 异步高并发请求*/public function asyncRequests…

Android自定义类-写字板

目录 1. 属性文件 res/values/attrs.xml 2. 自定义控件类文件 MyClipbroad.class 3. XML布局文件中的使用 4. Java文件中的使用 该写字板可设置画笔颜色、画笔宽度、画布背景&#xff0c;具有导出图像、清空画布功能&#xff0c;可与OnTouchListener配合达到触摸绘画的效果…

速盾:cdn都能防御哪些攻击?

CDN&#xff08;Content Delivery Network&#xff09;是一种分布式的服务器网络&#xff0c;通过将资源缓存到多个服务器节点上&#xff0c;在用户请求资源时将其分发至最近的服务器节点&#xff0c;提供快速响应和高可用性。除了提供高速内容传输和优化用户体验之外&#xff…

算法课程笔记——STL键值对map

map当下标无限的数组 重点是对应关系&#xff0c;一般不修改compare 类比set 没有lowerbound&#xff0c;因为遍历是无序的 ; map不能用sort函数排序 但可用vector转化为map使用 std::set<std::pair<TKEY, mutable TVAL> > ≈ std::map<TKEY, TVAL>

使用 Cucumber框架进行BDD测试的一些项目

BehatMage 项目地址: https://github.com/MageTest/BehatMage 不过该项目在GitHub中有超过10年没有更新了。 项目介绍&#xff1a; BehatMage项目介绍 BehatMage是一个基于Behat的Magento测试框架&#xff0c;用于自动化测试Magento电子商务平台的功能和性能。Behat是一个行…

什么是认知负荷?

认知负荷&#xff08;Cognitive Load&#xff09;是心理学中的一个概念&#xff0c;它描述了一个人在特定时间内处理信息和进行思考所需耗费的认知资源的量。这个概念是由教育心理学家John Sweller在1988年提出的&#xff0c;主要用于描述学习过程中的认知需求。 认知负荷通常…

【剪映专业版】13快速为视频配好音:清晰、无噪声、对齐

视频课程&#xff1a;B站有知公开课【剪映电脑版教程】 使用场景&#xff1a;视频无声音或者视频有声音但是需要更改声音 时间指示器在哪里&#xff0c;就从哪里开始 红色按钮&#xff1a;开始录音 声音波纹&#xff1a;蓝色最佳&#xff0c;黄色或红色声音太大&#xff0c;…

23种设计模式之创建型模式篇

一、创建型模式 这类模式主要关注对象的创建过程。它们试图在创建对象的同时&#xff0c;将对象的创建和使用分离&#xff0c;以达到更高的灵活性和可扩展性. 包括: 工厂方法模式&#xff08;Factory Method&#xff09;抽象工厂模式&#xff08;Abstract Factory&#xff0…

C# 反射基础

1 在.NET中程序集是什么&#xff1f; 程序集&#xff08;Assembly&#xff09;以可执行文件(.exe)或动态链接库文件(.dll)的形式存在&#xff0c;是.NET应用程序构建的基本单元。程序集可用于部署、版本控制和设置安全权限等。 2.程序集的有哪些部分组成&#xff1f; 程序集…

Unity UGUI透明区域点击无效

是这样的&#xff0c;我有一张图&#xff0c;客户给的是1920*1080&#xff0c;但只有中间部分是按钮&#xff0c;是有效像素。为了让空白区域点击无效。需要设置如下 并且加上下面这句 this.GetComponent<Image>().alphaHitTestMinimumThreshold 0.1f;

tomcat中Pipeline-Valve解析

tomcat中用到Pipeline-Value有二种方式&#xff0c;一种是管道/阀门&#xff0c;另一种是过滤器链/过滤器。 管道/阀门过滤器链/过滤器管道&#xff08;Pipeline&#xff09;过滤器链&#xff08;FilterChain&#xff09;阀门&#xff08;Valve&#xff09;过滤器&#xff08;…