当前位置: 首页 > news >正文

GitLABJenkins

GitLAB & Jenkins

image-20230423061727812

目录

image-20230425201437649

实践:基于Jenkins提交流水线(测试成功)-2023.4.25

目的:掌握通过触发器将GitLab和Jenkins集成,实现提交流水线。

image-20220514100956964

image-20220512070753368

1、触发Jenkins构建

安装Generic Webhook Trigger插件

tstmp_20230423061901

重启后,进入一个Pipeline项目设置,已经可以选择这个触发器了…

tstmp_20230423061918

插件文档:https://plugins.jenkins.io/generic-webhook-trigger/

tstmp_20230423061936

Jenkins作业配置触发器

启动Generic Webhook触发器后, 相当于给Jenkins加了一个新的接口(http://JENKINS_URL/generic-webhook-trigger/invoke)。

tstmp_20230423064219

image-20230423064513170

调用的时候:这里要把 JENKINS_URL 换成自己真实的Jenkins 服务器地址,有端口就加上端口,是域名就写域名。下面是一个参考的URL:

http://192.168.1.200:8080/generic-webhook-trigger/invoke

Post content parameters: 获取调用接口传进来的数据

JsonPath语法文档: https://github.com/json-path/JsonPath

tstmp_20230423064424

Header parameters: 获取Header中的参数

tstmp_20230423064526

tstmp_20230423064534

Request parameters: 获取URL中的请求参数

curl http://192.168.1.200:8080/generic-webhook-trigger/invoke?runopts=gitlab

tstmp_20230423064602

Token: 给URL添加一个触发的认证

curl http://192.168.1.200:8080/generic-webhook-trigger/invoke?token=devops-service

tstmp_20230423064625

打印调试信息到日志中

tstmp_20230423064647

触发条件过滤:仅满足条件才能触发此作业

tstmp_20230423064709

创建测试项目

  • 创建一个叫做devops-demo-service的jenkins作业(这里的作业名称和gitlab里的项目名称推荐保持一致)

image-20230423062615216

  • 要加一个唯一的token,不然会触发所有token一样的项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2ZFLY8ZF-1682425393155)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230423062932520.png)]

  • 把这2个选项勾选上

image-20230423063138153

  • 此时在postman里测试触发

触发url http://172.29.9.101:8080/generic-webhook-trigger/invoke?token=devops-demo-service

image-20230423063612364

这里记得要加一个basic auth

image-20230423063634952

image-20230423063813220

image-20230423063828507

可以看到触发成功了。

  • 演示将postman中的请求转换curl方式。

image-20230423063911558

curl --location --request POST 'http://172.29.9.101:8080/generic-webhook-trigger/invoke?token=devops-demo-service' \
--header 'Authorization: Basic YWRtaW46YWRtaW4='

image-20230423064006576

image-20230423064023234

可以看到,也是能构建成功的。

解析GET/POST请求数据

传参注意,第一个参数使用?号连接, 后面的参数使用&符号连接。

?token=demo-pipeline-service&user=jenkins&a=1&b=2

解析GET数据

  • 客户端发送Get请求, 带有两个参数 versionusername
http://172.29.9.101:8080/generic-webhook-trigger/invoke?token=devops-demo-service&version=1.1.1&username=jenkins

image-20230423065438782

  • Jenkins 配置Generic hook,获取请求参数versionusername参数名称要一致

tstmp_20230423065144

  • 验证测试(Jenkins日志中能够打印出获取的值,则正常

image-20230423065442246

image-20230423065453824

哎,这里怎么没显示一些变量呢??

image-20230423065529929

这里简单写一个pipeline把。

image-20230423065824723

image-20230423065804019

可以看到效果了。

  • 通过jenkinsfile读取传递的参数,再次触发
currentBuild.displayName = "${version}"println("${version}")
println("${username}")pipeline {agent anystages {stage('Hello') {steps {echo 'Hello World'}}}
}

再次postman触发,观察效果:(符合预期)

image-20230423070111659

image-20230423070131842

解析HEADER参数数据

  • 客户端发送请求(什么请求都可以,这里的header与请求类型无关), 带有两个参数 devops和 tool-name。

image-20230423073947672

  • Jenkins 配置Generic hook,获取请求参数devops和 tool-name 。

image-20230423073742460

  • 通过jenkinsfile读取传递的参数

注意,这里的pipeline代码如果打印tool-name变量的话,会报错的

image-20230423074147969

image-20230423074130589

这里要使用下划线来替换横杠:

image-20230423074348398

image-20230423074251891

再次触发,就正常了,符合预期。

image-20230423074331148

解析POST数据

  • 客户端发送POST请求, 参数存储在body体中(参考POSTMAN中的样例

image-20230423075425757

  • Jenkins 配置触发器来获取Post参数。

删除之前测试的header参数,request参数。

$代表/,获取所有数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nYZuhkun-1682425393160)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230423075557421.png)]

获取name字段

image-20230423075615899

  • Jenkinsfile中使用参数

image-20230423075714076

触发:

image-20230423075743209

验证:

image-20230423075810592

image-20230423075832618

扩展流水线解析JSON数据

  • 安装插件: Pipeline Utility Steps

image-20230423121825709

  • readJSON: 处理json数据
