我一直在尝试使用 ioredis 连接到 Azure 中的 Redis 三节点集群。
当我使用 Redis.Cluster 构造函数进行连接时:
new Redis.Cluster(['host.redis.cache.windows.net', 6380], {
scaleReads: 'all',
slotsRefreshTimeout: 2000,
redisOptions: {
password: 'some-secret',
tls: true as any
},
});
我得到的错误是:
2020-06-04T13:05:41.787Z ioredis:cluster getting slot cache from 127.0.0.1:6380
2020-06-04T13:05:41.788Z ioredis:redis status[127.0.0.1:6380 (ioredisClusterRefresher)]: [empty] -> wait
2020-06-04T13:05:41.788Z ioredis:redis status[127.0.0.1:6380 (ioredisClusterRefresher)]: wait -> connecting
2020-06-04T13:05:41.788Z ioredis:redis queue command[127.0.0.1:6380 (ioredisClusterRefresher)]: 0 -> cluster([ 'slots' ])
2020-06-04T13:05:41.790Z ioredis:connection error: Error: connect ECONNREFUSED 127.0.0.1:6380
2020-06-04T13:05:41.791Z ioredis:redis status[127.0.0.1:6380 (ioredisClusterRefresher)]: connecting -> close
2020-06-04T13:05:41.791Z ioredis:connection skip reconnecting because `retryStrategy` is not a function
2020-06-04T13:05:41.791Z ioredis:redis status[127.0.0.1:6380 (ioredisClusterRefresher)]: close -> end
2020-06-04T13:05:41.792Z [auth-middleware] Redis error { ClusterAllFailedError: Failed to refresh slots cache.
at tryNode (/app/node_modules/ioredis/built/cluster/index.js:359:31)
at /app/node_modules/ioredis/built/cluster/index.js:376:21
at duplicatedConnection.cluster.utils_2.timeout (/app/node_modules/ioredis/built/cluster/index.js:624:24)
at run (/app/node_modules/ioredis/built/utils/index.js:156:22)
at tryCatcher (/app/node_modules/standard-as-callback/built/utils.js:11:23)
at promise.then (/app/node_modules/standard-as-callback/built/index.js:30:51)
at process._tickCallback (internal/process/next_tick.js:68:7)
lastNodeError:
Error: Connection is closed.
at close (/app/node_modules/ioredis/built/redis/event_handler.js:179:25)
at TLSSocket.<anonymous> (/app/node_modules/ioredis/built/redis/event_handler.js:150:20)
at Object.onceWrapper (events.js:277:13)
at TLSSocket.emit (events.js:194:15)
at _handle.close (net.js:600:12)
at TCP.done (_tls_wrap.js:388:7) }
当我使用非集群 Redis 连接进行连接时:
new Redis(6380, 'host.redis.cache.windows.net', { password: 'some-secret' });
我得到的错误是:
020-06-04T15:04:08.609Z ioredis:redis status[10.211.x.x:6380]: connecting -> connect
2020-06-04T15:04:08.614Z ioredis:redis write command[10.211.x.x:6380]: 0 -> auth([ 'some-secret' ])
2020-06-04T15:04:08.616Z ioredis:redis write command[10.211.x.x:6380]: 0 -> info([])
2020-06-04T15:05:16.114Z ioredis:connection error: Error: read ECONNRESET
2020-06-04T15:05:16.115Z [auth-middleware] Redis error { Error: read ECONNRESET
at TCP.onStreamRead (internal/stream_base_commons.js:111:27) errno: 'ECONNRESET', code: 'ECONNRESET', syscall: 'read' }
如您所见,它在端口 6380 上使用 TLS。Azure 为我提供了一个主机 + 端口组合和两个不同的访问密钥(主/辅助( - 我觉得很奇怪,我应该使用哪个访问密钥?我也不确定我是否应该在集群模式下连接,但我更愿意获得集群的好处。当我这样做时,它似乎试图在127.0.0.1:6380
找到插槽,这可能是不正确的。
在 Azure 的快速入门中,他们使用 node_redis 与以下内容进行连接:
var redis = require("redis");
// Add your cache name and access key.
var client = redis.createClient(6380, process.env.REDISCACHEHOSTNAME,
{auth_pass: process.env.REDISCACHEKEY, tls: {servername: process.env.REDISCACHEHOSTNAME}});
我希望这里有人会遇到同样的问题并解决它。
谢谢!
好的,我已经设法使用非tls连接连接到Azure Redis群集:
new Redis.Cluster(['host.redis.cache.windows.net', 3679], {
scaleReads: 'all',
slotsRefreshTimeout: 2000,
redisOptions: {
password: 'some-secret',
},
})
由于某种原因,在启用 TLS 的情况下连接到 6380 不起作用。
下面是使用TLS 端口上的 NodeJs 连接 Azure Redis 群集( 群集模式 ( 的正确代码
从以下链接下载计算机上的DigiCert全局根G2证书: [1]: https://www.digicert.com/kb/digicert-root-certificates.htm
const Redis = require("ioredis");
const fs = require('fs');
const path = require('path');
const cluster = new Redis.Cluster([{
port: 6380,
host: "xxx—your-redis-cache-host-name—xxx"
}], {
scaleReads: 'all',
slotsRefreshTimeout: 50000,
enableReadyCheck: true,
redisOptions: {
tls: {
ca: fs.readFileSync(path.resolve("DigiCertGlobalRootG2.crt.pem")),
rejectUnauthorized: false
},
password: "xxx—your-redis-cache-key—xxx"
},
lazyConnect: true,
maxRetriesPerRequest: 3,
retryStrategy(times) {
const delay = Math.min(times * 50, 2000);
return delay;
},
reconnectOnError(err) {
// try to reconnect only when the error contains "READONLY"
const targetError = "READONLY";
if (err.message.includes(targetError)) {
return true;
}
},
});
cluster.set("today", "application");
cluster.get("today", (err, res) => {
console.log(res);
});