Filidor Wiese
Filidor Wiese

Reputation: 682

Connecting to an Azure Redis Cluster using node.js ioredis not working

I've been trying to connect to a Redis three node cluster in Azure using ioredis.

When I connect using the Redis.Cluster constructor:

new Redis.Cluster(['host.redis.cache.windows.net', 6380], {
    scaleReads: 'all',
    slotsRefreshTimeout: 2000,
    redisOptions: {
        password: 'some-secret',
        tls: true as any
    },
});

The error I get is:

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) }

When I connect using a non-cluster Redis connection:

new Redis(6380, 'host.redis.cache.windows.net', { password: 'some-secret' });

The error I get is:

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' }

As you can see it is using TLS on port 6380. Azure provides me with one host+port combination and two different access-keys (primary/seconday) - which I find weird, which access-key should I use? Also I'm not sure if I should be connecting in Cluster mode, but I'd prefer to to gain the benefits of clustering. When I do it appears it tries to find the slots at 127.0.0.1:6380 which is probably not correct.

In Azure's quickstart they connect using node_redis with:

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}});

I was hoping someone here would have come across the same issue and solved it.

Thanks!

Upvotes: 2

Views: 4209

Answers (2)

Shubham Tak
Shubham Tak

Reputation: 1

Below is the correct code to connect with Azure Redis Cluster( cluster mode on ) with NodeJs on TLS port

Download the DigiCert Global Root G2 certificate on your machine from this link: [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);
});

Upvotes: 0

Filidor Wiese
Filidor Wiese

Reputation: 682

Okay I've managed to connect to Azure Redis Cluster using a non-tls connection:

new Redis.Cluster(['host.redis.cache.windows.net', 3679], {
    scaleReads: 'all',
    slotsRefreshTimeout: 2000,
    redisOptions: {
      password: 'some-secret',
    },
})

For some reason connecting to 6380 with TLS enabled does not work.

Upvotes: 1

Related Questions