currentBuild.displayName = "${name}"println("${Data}")NewData = readJSON text: "${Data}"
envName = NewData["envName"]
appsName = NewData["apps"]["name"]pipeline {agent anystages {stage('Hello') {steps {script {println("${envName}")println("${appsName}")}}}}
}

再次构建:

验证:(符合预期)

image-20230423123103473

image-20230423122848208

Rebuilder插件使用

可以直接携带原触发参数进行触发,不用重复触发(不用在重复的提交代码了)

tstmp_20230423071021

进入某一次构建后,可以点击rebuild。

tstmp_20230423071045

2、获取触发参数

1.触发器配置

Jenkins开启trigger

目的: 开启trigger后,就可以实现其他系统通过一个指定的URL进行自动触发构建了;

新建一个文件夹存放对应GitLab仓库组中的流水线。这里建议用仓库组的名称作为文件夹的名称devops03;

用Gitlab项目名称与流水线命名; devops03-demo-service项目;

tstmp_20230423210432

tstmp_20230423210444

  • 开启Generic webhook;
  • 配置触发Token,例如:作业名称devops03-demo-service (这个token是流水线触发需要传递的);
  • 生成的触发URL;

tstmp_20230423210537

http://192.168.1.200:8080/generic-webhook-trigger/invoke?token=devops03-demo-service

(此时,已经生成了触发URL,接着可以使用Curl或者Postman进行触发测试了!)

自己本次的这部分配置已经配置完成了。

  • 这里还原下,删除之前的变量,这里只保留Data。

image-20230423205253027

  • 修改下pipeline代码

image-20230423210735163

println("${Data}")NewData = readJSON text: "${Data}"
// envName = NewData["envName"]
// appsName = NewData["apps"]["name"]
println("${NewData}")pipeline {agent anystages {stage('Hello') {steps {script {println("${NewData}")}}}}
}

配置GitLab WebHook

进入GitLab项目设置, 进入 webhook配置页面;

  • 配置要触发的URL,即Jenkins触发器接口URL;

  • 选择发生哪种GitLab事件后触发此Webhook;例如:Push提交代码、Tag创建标签等等;

  • 在gitlab的项目里配置好webhook

http://172.29.9.101:8080/generic-webhook-trigger/invoke?token=devops-demo-service

image-20230423205606399

image-20230423205641544

事件:

  • Push 提交事件

  • Tag Push 创建事件

  • MergeRequest 合并事件

  • Issue 问题创建更新事件

  • 测试模拟触发

模拟事件触发,点击test按钮选择push事件,此时去看下Jenkins是否成功被触发。

这里稍微测试下:

点击Test

image-20230423205744825

触发成功则提示: Hook executed successfully: HTTP 200, 此时可以看下Jenkins是否已经触发了一次构建;

image-20230423205757026

image-20230423211029028

Webhook问题排查调试

进入webhook添加页面的最下方,点击你所创建的webhook的 Edit按钮 ;

image-20230423211150162

webhook历史记录: 此记录可以判断,当前动作提交是否产生了webhook。

image-20230423211127448

点击 View details 可以看到此webhook发送给对端Jenkins的数据信息,和请求状态。

  • 200: 表示触发Jenkins请求成功;
  • Resend Request: 重新发送请求;(此处便于排查调试错误)
  • RequestBody: GitLab传递给Jenkins的数据信息;

image-20230423211316059

假如请求由于xxx原因导致没有触发jenkins构建, 可以在这里点击 Resend Request 按钮进行重新发送请求,而不是再次提交代码。

image-20230423211351860

如果Jenkins触发成功了之后,我们可以在Jenkins的构建日志中查看效果。 这些数据就是gitlab post传递过来的。

image-20230423211409172

到此:你基本上已经知道了Gitlab如何触发Jenkins的了。(多看几遍,多练习几遍)

2.提交流水线优化

过滤新建分支和tag的触发

你可能发现问题了,新建一个分支或者标签也会出现构建,这个构建是没有意义的。我们需要排除掉。没错,jenkins 的 Generic webHook 也是支持的。

参考官方的说明:https://github.com/jenkinsci/generic-webhook-trigger-plugin/blob/master/src/test/resources/org/jenkinsci/plugins/gwt/bdd/gitlab/gitlab-push-ignore-create-remove-branch.feature

tstmp_20230424064510

添加三个变量,获取当前的提交信息 $object_kind $before $after

此步骤一定要注意下参数名和值后面的空格,要去掉

tstmp_20230424064538

通过正则表达式配置触发条件:Expression ^push\s(?!0{40}).{40}\s(?!0{40}).{40}$ Text $object_kind $before $after。 push请求只有after和before的值都不是40个0的时候触发构建(为40个0的情况是删除分支或者新建分支)

tstmp_20230424064614

本次测试过程:

  • 我们在gitlab上新创建一个分支

image-20230424064755074

可以看到,gitlab上新创建一个分支后,就会触发jenkins流水线,这不是我们所期望的,因此下面将进一步优化。

image-20230424064821698

  • 在jenlins侧如何过滤出一些构建:

before如果是40个0的话,那么可能是创建分支;

after如果是40个0的话,那么可能是合并分支;

image-20230424065115566

