使用 Node.js 和 socket.io 一段时间后,我明白如果我希望我的应用程序支持多达 100 万个并发用户,我需要对其进行扩展,因此我开始使用 Redis 在PUB/SUB套接字之间发送消息并运行大量套接字.io 服务器实例,在同一台机器和其他机器上,但我所有的 socket.io 服务器都使用同一个 Redis 服务器。
这让我思考:这有什么意义呢?我是否需要更多的 Redis 服务器并在它们之间进行扩展?我的观点是,它们永远是顶级服务器的瓶颈。
我的问题是,Redis 是否可以扩展?如果是,那么连接到不同 socket.io 服务器的所有套接字如何能够在 Redis 服务器之间进行 PUB/SUB?
我目前在node.js和socket.io中有一个聊天应用程序(一对一).随着我网站中的用户不断增加,我想在聊天应用中引入redis.这是我当前应用的一个小例子:
// all requires and connections
io.sockets.on('connection', function(socket) {
socket.on('message', function(msg) {
// code to get receiverssocket
io.sockets.sockets[receiverssocket].emit('message',
{"source": msg.sendersusername,"msg": msg.msg});
});
});
Run Code Online (Sandbox Code Playgroud)
现在,我试图找到如何使用redis执行此操作的示例,但我找不到使用redis进行一对一聊天的示例.我只能找到将消息发送给所有用户的示例.这是我看过的一个例子
我想到这样做的一种方法是为每个接收消息的用户创建频道,但这会产生数千个频道.有关我如何做到这一点的任何帮助?
编辑:添加了一些代码
io.sockets.on('connection', function (client) {
sub.on("message", function (channel, message) {
console.log("message received on server from publish ");
client.send(message);
});
client.on("message", function (msg) {
console.log(msg);
if(msg.type == "chat"){
pub.publish("chatting." + msg.tousername,msg.message);
}
else if(msg.type == "setUsername"){
sub.subscribe("chatting." + msg.user);
sub.subscribe("chatting.all" );
pub.publish("chatting.all","A new user in connected:" + msg.user);
store.sadd("onlineUsers",msg.user);
}
});
client.on('disconnect', function () { …Run Code Online (Sandbox Code Playgroud) 我希望我的应用程序(现在假设是一个简单的节点文件)即使 redis 不可用也能正常工作。我无法以正确的方式做到这一点。这是我尝试过的。
var redis = require('redis');
var redisClient = null;
var getRedisClient = function(){
if(redisClient){
return redisClient;
}
try {
redisClient = redis.createClient({connect_timeout : 5000, max_attempts : 1});
redisClient.on("error", function(err) {
console.error("Error connecting to redis", err);
redisClient = null;
});
return redisClient;
} catch(ex){
console.log("error initialising redis client " + ex);
return null;
}
};
try {
var client = getRedisClient();
console.log("done!");
} catch (ex){
console.log("Exception");
}
Run Code Online (Sandbox Code Playgroud)
但是,使用此代码,如果 redis 不可用,我的应用程序将退出(不应该,因为我没有给出 process.exit() 命令)。
我该如何解决这个问题?
我正在设置一个简单的1 Master - N Slaves Redis集群(低写入循环,高读取计数).如何设置它在Redis网站上有详细记录,但是,没有关于客户端(在我的情况下是Node.js服务器)如何处理集群的信息(或者我错过了它).我的服务器是否需要打开2个Redis连接:一个用于Master(写入),另一个用于Slave负载平衡器用于读取?Redis驱动程序是否自动处理此问题并将读取发送到从属服务器并写入主服务器?
我为项目实现了基本的缓存功能,并在测试期间遇到了问题。我使用玩笑和redis-mock进行测试,所有测试均通过。问题是当我导入一个导入redis文件的文件时。测试文件不会退出。
例:
index.test.js
import redis from 'redis'
import redis_mock from 'redis-mock'
jest.spyOn(redis, 'createClient').mockImplementation(red_mock.createClient)
import fileUsingRedis from './index'
describe('index', () => {
it('should pass', () => expect(true).toBeTruthy())
}
Run Code Online (Sandbox Code Playgroud)
index.js
import {set} from './redis'
export default function ...
Run Code Online (Sandbox Code Playgroud)
redis.js
import redis from 'redis'
const client = redis.createClient()
export function set(key, value) {...}
Run Code Online (Sandbox Code Playgroud)
'1通过'...'跑所有匹配的测试套件...'
但是随后它一直在等待,因为reis.createClient()是异步的或其他原因。看到导入时发生的情况,我不能仅仅解决它。每次测试后是否都必须关闭redis-instance连接?
解决方案/最佳做法是什么?
我正在开发一个使用 Redis 作为数据库的 NodeJS 服务器,我需要检索具有特定 service_id 值的所有 Redis 键。例如,如果服务 id 为 4,我需要检索 service_id = 4 的所有键。我在 Redis 中得到以下结构,其中值是 JSON:
key: "{service_id: number}"
是否可以过滤具有特定服务 ID 的密钥?也许有一些解决方法可以使其成为可能?
const redis = require('redis');
require('dotenv').config();
console.log(process.env.redisHost, ':', process.env.redisPort);
const redisClient = redis.createClient({
host: process.env.redisHost,
port: process.env.redisPort,
password: process.env.redisKey
});
redisClient.connect();
redisClient.on('error', err => console.log('Redis error: ', err.message));
redisClient.on('connect', () => console.log('Connected to redis server'));
module.exports = redisClient;
Run Code Online (Sandbox Code Playgroud)
我尝试了 redis 文档中的示例,但仍然收到错误消息:
Redis error: connect ECONNREFUSED 127.0.0.1:6379
我将环境主机和端口变量记录到控制台,并获得了远程主机 ipv4 地址,但客户端仍然尝试连接到本地主机而不是远程主机(我故意从本地设备卸载了 redis 以检查客户端是否正常工作正如它应该的那样)。我还确认远程redis主机工作正常。
我还尝试了不同的方法,例如: https: //cloud.google.com/community/tutorials/nodejs-redis-on-appengine
redis.createClient(port, host, {auth_pass: password});
Run Code Online (Sandbox Code Playgroud)
但我仍然遇到了同样的错误。
我可以通过命令行连接到 redis 主机:
redis-cli.exe -h XX.XX.XX.XXX -a Password
XX.XX.XX.XXX:6379> set name dhruv
OK
XX.XX.XX.XXX:6379> get name
"dhruv"
XX.XX.XX.XXX:6379> exit
Run Code Online (Sandbox Code Playgroud)
我第一次尝试在nodejs上使用redis,所以没有正确的想法,但我认为我做的一切都是正确的。任何解决方案/解决方法都会有帮助:D
我正在 Node 中构建一个 API,并希望将 API 密钥/访问令牌存储在 Redis 中。
如何最好地生成唯一的 API 密钥/访问令牌以将其作为密钥存储在 Redis 中,并将电子邮件地址作为值存储?
Redis 是否有一个内置函数可以生成具有一定长度和字符集的唯一 id,或者我应该如何最好地解决这个问题?
谢谢你!
我有 2 个 Redis 服务器,一个主服务器,另一个从服务器(复制)。一旦Master由于某种原因宕机了,Slave就会成为Master,并继续充当Master,直到该服务器出现问题为止。
我有一个nodeJS服务器,我想将数据推送到当前作为Master运行的Redis。我有一个监视 Redis 服务器的哨兵,但我的问题是如何使用 nodeJS 从哨兵获取主信息?如果有办法的话,它是否会自动将数据推送到备用redis服务器而无需重新启动任何服务?
让我在问题前言说,我理解这个主题可能不会有明确的、是或否的答案,并且给出的答案可能是观点驱动的。但是,我确实需要并感谢您在部署和操作以下 API 设计方面的建议和/或指导。
对于我的 SaaS,我想通过 API 向我的客户提供其功能。SaaS 提供的任务是一项长期运行且计算成本高昂的任务。因此,不幸的是,运行一个简单的“同步”API(其中调用者等待此任务的结果作为对其请求的响应来传递)是不合适的。相反,我选择了一种方法,让调用者安排Jobs并定期查询 API 以查看给定的作业是否已完成。我对这个设计非常满意。
为了实现,我构建/使用了以下技术:
Node.js服务器Express用于 API 和路由的 npm 包Redis用于作业调度的数据库bullmq用于 Redis 连接和队列管理的 npm 包使用bullmq,我创建一个队列Queue并将其添加Jobs到该队列中,以响应对给定端点的调用。
对我来说,这是api.ts(缩短):
import Express from "express"
import { Queue } from "bullmq"
const api = Express()
const queue = new Queue("com.mysaas.workerQueue")
api.post("/job", async (request, response) => {
var data, jobId
...
await queue.add("com.mysaas.defaultJob", data, {
jobId: jobId,
removeOnComplete: true,
...
}) …Run Code Online (Sandbox Code Playgroud) node-redis ×10
node.js ×10
redis ×8
socket.io ×2
api-design ×1
bullmq ×1
database ×1
express ×1
javascript ×1
jestjs ×1
pm2 ×1
sockets ×1