Jenkins 与 RabbitMQ 集成包括两部分: 1. 通过 RabbitMQ 触发 Jenkins 构建,这里 Jenkins 作为 RabbitMQ 的 consumer;2. Jenkins 构建结束后将构建结果发送到 RabbitMQ,以便其他程序消费,这里 Jenkins 作为 RabbitMQ 的 producer
这篇文章将介绍如何通过 RabbitMQ 触发 Jenkins 构建,内容如下:
- 插件安装
- 配置 RabbitMQ Consumer
- 配置 Jenkins Job
- 触发 Jenkins 构建
- Node.js 实现
关于如何在 Centos 7 下安装 RabbitMQ,可以参考这篇文章:阿里云 Centos 7 安装和配置 RabbitMQ
关于如何将 Jenkins 构建结果发送给 RabbitMQ,请参考 Jenkins 与 RabbitMQ 集成(二)
1. 插件安装
打开 Jenkins 主页,进入 Manage Jenkins -> Manager Plugin
, 搜索并安装插件 RabbitMQ Build Trigger Plugin
.
如果找不到RabbitMQ Build Trigger Plugin
,不要担心,可能是Update Site
配置得不对, 点击 Installed
右边的 Advanced
,配置 Update Site
的URL 为 http://updates.jenkins-ci.org/stable/update-center.json
, 再重新搜索就好。
2. 配置 RabbitMQ Consumer
打开 Jenkins 主页,进入 Manage Jenkins -> Configure System
, 找到 RabbitMQ Consumer
, 选中 Enable consumer
,并配置好 Service URI
,Username
和Password
, 然后点击 Test Connection
是否可以与Rabbitmq通信。
在 Queues
里点击 Add
,并配置好 Application ID
和 Queue name
,如下图所示:
3. 配置 Jenkins Job
打开想要触发的 Job,点击左侧的 Configure
,进入配置页面,点击 Build trigger
,勾上 RabbitMQ Build Trigger
,并将用于触发的 Token 填上,如下图所示:
4. 触发 Jenkins 构建
到此为止,通过 RabbitMQ 远程触发 Jenkins 构建的配置工作就完成了,接下来我们来验证吧~
验证过程中我会用到配置 RabbitMQ Consumer 的时候设置的 Application ID
和 Queue name
,以及配置 Jenkins Job 的时候设置的 token。
- 在 RabbitMQ 中新建一个 Queue,Queue 的名字就是你在 Jenkins 中配置的
Queue name
; - 在刚刚新建的 Queue 里面加一条 Message,Message 内容如下:
{
'project': 'wangxiaoqi/first project',
'token': "your token",
'parameter': []
}
其中 wangxiaoqi/first project
是我要触发的 Job 的位置,这个 Job 位于目录 wangxiaoqi
下,Job 的名字叫做 first project
。
Message 的 Properties 如下:
{
contentType: 'application/json',
appId: 'remote-build'
}
Message 创建成功后就会被 Jenkins 接收,触发 first project
这个 Job 的构建。
点开构建详情,也能看到 Triggered by remote build message from RabbitMQ queue: jenkins.build-trigger.queue
,如下图所示:
5. Node.js 实现
下面是我用 Node.js 实现的每分钟发送一条 Message 来触发 Jenkins 的脚本,供大家参考。
注意:在运行这个脚本之前,我已经手动在 RabbitMQ 上建好了 Queue jenkins.build-trigger.queue
,并将其 bind 在了 exchange test.build-trigger.exchange
上,当然大家也可以直接在代码里实现这一步操作。
代码只有一个 test.js 和一个 package.json,若要运行,执行 npm install
,然后 npm start
就好。
这是 package.json 的内容:
{
"name": "rabbitmq-trigger-jenkins",
"version": "1.0.0",
"description": "test",
"author": "wangxiaoqi",
"scripts": {
"start": "node text.js"
},
"dependencies": {
"amqplib": "0.5.2",
"node-schedule": "latest"
},
"engines": {
"node": "8.13.0"
}
}
这是 test.js 的内容:
const Amqpplib = require('amqplib/callback_api')
const schedule = require("node-schedule");
var rabbitMQConnection = null
var pubChannel = null
const rabbitMQurl = "amqp://user:password@host";
function connected () {
rabbitMQConnection.createConfirmChannel(function (err, channel) {
if (err) {
console.log('[AMQP] error', err)
rabbitMQConnection.close()
return
}
channel.on('error', function (err) {
console.log('RabbitMQ: channel error', err.message)
})
pubChannel = channel
})
}
class RabbitMQ {
static start () {
Amqpplib.connect(rabbitMQurl + '?heartbeat=30', function (err, conn) {
if (err) {
console.log('RabbitMQ: Connection Error. Reconnecting', err.message)
return setTimeout(RabbitMQ.start, 1000)
}
conn.on('error', function (err) {
if (err.message !== 'Connection closing') {
console.log('RabbitMQ: Connection broken.', err.message)
}
})
conn.on('close', function () {
console.log('RabbitMQ: Connection closed. Reconnecting')
return setTimeout(RabbitMQ.start, 1000)
})
console.log('RabbitMQ: connected')
rabbitMQConnection = conn
connected()
})
}
static assertExchange (exchange, type, option = {durable: false}, callback) {
return pubChannel.assertExchange(exchange, type, option, callback)
}
static publishMessage (exchange, routingKey, content, options = {persistent: true}) {
try {
pubChannel.publish(exchange, routingKey, content, options,
function (err, ok) {
if (err) {
console.log('RabbitMQ: publish message', err)
pubChannel.connection.close()
}
console.log('RabbitMQ: publish a message')
})
} catch (e) {
console.log('RabbitMQ: publish message error', e.message)
localQueue.push([exchange, routingKey, content, options])
}
}
static consume (queue, callback) {
pubChannel.consume(queue, callback, {noAck: true})
}
}
RabbitMQ.start()
let buildTriggerMsg = {
'project': 'wangxiaoqi/first project',
'token': "token",
'parameter': []
};
let msgProperties = {
contentType: 'application/json',
appId: 'remote-build'
};
let ex = 'test.build-trigger.exchange'
var rule = new schedule.RecurrenceRule();
rule.second = 0;
schedule.scheduleJob(rule, function(){
RabbitMQ.assertExchange(ex, 'direct', {durable: true}, () => {
RabbitMQ.publishMessage(ex, '#', Buffer.from(JSON.stringify(buildTriggerMsg), 'utf8'), msgProperties)
})
});
网友评论