image-20230424065148774

  • 这里先编辑jenkins上流水线的触发过滤条件

tstmp_20230424065530

通过正则表达式配置触发条件:Expression ^push\s(?!0{40}).{40}\s(?!0{40}).{40}$ Text $object_kind $before $after。 push请求只有after和before的值都不是40个0的时候触发构建(为40个0的情况是删除分支或者新建分支)

\s是空格

tstmp_20230424065601

配置完成后,保存。

gitlab上再新建分支,观察是否会触发jenkins?

image-20230424065732263

可以看到gitlab上已经成功触发了,但是被jenkins过滤掉了,符合预期。😘

image-20230424065748614

image-20230424065812170

如何支持多个分支触发构建?

方法1:创建多个gitlab webhook, 设置不同的分支,最终指向同一个jenkins 作业;

tstmp_20230424070102

方法2:过滤

gitlab上设置,只允许feature开头的分支才可以进行触发:

image-20220512161043337

编辑gitlab上的webhook配置:

image-20220512161217000

3、自动触发Pipeline

  • 这里写下代码

获取项目地址:

image-20230423214458124

image-20230423214451643

获取分支名:

image-20230423214649532

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zds29h2j-1682425393170)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230423214640427.png)]

下载代码:

利用片段生成器生成代码:

image-20230424061051864

创建gitlab-root凭据:

image-20230424060852593

image-20230424061127147

生成代码:

checkout([$class: 'GitSCM', branches: [[name: 'main']], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab-root', url: 'srcUrl']]])

继续编写代码:

println("${Data}")NewData = readJSON text: "${Data}"
// envName = NewData["envName"]
// appsName = NewData["apps"]["name"]
println("${NewData}")// Get git repo url 项目地址
srcUrl = NewData["project"]["git_http_url"]// Get git repo branch
branchName = NewData["ref"] - "refs/heads/"// current build desc
currentBuild.displayName = "${branchName}"
currentBuild.description = "src: ${srcUrl}"pipeline {agent anystages {stage('CheckOut') {steps {script {println("Checkout: ${srcUrl} ${branchName}")checkout([$class: 'GitSCM', branches: [[name: "${branchName}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab-root', url: "${srcUrl}"]]])sh 'ls -l'}}}}
}

image-20230424062941803

将写好的代码保存到jekins里。

  • 在gitlab任意分支做个提交:

我们先拉取下代码:

image-20230424062044964

feature-dev-01编辑README.md文件并推送。

Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-dev-01)
$ cat README.md
情出自愿-事过无悔Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-dev-01)
$ echo>> README.mdWin@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-dev-01)
$ git add .
warning: in the working copy of 'README.md', LF will be replaced by CRLF the next time Git touches itWin@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-dev-01)
$ git commit -m "佳"
[feature-dev-01 683b378]1 file changed, 1 insertion(+)Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-dev-01)
$ git push origin feature-dev-01
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 287 bytes | 287.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote:
remote: To create a merge request for feature-dev-01, visit:
remote:   http://172.29.9.101:8076/devops6/devops-demo-service/-/merge_requests/new?merge_request%5Bsource_branch%5D=feature-dev-01
remote:
To http://172.29.9.101:8076/devops6/devops-demo-service.git7cf5639..683b378  feature-dev-01 -> feature-dev-01Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-dev-01)
$
  • 此时可以看到jenkins里的流水线被触发了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aqRmpjvu-1682425393171)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424063019832.png)]

image-20230424063039348

  • 这里再在新建一个分支,用于测试,看是否会触发jebnkins流水线
Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-dev-01)
$ git checkout -b feature-003
Switched to a new branch 'feature-003'Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-003)
$ ls
HELP.md  README.md  mvnw*  mvnw.cmd  pom.xml  src/Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-003)
$ echo "i am very hurt" > README.mdWin@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-003)
$ git add .
warning: in the working copy of 'README.md', LF will be replaced by CRLF the next time Git touches itWin@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-003)
$ git commit -m "hurt"
[feature-003 1de466b] hurt1 file changed, 1 insertion(+), 2 deletions(-)Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-003)
$ git push origin feature-003
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 262 bytes | 262.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote:
remote: To create a merge request for feature-003, visit:
remote:   http://172.29.9.101:8076/devops6/devops-demo-service/-/merge_requests/new?merge_request%5Bsource_branch%5D=feature-003
remote:
To http://172.29.9.101:8076/devops6/devops-demo-service.git* [new branch]      feature-003 -> feature-003Win@DESKTOP-VUMV922 MINGW64 ~/Desktop/demo (feature-003)
$

可以看到,jenkins流水线被触发了。

image-20230424063343728

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uKeDH3jU-1682425393172)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424063427563.png)]

🍀 之前代码

tstmp_20230424073517

