建立一个Nodejs websocket+redis推送服务器,遇到阻塞问题
建立一个Nodejs websocket+redis推送服务器,遇到阻塞问题
sever端,使用nodejs+redis建立一个推送服务器,运作机制是 nodejs不停地读取redis中的数据,然后使用websocket发送给client。 当client通过websocket连接服务器,然后服务器就开始向client不停的发送数据。 server端,我尝试使用while循环不停地访问redis数据库,发现代码在while这边卡住了。 求思路~~~~~~简易代码就好
当然可以。在Node.js中,直接使用while
循环来不停地读取Redis数据会导致阻塞问题,因为这会占用整个事件循环,使得其他异步操作无法执行。为了实现非阻塞的WebSocket + Redis推送服务器,我们可以利用事件驱动的方式,结合setInterval
或setTimeout
来定期检查Redis中的数据,并通过WebSocket将这些数据推送给客户端。
以下是一个简单的示例代码,展示了如何实现这一功能:
1. 安装必要的依赖
首先,你需要安装ws
(WebSocket库)和redis
(Redis客户端)库:
npm install ws redis
2. 编写服务器代码
接下来是服务器端的代码:
const WebSocket = require('ws');
const redis = require('redis');
// 创建WebSocket服务器
const wss = new WebSocket.Server({ port: 8080 });
// 创建Redis客户端
const client = redis.createClient();
// 处理连接
wss.on('connection', function connection(ws) {
console.log('A client connected.');
// 定期从Redis获取数据并推送给客户端
setInterval(() => {
client.get('message', (err, reply) => {
if (reply) {
ws.send(reply);
}
});
}, 1000); // 每秒检查一次Redis
});
console.log('WebSocket server is running on ws://localhost:8080');
3. 客户端代码
客户端代码非常简单,这里仅作示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebSocket Client</title>
</head>
<body>
<script>
const ws = new WebSocket('ws://localhost:8080');
ws.onmessage = function(event) {
console.log('Message from server:', event.data);
};
ws.onopen = function() {
console.log('Connected to the server.');
};
ws.onclose = function() {
console.log('Disconnected from the server.');
};
</script>
</body>
</html>
解释
- WebSocket服务器:我们创建了一个WebSocket服务器,监听8080端口。
- Redis客户端:我们创建了一个Redis客户端实例来与Redis进行通信。
- 定时任务:我们使用
setInterval
函数每秒检查一次Redis中的数据。如果Redis中有数据,我们将这些数据通过WebSocket发送给客户端。 - 客户端:客户端连接到WebSocket服务器,并接收来自服务器的数据。
这种方法避免了阻塞问题,因为setInterval
和Redis的回调都是异步的,不会阻塞事件循环。
我做过类似的事情,你while里面不停地去访问redis,由于是异步的,会不断去和redis建立链接,这样会占满cpu,占满网络资源,甚至占满内存。
我之前在redis里面存储的是list结构的数据,思路是这样的:每次要读redis里面的数据时先用llen查一下有多少数据,如果有超过200条(自己设置阀值),就读200条出来并且在处理完这二百条之后再立即去redis里面继续读数据,如果少于200条时就全部读出来并在处理完之后500ms(自己设置)再去读redis里面的数据。或者傻瓜式的:每500毫秒去拿一次数据。(瞬间压力就下来了)
其实你应该是想弄一个队列服务器的,建议还是用专门的库或者用rabbitMq这样的大杀器。如果自己写,容错做的不好的话很容易出bug.
在Node.js中使用Websocket和Redis来构建一个推送服务器时,如果使用while
循环不断地查询Redis,会导致程序阻塞,因为while
循环会占用主线程,使得其他操作无法执行。
为了解决这个问题,可以采用事件驱动的方式。我们可以利用setInterval
来定期检查Redis中的数据变化,或者使用redis
模块提供的订阅功能来监听数据变化。下面是一个简单的实现方式:
- 使用
ws
库来创建WebSocket服务器。 - 使用
ioredis
库来连接到Redis并监听变化。
示例代码
const WebSocket = require('ws');
const Redis = require('ioredis');
// 创建WebSocket服务器
const wss = new WebSocket.Server({ port: 8080 });
// 创建Redis客户端
const redis = new Redis();
// 存储已连接的WebSocket客户端
const clients = new Set();
// 监听新的WebSocket连接
wss.on('connection', (ws) => {
console.log('Client connected');
clients.add(ws);
ws.on('close', () => {
console.log('Client disconnected');
clients.delete(ws);
});
});
// 使用Redis订阅频道
redis.subscribe('news', (err, count) => {
if (err) throw err;
});
// 监听消息事件
redis.on('message', (channel, message) => {
console.log(`Received message on channel ${channel}: ${message}`);
// 将消息广播给所有客户端
clients.forEach((client) => {
client.send(message);
});
});
解释
ws
是一个用于创建WebSocket服务器的库。ioredis
是一个高性能的Redis客户端。clients
集合用于存储所有连接的WebSocket客户端。- 当有新的WebSocket连接时,将其添加到
clients
集合,并监听关闭事件以删除断开连接的客户端。 - 使用Redis的
subscribe
方法订阅特定频道(例如'news'
),并监听message
事件来处理新消息。 - 当接收到消息时,将消息广播给所有已连接的客户端。
这种方法避免了使用while
循环带来的阻塞问题,使得服务器能够高效地处理WebSocket连接和Redis消息。