amqplib-init 1.1.6 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/demo.js +5 -0
- package/index.js +93 -102
- package/package.json +2 -1
package/demo.js
ADDED
package/index.js
CHANGED
|
@@ -1,119 +1,110 @@
|
|
|
1
1
|
const amqp = require('amqplib');
|
|
2
2
|
const shelljs = require('shelljs');
|
|
3
|
-
const
|
|
3
|
+
const log = require('chalk-style')
|
|
4
|
+
const happy = require('happy-help');
|
|
4
5
|
|
|
5
|
-
const sleep = (time) => {
|
|
6
|
-
return new Promise(resolve => {
|
|
7
|
-
setTimeout(_ => resolve(), time * 1000)
|
|
8
|
-
})
|
|
9
|
-
};
|
|
10
6
|
module.exports = {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* @returns {Promise<unknown>}
|
|
14
|
-
* @param option
|
|
15
|
-
*/
|
|
16
|
-
init (option){
|
|
7
|
+
// 初始化函数
|
|
8
|
+
init(option) {
|
|
17
9
|
const {
|
|
18
|
-
channelName = 'node-test-channel',
|
|
19
|
-
prefetch = 1,
|
|
20
|
-
pmId = 0,
|
|
21
|
-
callback = ()=> {},
|
|
22
|
-
finish = ()=> {},
|
|
23
|
-
amqpLink =
|
|
24
|
-
heartbeat = 5,
|
|
25
|
-
timeout =
|
|
26
|
-
delay = 0,
|
|
27
|
-
autoReload = 0,
|
|
28
|
-
queryHook = () => {},
|
|
29
|
-
|
|
10
|
+
channelName = 'node-test-channel', // 频道名称,默认为'node-test-channel'
|
|
11
|
+
prefetch = 1, // 预取计数,默认为1
|
|
12
|
+
pmId = 0, // PM2进程ID,默认为0
|
|
13
|
+
callback = () => {}, // 消息处理回调,默认为空函数
|
|
14
|
+
finish = () => {}, // 初始化完成回调,默认为空函数
|
|
15
|
+
amqpLink = '', // RabbitMQ连接地址
|
|
16
|
+
heartbeat = 5, // 心跳间隔,单位为秒,默认为2秒
|
|
17
|
+
timeout = 2000, // 连接超时时间,单位为毫秒,默认为10000毫秒
|
|
18
|
+
delay = 0, // 消息处理完成后延迟ack的时间,单位为毫秒,默认为0毫秒
|
|
19
|
+
autoReload = 0, // 自动重载间隔时间,单位为毫秒,默认为0毫秒(不自动重载)
|
|
20
|
+
queryHook = () => {}, // 查询钩子,默认为空函数(用于判断是否有其他消息来源)
|
|
21
|
+
initHook = () => {} // 初始化钩子,默认为空函数(在连接成功后执行)
|
|
30
22
|
} = option;
|
|
31
|
-
const durable = true;
|
|
32
|
-
|
|
33
|
-
let
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
shelljs.exec(`pm2 reload ${pmId}`);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return new Promise(async (resolve) => {
|
|
46
|
-
await amqpInit();
|
|
47
|
-
chalk.log(`✳️->RabbitMQ链接成功`);
|
|
48
|
-
const channel = await connect.createChannel();
|
|
49
|
-
chalk.log(`✳️->数据队列名称`, channelName);
|
|
50
|
-
chalk.log(`✳️->是否持久化`, durable);
|
|
51
|
-
const { queue } = await channel.assertQueue(channelName, { durable });
|
|
52
|
-
// 从这里绑定交换机;
|
|
53
|
-
await init && init({ channel, connect });
|
|
54
|
-
// 一次性读取一条;
|
|
23
|
+
const durable = true; // 队列是否持久化,默认为true
|
|
24
|
+
let connection = null; // RabbitMQ连接
|
|
25
|
+
let channel = null; // RabbitMQ频道
|
|
26
|
+
|
|
27
|
+
// 重连函数
|
|
28
|
+
const reconnect = async () => {
|
|
29
|
+
log.error('连接丢失,正在尝试重连...');
|
|
30
|
+
await happy.sleep(2); // 重连前等待2秒
|
|
31
|
+
connection = await amqp.connect(amqpLink, { heartbeat, timeout });
|
|
32
|
+
channel = await connection.createChannel();
|
|
33
|
+
await channel.assertQueue(channelName, { durable });
|
|
55
34
|
await channel.prefetch(prefetch);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
await
|
|
35
|
+
await initHook({ channel, connection }); // 执行初始化钩子
|
|
36
|
+
log.log(`已重新连接到RabbitMQ,频道: ${channelName}`);
|
|
37
|
+
await consumeMessages(); // 开始消费消息
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// 消费消息函数
|
|
41
|
+
const consumeMessages = async () => {
|
|
42
|
+
log.log(`开始消费: ${channelName}`);
|
|
43
|
+
await channel.consume(channelName, async (msg) => {
|
|
59
44
|
if (msg !== null) {
|
|
60
45
|
try {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const endTime = (new Date().getTime() - startTime);
|
|
69
|
-
chalk.log(`✳️->消息处理完成, 需要延迟: ${delay}ms, 共耗时: ${endTime}ms`);
|
|
70
|
-
channel.ack(msg);
|
|
71
|
-
}, delay)
|
|
72
|
-
} catch (e) {
|
|
73
|
-
chalk.warning(`队列消费遇到异常`, e);
|
|
74
|
-
channel.reject(msg,true);
|
|
75
|
-
}
|
|
76
|
-
}).catch(e => {
|
|
77
|
-
chalk.warning(`消息处理遇到异常`, e);
|
|
78
|
-
channel.reject(msg, true);
|
|
79
|
-
});
|
|
46
|
+
const content = JSON.parse(msg.content.toString());
|
|
47
|
+
log.log(`收到消息: ${JSON.stringify(content)}`);
|
|
48
|
+
const startTime = Date.now();
|
|
49
|
+
await callback(content); // 执行消息处理回调
|
|
50
|
+
const endTime = Date.now() - startTime;
|
|
51
|
+
log.log(`消息处理完成,延迟: ${delay}ms,总时间: ${endTime}ms`);
|
|
52
|
+
setTimeout(() => channel.ack(msg), delay); // 延迟ack
|
|
80
53
|
} catch (e) {
|
|
81
|
-
|
|
54
|
+
log.error('处理消息时出错:', e);
|
|
55
|
+
channel.reject(msg, true); // 拒绝消息并重新排队
|
|
82
56
|
}
|
|
83
57
|
} else {
|
|
84
|
-
|
|
58
|
+
log.error('收到无效消息:', msg);
|
|
85
59
|
}
|
|
86
60
|
}, { noAck: false });
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// 启动函数
|
|
64
|
+
const start = async () => {
|
|
65
|
+
try {
|
|
66
|
+
connection = await amqp.connect(amqpLink, { heartbeat, timeout });
|
|
67
|
+
channel = await connection.createChannel();
|
|
68
|
+
await channel.assertQueue(channelName, { durable });
|
|
69
|
+
await channel.prefetch(prefetch);
|
|
70
|
+
await initHook({ channel, connection }); // 执行初始化钩子
|
|
71
|
+
log.log(`已连接到RabbitMQ,频道: ${channelName}`);
|
|
72
|
+
await consumeMessages(); // 开始消费消息
|
|
73
|
+
// 连接错误处理
|
|
74
|
+
connection.on('error', (err) => {
|
|
75
|
+
log.error('连接错误:', err.message);
|
|
76
|
+
reconnect(); // 尝试重连
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// 连接关闭处理
|
|
80
|
+
connection.on('close', () => {
|
|
81
|
+
log.error('与RabbitMQ的连接已关闭');
|
|
82
|
+
reconnect(); // 尝试重连
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// 自动重载逻辑
|
|
86
|
+
if (autoReload > 0) {
|
|
87
|
+
setInterval(async () => {
|
|
88
|
+
try {
|
|
89
|
+
const { messageCount } = await channel.checkQueue(channelName);
|
|
90
|
+
const hookResult = await queryHook()
|
|
91
|
+
log.log(`MQ队列中有 ${messageCount} 条消息,检测是否可以重启: ${hookResult?1:0}`);
|
|
92
|
+
if (messageCount === 0 && hookResult) {
|
|
93
|
+
log.log('队列中没有消息,正在重载服务...');
|
|
94
|
+
shelljs?.exec(`pm2 reload ${pmId}`); // 使用PM2重载服务
|
|
95
|
+
}
|
|
96
|
+
} catch (e) {
|
|
97
|
+
log.error('检查队列长度时出错:', e);
|
|
110
98
|
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
99
|
+
}, autoReload);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
finish(); // 执行初始化完成回调
|
|
103
|
+
} catch (e) {
|
|
104
|
+
log.error('初始化RabbitMQ连接时出错:', e);
|
|
115
105
|
}
|
|
116
|
-
|
|
117
|
-
|
|
106
|
+
};
|
|
107
|
+
// 返回启动函数并立即执行
|
|
108
|
+
return start();
|
|
118
109
|
}
|
|
119
|
-
}
|
|
110
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "amqplib-init",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.8",
|
|
4
4
|
"description": "消息队列初始化",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"amqplib": "^0.10.4",
|
|
13
13
|
"chalk-style": "^1.0.0",
|
|
14
|
+
"happy-help": "^1.0.1",
|
|
14
15
|
"js-base64": "^3.7.7",
|
|
15
16
|
"shelljs": "^0.8.5"
|
|
16
17
|
}
|