webhookData = readJSON text: "${webhook_data}"//分支名称
env.branchName = webhookData["ref"] - "refs/heads/"
env.projectUrl = webhookData["project"]["git_http_url"]
env.userEmail = webhookData["user_email"]//修改描述信息
currentBuild.description = "BranchName: ${env.branchName}"
currentBuild.displayName = "${env.branchName}"pipeline {agent { label "build01"}stages {stage('Checkout') {steps {script{//checkout checkout([$class: 'GitSCM', branches: [[name: "${env.branchName}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'd7e4e500-e5c6-4673-ae4b-d43bf4ff5d19', url: "${env.projectUrl}"]]])}}}stage('Build'){steps{script{sh "mvn clean package -DskipTests"}}}stage('test'){steps{script{sh "mvn test"}}}}post {always{script{EmailUser("${env.userEmail}",currentBuild.currentResult)}}}
}def EmailUser(userEmail,status){emailext body: """<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0"> <img src="http://192.168.1.200:8080/static/0eef74bf/images/headshot.png"><table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">   <tr> <td><br /> <b><font color="#0B610B">构建信息</font></b> </td> </tr> <tr> <td> <ul> <li>项目名称:${JOB_NAME}</li>         <li>构建编号:${BUILD_ID}</li> <li>构建状态: ${status} </li>                         <li>项目地址:<a href="${BUILD_URL}">${BUILD_URL}</a></li>    <li>构建日志:<a href="${BUILD_URL}console">${BUILD_URL}console</a></li> </ul> </td> </tr> <tr>  </table> </body> </html>  """,subject: "Jenkins-${JOB_NAME}项目构建信息 ",to: userEmail}
  • 进一步更新代码

此时,想要commitId的前8位该如何取呢?

这样处理就好:

image-20230425154819839

println("${Data}")NewData = readJSON text: "${Data}"
// envName = NewData["envName"]
// appsName = NewData["apps"]["name"]
println("${NewData}")// Get git repo url 项目地址
srcUrl = NewData["project"]["git_http_url"]// Get git repo branch
branchName = NewData["ref"] - "refs/heads/"// Get short commit id 想要commitId的前8位
env.commitId = NewData["checkout_sha"][0..7]// current build desc
currentBuild.displayName = "${branchName}:${env.commitId}"
currentBuild.description = "src: ${srcUrl}"pipeline {agent anystages {stage('CheckOut') {steps {script {println("Checkout: ${srcUrl} ${branchName}")checkout([$class: 'GitSCM', branches: [[name: "${branchName}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab-root', url: "${srcUrl}"]]])sh 'ls -l'}}}}
}

触发测试:(符合预期)

image-20230425154646725

4、手动触发流水线

很简单的,就是在jenkins项目里添加一些选项参数,把这些变量写死在选项参数里就好。

自动触发和手动触发的可以并存的,例如写一些If ……else,但是不推荐。

手动触发:例如有一些版本分支,这些分支名是会变的,因此不是很方便;但是如果不想每次提交都触发流水线,而是等到一个小版本后再触发,这个用手动触发也是可以的哦。

tstmp_20230424073934


//修改描述信息
currentBuild.description = "BranchName: ${env.branchName}"
currentBuild.displayName = "${env.branchName}"pipeline {agent { label "build01"}stages {stage('Checkout') {steps {script{//checkout checkout([$class: 'GitSCM', branches: [[name: "${env.branchName}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'd7e4e500-e5c6-4673-ae4b-d43bf4ff5d19', url: "${env.projectUrl}"]]])}}}stage('Build'){steps{script{sh "mvn clean package -DskipTests"}}}stage('test'){steps{script{sh "mvn test"}}}}
}

这里做下测试:

  • jenkins上创建项目gitlab-jenkins-service-manual,配置好选项参数。

image-20230425065842085

image-20230425065859778

  • 编写pipeline代码
//修改描述信息
currentBuild.description = "BranchName: ${env.branchName}"
currentBuild.displayName = "${env.branchName}"pipeline {agent { label "build01"}stages {stage('CheckOut') {steps {script {println("Checkout: ${projectUrl} ${branchName}")checkout([$class: 'GitSCM', branches: [[name: "${branchName}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab-root', url: "${projectUrl}"]]])sh 'ls -l'}}}        stage('Build'){steps{script{println("mvn clean package -DskipTests") }}}stage('test'){steps{script{println("mvn test")}}}}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZWq1xNg3-1682425393173)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230425065947246.png)]

  • 准备好一个gitlab项目就好。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0jdHoDId-1682425393173)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230425070037754.png)]

  • 测试(符合预期)

image-20230425070134247

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4dfgOONl-1682425393173)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230425065814820.png)]

5、Jenkins消息通知

添加邮箱

邮箱是标配吧。(钉钉机器人也是可以的)

  • 默认情况可能每个Gitlab用户没有配置邮箱的, 需要Gitlab用户要配置好邮箱。

image-20230424123744541

  • 点击头像进入 edit profile

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oU6PqOcc-1682425393174)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/tstmp_20230424123355.png)]

添加自己邮箱:

image-20230424123532445

这里需要登录到自己的邮箱去确认下:

方法1:或者按如下方式直接配置好自己的gitlab邮箱为qq邮箱:(强制更改本次是强制更改的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j1VidOF8-1682425393174)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424204730808.png)]

点击Edit

image-20230424204803668

这里配置好自己的邮箱,点击保存:

image-20230424204854790

可以看到这里的邮箱被确认了:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CTNLrvSR-1682425393175)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424205009192.png)]

方法2:在自己的邮箱里确认。

  • 奇怪,我这里怎么163、qq邮箱都收不到确认邮件呢??😥

image-20220512222617386

  • 经过百度,发现是在gitlab里的配置文件要做下配置的:
[root@devops ~]#docker ps
CONTAINER ID   IMAGE                                  COMMAND                  CREATED       STATUS                  PORTS                                                                                      NAMES
11a54a1f4a2a   gitlab/gitlab-ce:14.9.3-ce.0           "/assets/wrapper"        6 days ago    Up 28 hours (healthy)   0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:2222->22/tcp                             devops_tutorial_gitlab
f3f039aa667a   jenkins/jenkins:2.332.2-centos7-jdk8   "/sbin/tini -- /usr/…"   4 weeks ago   Up 24 hours             0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:50000->50000/tcp, :::50000->50000/tcp   jenkins
[root@devops ~]#docker exec -it devops_tutorial_gitlab bash
root@11a54a1f4a2a:/# vi /etc/gitlab/gitlab.rb
#搜索smtp
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.163.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "onexlforyou@163.com"
gitlab_rails['smtp_password'] = "NVSMOUfffAxxxccEMXAB"
gitlab_rails['smtp_domain'] = "163.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = true
gitlab_rails['gitlab_email_from'] = 'onexlforyou@163.com'root@11a54a1f4a2a:/# gitlab-ctl reconfigure

image-20220512230631903

image-20220512232120119

image-20220512231434198

  • 此时,发下就可以正常识别到自己的邮箱了:

image-20220512231704671

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SZ6LEB58-1682425393176)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20220512231531784.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QZxrlTV3-1682425393176)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20220512231618636.png)]

  • 参考链接:

http://t.zoukankan.com/zgz345-p-9122146.html

image-20220512232258888

  • 在这个页面配置好邮箱地址,最好这几个email都配置上吧…最后img

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yTiQhTTT-1682425393177)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424205222529.png)]

  • 这里在gitlab上提交一次代码,确认post请求里的数据体是否含user_email信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G0nCvZFA-1682425393177)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424205446256.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-31XOyYPn-1682425393177)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424205511731.png)]

