socket.io-redis
如何去使用
代码语言:javascript复制const io = require('socket.io')(3000);
const redisAdapter = require('socket.io-redis');
io.adapter(redisAdapter({ host: 'localhost', port: 6379 }));
通过使用socket.io-redis
适配器运行socket.io 你可以在不同的进程或者服务器上运行多个socket.io实例,这样可以每个客户端广播和发送事件。
下面是一些命令:
代码语言:javascript复制io.emit('hello', '给所有客户端发送');
io.to('room42').emit('hello', "给所有在'room42'房间的客户端发送");
io.on('connection', (socket) => {
socket.broadcast.emit('hello', '给所有除了发送者的客户端发送');
socket.to('room42').emit('hello', "给所有在'room42'房间除了发送者的客户端发送");
});
将通过Redis 订阅/发布机制,给客户端广播
如果你想通过非socket.io进程向socket.io广播,你需要使用socket.io-emitter.
API
adapter(uri[, opts])
uri
是一个类似 localhost:6379
的字符串,如果你的 redis 是本地的. 下面列出了一些配置项
adapter(opts)
下列是被允许的配置项:
-
key
: 订阅/发布事件的key的名称,比如(socket.io
) -
host
: 连接redis的主机 (localhost
) -
port
: 连接redis的端口(6379
) -
pubClient
: 可选的, redis客户端的发布事件 -
subClient
: 可选的, redis客户端的订阅时间 -
requestsTimeout
: 可选的, 超时后适配器将停止响应请求(5000ms
)
如果你决定提供pubClient
和 subClient
, 确定你使用make sure you use
node_redis 作为客户端或者一个同等的API
RedisAdapter
redis适配器实例暴露了下面的属性,这是一般 适配器
所没有的
uid
prefix
pubClient
subClient
requestsTimeout
RedisAdapter#clients(rooms:Array, fn:Function)
返回连接房间名为rooms
的所有节点的客户端ID列表.查看 Namespace#clients(fn:Function)
io.of('/').adapter.clients((err, clients) => {
console.log(clients); // 一个包含所有连接上的客户端id的数组
});
io.of('/').adapter.clients(['room1', 'room2'], (err, clients) => {
console.log(clients); // 一个包括了房间名为'room1' 和/或 'room2'的客户端id的数组
});
// 你也可以这样用
io.in('room3').clients((err, clients) => {
console.log(clients); // 一个包括了'room3'房间内所有客户端id的数组
});
RedisAdapter#clientRooms(id:String, fn:Function)
返回给定客户端ID加入的房间的列表(甚至是在其他节点).
代码语言:javascript复制io.of('/').adapter.clientRooms('<my-id>', (err, rooms) => {
if (err) { /* 未知 id */ }
console.log(rooms); // 一个包含所给id的客户端加入的所有房间的数组
});
RedisAdapter#allRooms(fn:Function)
返回包含所有房间的列表
代码语言:javascript复制io.of('/').adapter.allRooms((err, rooms) => {
console.log(rooms); // 一个包括所有房间的数组 (所有节点)
});
RedisAdapter#remoteJoin(id:String, room:String, fn:Function)
让socket给定的id加入房间。回调将在socket加入到房间后触发,否则如果没有找到socket客户端,会提供一个err
参数
io.of('/').adapter.remoteJoin('<my-id>', 'room1', (err) => {
if (err) { /* 未知 id */ }
// 成功
});
RedisAdapter#remoteLeave(id:String, room:String, fn:Function)
使给定socketid的客户端离开房间。回调将在客户端离开房间后触发,如果没找到socket客户端,则会返回一个arr
参数.
io.of('/').adapter.remoteLeave('<my-id>', 'room1', (err) => {
if (err) { /* 未知的 id */ }
// 成功
});
RedisAdapter#remoteDisconnect(id:String, close:Boolean, fn:Function)
使给定id的socket客户端断开连接M. 如果将 close
设置为true, 它也将关闭其底层等socket。回调将会在socket客户端断开连接后调用,如果socket客户端没找到,则会返回一个 err
参数.
io.of('/').adapter.remoteDisconnect('<my-id>', true, (err) => {
if (err) { /* 未知的 id */ }
// 成功
});
RedisAdapter#customRequest(data:Object, fn:Function)
给所有节点发送一个请求,将会通过 customHook
的方法响应.
// 所有节点
io.of('/').adapter.customHook = (data, cb) => {
cb('hello ' data);
}
// 之后
io.of('/').adapter.customRequest('john', function(err, replies){
console.log(replies); // an array ['hello john', ...] with one element per node
});
客户端错误处理
接收Redis适配器实例的 pubClient
和 subClient
属性来订阅它的'error'时间:
const adapter = require('socket.io-redis')('localhost:6379');
adapter.pubClient.on('error', function(){});
adapter.subClient.on('error', function(){});
从pubClient
和 subClient
发布的错误,也将被转发到适配器实例:
const io = require('socket.io')(3000);
const redisAdapter = require('socket.io-redis');
io.adapter(redisAdapter({ host: 'localhost', port: 6379 }));
io.of('/').adapter.on('error', function(){});
自定义 client (例如: with authentication)
如果你需要给一个redis实例创建一个有密码的redisAdapter, that has a password, 使用订阅/发布属性代替密码
代码语言:javascript复制const redis = require('redis');
const redisAdapter = require('socket.io-redis');
const pub = redis.createClient(port, host, { auth_pass: "pwd" });
const sub = redis.createClient(port, host, { auth_pass: "pwd" });
io.adapter(redisAdapter({ pubClient: pub, subClient: sub }));
With ioredis client
集群例子
代码语言:javascript复制const io = require('socket.io')(3000);
const Redis = require('ioredis');
const cluster = new Redis.Cluster([
{
port: 6380,
host: '127.0.0.1'
},
{
port: 6381,
host: '127.0.0.1'
}
]);
const redisAdapter = require('socket.io-redis');
io.adapter(redisAdapter({ pubClient: cluster, subClient: cluster }));
哨兵例子
代码语言:javascript复制const io = require('socket.io')(3000);
const Redis = require('ioredis');
const options = {
sentinels: [
{ host: 'somehost1', port: 26379 },
{ host: 'somehost2', port: 26379 }
],
name: 'master01'
};
const pubClient = new Redis(options);
const subClient = new Redis(options);
io.adapter(redisAdapter({ pubClient: options, subClient: options }));
协议
socket.io-redis
适配器 在特别命名的Redis通道上广播和接受信息。全局等广播通道名称为:
prefix '#' namespace '#'
给单个房间广播的通道命名为:
代码语言:javascript复制prefix '#' namespace '#' room '#'
-
prefix
: 基本通道名称。默认为socket.io
.通过设置adapter(opts)
构造器中的opts.key
来更改 -
namespace
: 查看 https://github.com/socketio/socket.io#namespace. -
room
: 用于指向特定的房间
还有其他的库采用这个协议:
- socket.io-emitter
- socket.io-python-emitter
- socket.io-emitter-go
License
MIT