Node-Redis:就绪检查失败 - 需要 NOAUTH 身份验证

Node-Redis: ready check failed - NOAUTH Authentication required

我有一个奇怪的 redis 行为:

const redis = require('redis');
const { REDIS_URL: redisUrl, REDIS_PASSWORD: redisPassword } = process.env;

const client = redis.createClient(redisUrl, {
  no_ready_check: true,
  auth_pass: redisPassword
});

client.on('connect', () => {
  redisPassword && client.auth(redisPassword);
});

client.on('error', err => {
  global.console.log(err.message)
});

但我一直收到以下错误:

throw er; // Unhandled 'error' event

ReplyError: Ready check failed: NOAUTH Authentication required.

为什么未处理?我 设置 错误处理程序
为什么 Ready 检查失败?我在选项中禁用

我不确定为什么您的代码会抛出此错误。但是我在我的本地机器上尝试了这段代码,它运行良好。

const redis = require('redis');
const redisPassword = "password" ; 
const client = redis.createClient({
          host : '127.0.0.1',  
          no_ready_check: true,
          auth_pass: redisPassword,                                                                                                                                                           
});                               
                                  
client.on('connect', () => {   
          global.console.log("connected");
});                               
                                  
client.on('error', err => {       
          global.console.log(err.message)
});                               
                                  
client.set("foo", 'bar');         
                                  
client.get("foo", function (err, reply) {
        global.console.log(reply.toString())
})

和运行节点client.js将输出:

connected

bar

NOAUTH required Authentication required 是redis process command的时候,发现客户端没有认证,所以投诉了。

我猜可能是你给createClient的redisUrl有问题,调试一下或者换成我的代码方式试试。希望你能解决它。

还有一件事:client.auth(redisPassword) 不是必需的,因为如果您设置 auth_pass 或密码选项,redis 客户端将在任何命令之前自动向服务器发送 auth 命令。

如果您将 redis uri 保存为字符串。您需要将其分解为对象。对于 ioredis 你可以使用函数

export function decomposeRedisUrl(url) {
  const [[, , password, host, port]] = [...(url.matchAll(/redis:\/\/(([^@]*)@)?(.*?):(\d*)/g))];
  return { password, host, port };
}

此功能有测试:

it("redis url should be decomposed correctly with password", () => {
  expect(decomposeRedisUrl("redis://pass@host.com:9183")).to.eql({
    password: "pass",
    host: "host.com",
    port: "9183",
  });
});

it("redis url should be decomposed correctly without password", () => {
  expect(decomposeRedisUrl("redis://localhost:6379")).to.eql({
    password: undefined,
    host: "localhost",
    port: "6379",
  });
});

和用法

import Redis from "ioredis";

async function getKeysFromRedisUrl(url) {
  const rc = new Redis(decomposeRedisUrl(url));
  const keys = await rc.keys("*");
  rc.disconnect();
  return keys;
}

describe("Redis can connect", () => {
  it("with cloud", async () => {
    expect(await getKeysFromRedisUrl("redis://pass@host.com:9183")).to.be.an("array");
  });
  it("with local redis instance", async () => {
    expect(await getKeysFromRedisUrl("redis://localhost:6379")).to.be.an("array");
  });
});
  • 此函数不处理用户名