image-20230424205529691

可以看到,这里的user_email数据是有了。

安装Email Extension插件

  • Jenkins需要配置邮件通知,安装插件Email Extension安装后重启Jenkins。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ItnszpQZ-1682425393178)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/tstmp_20230424205619.png)]

  • 然后进入系统管理-> 系统设置 , 先配置下全局的admin的邮箱地址。(最后配置下不然可能会出错的)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pm9S1M6c-1682425393178)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424205904038.png)]

拿到邮箱授权码

  • 登入邮箱拿到授权码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hj46fHWs-1682425393178)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/tstmp_20230424210549.png)]

zpnchpffffgggvnfgfeqwggzhgecef

发送短信之后获取授权码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uMNFQ6Ov-1682425393178)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/tstmp_20230424210610.png)]

配置Email Extension

  • ->Extended E-email Notification。设置邮件系统配置信息。

这里我使用的是QQ邮箱,填写SMTP服务器地址smtp.qq.com 和端口 465注意要开启SSL,密码为授权码。

这里写下自己的qq的授权码凭证:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yq5sxTb9-1682425393179)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424211243147.png)]

  • 换个选项注意下: 不选择 HTML 就是普通的文本, HTML 可以支持html网页,更加美观。这里选择 HTML

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5hAAXK4j-1682425393179)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424211401396.png)]

编写代码

  • pipeline as code , 进入片段生成器,生成邮件通知代码。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AmNU2xzm-1682425393179)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/tstmp_20230424211508.png)]

emailext body: 'hello world!....jenkins', subject: 'test.....', to: '2560350642@qq.com'

然后我们将此段代码加入到Jenkins pipeline 中运行, 可以看到效果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-88VOg56c-1682425393179)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/tstmp_20230424211545.png)]

  • jenkins as code 将email 写成一个函数。这个通知信息是一个html格式的。

def EmailUser(userEmail,status){emailext body: """<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0"> <img src="http://192.168.1.200:8080/static/0eef74bf/images/headshot.png"><table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">   <tr> <td><br /> <b><font color="#0B610B">构建信息</font></b> </td> </tr> <tr> <td> <ul> <li>项目名称:${JOB_NAME}</li>         <li>构建编号:${BUILD_ID}</li> <li>构建状态: ${status} </li>                         <li>项目地址:<a href="${BUILD_URL}">${BUILD_URL}</a></li>    <li>构建日志:<a href="${BUILD_URL}console">${BUILD_URL}console</a></li> </ul> </td> </tr> <tr>  </table> </body> </html>  """,subject: "Jenkins-${JOB_NAME}项目构建信息 ",to: userEmail}
  • 这里继续编写下代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uyXhJU4i-1682425393179)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424212344209.png)]

println("${Data}")NewData = readJSON text: "${Data}"
// envName = NewData["envName"]
// appsName = NewData["apps"]["name"]
println("${NewData}")// Get git repo url 项目地址
srcUrl = NewData["project"]["git_http_url"]// Get git repo branch
branchName = NewData["ref"] - "refs/heads/"// Get git user email
userEmail = NewData["user_email"]// current build desc
currentBuild.displayName = "${branchName}"
currentBuild.description = "src: ${srcUrl}"pipeline {agent anystages {stage('CheckOut') {steps {script {println("Checkout: ${srcUrl} ${branchName}")checkout([$class: 'GitSCM', branches: [[name: "${branchName}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab-root', url: "${srcUrl}"]]])sh 'ls -l'}}}}post {always{script{EmailUser(userEmail,"${currentBuild.currentResult}")}}}}def EmailUser(userEmail,status){emailext body: """<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0"> <img src="http://192.168.1.200:8080/static/0eef74bf/images/headshot.png"><table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">   <tr> <td><br /> <b><font color="#0B610B">构建信息</font></b> </td> </tr> <tr> <td> <ul> <li>项目名称:${JOB_NAME}</li>         <li>构建编号:${BUILD_ID}</li> <li>构建状态: ${status} </li>                         <li>项目地址:<a href="${BUILD_URL}">${BUILD_URL}</a></li>    <li>构建日志:<a href="${BUILD_URL}console">${BUILD_URL}console</a></li> </ul> </td> </tr> <tr>  </table> </body> </html>  """,subject: "Jenkins-${JOB_NAME}项目构建信息 ",to: userEmail}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zMluC30w-1682425393180)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424220307725.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EdJCbw0P-1682425393180)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424220258311.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y1cjr9Vu-1682425393180)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424220237905.png)]

触发测试

  • 提交下代码,触发下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Me3WP333-1682425393180)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424212630637.png)]

  • 自己的测试现象(符合预期)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aoccgQGI-1682425393180)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424214039852.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fM9J30cm-1682425393180)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424214104233.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kE3BBZoj-1682425393181)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424214122673.png)]

解决默认图片显示异常问题

  • 可以看到这里的人图片显示异常,这里我们使用oss路径来存储图片就可以了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rLK47nvC-1682425393181)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230424220342128.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZwsrlHfV-1682425393181)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230425161711144.png)]

本次最新代码(测试成功)

//打印jenkins的Generic Webhook Trigger接收到的数据,默认为字符串
println("${Data}")//格式化webhook接收的数据为json格式
NewData = readJSON text: "${Data}" //$表示全量数据
// envName = NewData["envName"]
// appsName = NewData["apps"]["name"]
println("${NewData}")// Get git repo url 项目地址
srcUrl = NewData["project"]["git_http_url"]// Get git repo branch 提交分支
branchName = NewData["ref"] - "refs/heads/"// Get git user email 
userEmail = NewData["user_email"]// Get short commit id 想要commitId的前8位 commit ID
env.commitId = NewData["checkout_sha"][0..7]
//env.commitId = NewData["checkout_sha"] // 提交人
env.commitUser = NewData["user_username"]  //这里为什么要使用env.定义变量呢? 因为全局变量保险些,便于后面所有阶段间的引用;// current build desc
currentBuild.displayName = "${branchName}:${env.commitId}"
currentBuild.description = "src: ${srcUrl}"pipeline {agent anystages {stage('CheckOut') {steps {script {println("Checkout: ${srcUrl} ${branchName}")checkout([$class: 'GitSCM', branches: [[name: "${branchName}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab-root', url: "${srcUrl}"]]])sh 'ls -l'}}}// 代码构建stage("Build"){steps{script{echo "build"}}}//单元测试stage("UnitTest"){steps{script{echo "unit test"}}}//部署stage("deploy"){steps {script{echo "deploy"}}}}post {always{script{EmailUser(userEmail,"${currentBuild.currentResult}")}}}}def EmailUser(userEmail,status){emailext body: """<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0"> <img src="https://s1.ax1x.com/2023/04/25/p9usju8.jpg"><table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">   <tr> <td><br /> <b><font color="#0B610B">构建信息</font></b> </td> </tr> <tr> <td> <ul> <li>项目名称:${JOB_NAME}</li>         <li>构建编号:${BUILD_ID}</li> <li>构建状态: ${status} </li>                         <li>项目地址:<a href="${BUILD_URL}">${BUILD_URL}</a></li>    <li>构建日志:<a href="${BUILD_URL}console">${BUILD_URL}console</a></li> </ul> </td> </tr> <tr>  </table> </body> </html>  """,subject: "Jenkins-${JOB_NAME}项目构建信息 ",to: userEmail}

相关文章:

GitLABJenkins

GitLAB & Jenkins 目录 实践&#xff1a;基于Jenkins提交流水线(测试成功)-2023.4.25 目的&#xff1a;掌握通过触发器将GitLab和Jenkins集成&#xff0c;实现提交流水线。 1、触发Jenkins构建 安装Generic Webhook Trigger插件 重启后&#xff0c;进入一个Pipeline项目设…...

互联网摸鱼日报(2023-04-26)

互联网摸鱼日报&#xff08;2023-04-26&#xff09; InfoQ 热门话题 神州数码&#xff1a;抢抓云原生发展机遇&#xff0c;共建共治共享 OpenNJet 应用引擎开源生态 《产业数字人才研究与发展报告&#xff08;2023&#xff09;》 如何写出CPU友好的代码&#xff0c;百倍提升…...

石化企业数字化防爆融合通信解决方案

项目背景 石化工业是我国国民经济和社会发展的基础性、战略性产业&#xff0c;其发展和壮大受到了党和国家的高度重视。随着石化企业厂区规模的不断扩大以及技术的快速发展&#xff0c;现有石化企业专网通信系统建设相对滞后&#xff0c;缺乏结合人员管理、安全生产、安全通信…...

NTT学习笔记(快速数论变换)

一些概念 欧拉函数 ϕ ( n ) \phi(n) ϕ(n) 欧拉函数简介 阶 若 g g g和 n n n互质&#xff0c;则令 g x % n 1 g^x\%n1 gx%n1的最小正整数 x x x称为 g g g模 n n n的阶。 原根 对于互质的两个正整数 g g g和 n n n&#xff0c;如果 g g g模 n n n的阶为 ϕ ( n ) \phi…...

Android类似微信首页的页面开发教程(Kotlin)二

前提条件 安装并配置好Android Studio Android Studio Electric Eel | 2022.1.1 Patch 2 Build #AI-221.6008.13.2211.9619390, built on February 17, 2023 Runtime version: 11.0.150-b2043.56-9505619 amd64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. Windows 11 …...

PAt A1015 Reversible Primes

1015 Reversible Primes 分数 20 作者 CHEN, Yue 单位 浙江大学 A reversible prime in any number system is a prime whose "reverse" in that number system is also a prime. For example in the decimal system 73 is a reversible prime because its rever…...

解决Lemuroid识别不到蓝牙键盘的问题

Android系统基于libretro的全能游戏模拟器&#xff0c;目前有RetroArch&#xff0c;Kodi&#xff0c;Lemuroid。 而且这三个都是开源免费的APP。 Lemuroid相对前面两个功能比较简陋。也不能自己下载核心。但代码也是最少的。 在使用Lemuroid的时候&#xff0c;发现它不能检测…...

SpringBoot 使用 Sa-Token 完成权限认证

一、设计思路 所谓权限认证&#xff0c;核心逻辑就是判断一个账号是否拥有指定权限&#xff1a; 有&#xff0c;就让你通过。没有&#xff1f;那么禁止访问&#xff01; 深入到底层数据中&#xff0c;就是每个账号都会拥有一个权限码集合&#xff0c;框架来校验这个集合中是…...

Spring核心与设计思想、创建与使用

文章目录 一、Spring是什么二、为什么要学习框架三、IoC和DI&#xff08;一&#xff09;IoC1. 认识IoC2. Spring的核心功能 &#xff08;二&#xff09;DI 四、Spring项目的创建&#xff08;一&#xff09;使用 Maven 方式创建一个 Spring 项目 五、Spring项目的使用&#xff0…...

mysql 备份 还原

1:备份 执行命令方案1: /usr/local/mysql/bin/mysqldump -uX -pX -h 127.0.0.1 --set-gtid-purgedOFF --skip-extended-insert --add-drop-table --add-locks --create-options --disable-keys --lock-tables --quick --set-charset -e --max_allowed_packet16777216 --net_b…...

每日学术速递4.26

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1.AutoNeRF: Training Implicit Scene Representations with Autonomous Agents 标题&#xff1a;AutoNeRF&#xff1a;使用自主代理训练隐式场景表示 作者&#xff1a;Pierre Marz…...

RabbitMQ使用StringRedisTemplate-防止重复消费

造成重复消费的原因&#xff1a; MQ向消费者推送message&#xff0c;消费者向MQ返回ack&#xff0c;告知所推送的消息消费成功。但是由于网络波动等原因&#xff0c;可能造成消费者向MQ返回的ack丢失。MQ长时间&#xff08;一分钟&#xff09;收不到ack&#xff0c;于是会向消…...

临沂大学张继群寄语

目录 寄语 1、不能有不良睹好 2、坚毅的个性和勤奋的品质 3、会存钱...

线程学习笔记

1:Thread 线程的生命周期控制 2:Runnable 可执行的任务和程序 3:Callable 执行程序后返回结果 4:Future 收集程序返回结果 5:Executor 线程池 6:ForkJoin 默认线程池 每个线程有工作队列 工作窃取 7:RunnableFuture FutureTask 实现 Runnable 和 Future 执…...

代码随想录算法训练营第四十二天|01背包问题,你该了解这些!、01背包问题,你该了解这些! 滚动数组 、416. 分割等和子集

文章目录 01背包问题&#xff0c;你该了解这些&#xff01;01背包问题&#xff0c;你该了解这些&#xff01; 滚动数组416. 分割等和子集 01背包问题&#xff0c;你该了解这些&#xff01; 题目链接&#xff1a;代码随想录 二维数组解决0-1背包问题 解题思路&#xff1a; 1.dp…...

结构体指针、数组指针和结构体数组指针

结构体指针 首先让我们定义结构体&#xff1a; struct stu { char name[20]; long number; float score[4]; }; 再定义指向结构体类型变量的指针变量&#xff1a; struct stu *student; /*定义结构体类型指针*/ student malloc(sizeof(struct stu)); /*为指针变量分…...

项目架构一些注意点

考虑系统的 稳定性 一、微服务的稳定性 1、如何解决那些不稳定的因素/问题&#xff1f;也是常说的如何容错。 2、一个系统的高可用取决于它本身和其强依赖的组件的高可用 3、消除单点 保活机制 健康检查 注册中心如何保障稳定性 注册中心集群 微服务本身对注册信息的本地持…...

Forefront GPT-4免费版:开启无限畅聊时代,乐享人工智能快感,无限制“白嫖”,还能和N多角色一起聊天?赶紧注册,再过些时间估计就要收费了

目录 前言注册登录方式应用体验聊天体验绘图体验 “是打算先免费后收费吗&#xff1f;”建议其它资料下载 前言 近期&#xff0c;人工智能技术迎来重大飞跃&#xff0c;OpenAI的ChatGPT等工具成为全球数亿人探索提高生产力和增强创造力的新方法。人们现在可以使用人工智能驱动…...

深入浅出 Compose Compiler(1) Kotlin Compiler KCP

前言 Compose 的语法简洁、代码效率非常高&#xff0c;这主要得益于 Compose Compiler 的一系列编译期魔法&#xff0c;帮开发者生成了很多样板代码。但编译期插桩也阻碍了我们对于 Compose 运行原理的认知&#xff0c;想要真正读懂 Compose 就必须先了解它的 Compiler。本系列…...

BatchNormalization和LayerNormalization的理解、适用范围、PyTorch代码示例

文章目录 为什么要NormalizationBatchNormLayerNormtorch代码示例 学习神经网络归一化时&#xff0c;文章形形色色&#xff0c;但没找到适合小白通俗易懂且全面的。学习过后&#xff0c;特此记录。 为什么要Normalization 当输入数据量级极大或极小时&#xff0c;为保证输出数…...

大数据 | 实验二:文档倒排索引算法实现

文章目录 &#x1f4da;实验目的&#x1f4da;实验平台&#x1f4da;实验内容&#x1f407;在本地编写程序和调试&#x1f955;代码框架思路&#x1f955;代码实现 &#x1f407;在集群上提交作业并执行&#x1f955;在集群上提交作业并执行&#xff0c;同本地执行相比即需修改…...

Java文档注释-JavaDoc标签

标签含义author指定作者{code}使用代码字体以原样显示信息&#xff0c;不处理HTML样式deprecated指定程序元素已经过时{docRoot}指定当前文档的根目录路径exception标识由方法或构造函数抛出的异常{inheritDoc}从直接超类中继承注释{link}插入指向另外一个主题的内联链接{linkp…...

黑盒测试过程中【测试方法】详解5-输入域,输出域,猜错法

在黑盒测试过程中&#xff0c;有9种常用的方法&#xff1a;1.等价类划分 2.边界值分析 3.判定表法 4.正交实验法 5.流程图分析 6.因果图法 7.输入域覆盖法 8.输出域覆盖法 9.猜错法 黑盒测试过程中【测试方法】讲解1-等价类&#xff0c;边界值&#xff0c;判定表_朝一…...

Python学习之sh(shell脚本)在Python中的使用

文章目录 前言一、sh是什么&#xff1f;二、使用步骤1.安装2.使用示例3.使用sh执行命令4.关键字参数5.查找命令6.Baking参数 前言 本文章向大家介绍[Python库]分析一个python库–sh&#xff08;系统调用&#xff09;&#xff0c;主要内容包括其使用实例、应用技巧、基本知识点…...

追求卓越:编写高质量代码的方法和技巧

本文讨论了编写高质量代码的重要性&#xff0c;并详细介绍了高质量代码的特征、编程实践技巧和软件工程方法论。通过遵循这些原则和实践&#xff0c;程序员可以编写出更稳定、可维护和可扩展的代码。 一、 前言 写出高质量代码是每个程序员的追求和目标。高质量的代码可以使程…...

MATLAB算法实战应用案例精讲-【人工智能】机器视觉(概念篇)(最终篇)

目录 前言 几个高频面试题目 如何评价一个光源的好坏? 如何依靠光源增强图像对比度?...

【老王读SpringMVC-3】根据 url 是如何找到 controller method 的?

前面分析了 request 与 handler method 映射关系的注册&#xff0c;现在再来分析一下 SpringMVC 是如何根据 request 来获取对应的 handler method 的? 可能有人会说&#xff0c;既然已经将 request 与 handler method 映射关系注册保存在了 AbstractHandlerMethodMapping.Ma…...

人机交互到艺术设计及玫瑰花绘制实例

Python库之图形用户界面 Riverbank Computing | Introduction Welcome to wxPython! | wxPython Overview — PyGObject Python库之游戏开发 https://www.pygame.org/news Panda3D | Open Source Framework for 3D Rendering & Games python.cocos2d.org Python库之…...

多臂老虎机问题

1.问题简介 多臂老虎机问题可以被看作简化版的强化学习问题&#xff0c;算是最简单的“和环境交互中的学习”的一种形式&#xff0c;不存在状态信息&#xff0c;只有动作和奖励。多臂老虎机中的探索与利用&#xff08;exploration vs. exploitation&#xff09;问题一直以来都…...

DNS 查询原理详解

DNS&#xff08;Domain Name System&#xff09;是互联网上的一种命名系统&#xff0c;它将域名转换为IP地址。在进行DNS查询时&#xff0c;先要明确需要查询的主机名&#xff0c;然后向本地DNS服务器发出查询请求。 1. 本地DNS服务器查询 当用户在浏览器中输入一个URL或者点…...