创建Redis和Node.js带有连接超时监测的高可靠性方法 -ErenYatkin


本文谈论如何创建了一个漂亮的Redis连接处理程序。为微服务找到的最合适的方式。
如果您已经安装了Docker,只需执行以下命令即可运行Redis服务器实例。

docker run -d --name redis_srv -p 6379:6379 redis

如果您不想安装Docker,我们可以简单地使用Redis Labs。打开此链接以创建一个帐户。
请按照以下步骤创建环境:
  • 创建一个空文件夹以工作:

mkdir connect-redis && cd connect-redis

  • 初始化一个Node.js项目,-y将跳过以下形式:

npm init -y

  • 创建index.js:

touch index.js​​​​​​​

  • 如下所示编辑package.json:

{
  "name": "connect-redis",
 
"version": "0.0.0",
 
"private": true,
 
"scripts": {
   
"start": "node index",
  },
 
"dependencies": {},
 
"devDependencies": {}
}

  • 安装依赖项:

npm install --save redis lodash

  • 打开index.js,让我们定义依赖关系和我们的功能:

const redis = require('redis');
const _ = require('lodash');
const clients = {};
let connectionTimeout;
module.exports.init = () => {};
module.exports.getClients = () => {};
module.exports.closeConnections = () => {};

好了,我们定义了函数,让我们填充它们。首先,我们需要创建一个连接实例。我们这样做是因为将来我们可能需要与另一个Redis数据库建立第二个或第三个连接。不要问为什么,一个Redis是不够的,不要忘记用您的参数替换上面连接字符串!

module.exports.init =()=> { 
    const cacheInstance = redis.createClient('redis:// connection-string'); 
    client.cacheInstance = cacheInstance; 
};

我们使用Redis包创建了Redis连接,并将该连接保存在对象中以供以后导入和使用。
某些事件将根据连接状态触发。最好听他们采取行动。因为此模块将管理整个连接流程。我们需要知道任何中断或连接丢失。
让我们看看这些事件是什么:

  • 连接:成功连接后触发
  • 结束:如果连接断开,则触发
  • 重新连接:Redis尝试连接时触发
  • 错误:发生任何错误时触发

现在,我们添加一个事件侦听器,我如下更改了init()函数并添加了处理程序。在开发NodeJs应用程序时,我更喜欢RO-RO(接收对象-返回对象)方法。因为它提高了代码的可读性。

function instanceEventListeners({ conn }) {
    conn.on('connect', () => {
        console.log('CacheStore - Connection status: connected');
    });
    conn.on('end', () => {
        console.log('CacheStore - Connection status: disconnected');
    });
    conn.on('reconnecting', () => {
        console.log('CacheStore - Connection status: reconnecting');
    });
    conn.on('error', (err) => {
        console.log('CacheStore - Connection status: error ', { err });
    });
}
module.exports.init = () => {
    const cacheInstance = redis.createClient('redis://connection-string');
    clients.cacheInstance = cacheInstance;
    instanceEventListeners({ conn: cacheInstance });
};

如上,我们将自己处理重新连接过程。下面的代码简单地添加了一个timeout()。就我而言,我可以忍受很少的连接中断。我的意思是,只要在一定时间内重新连接,就可以断开连接。
让我们添加一下timeout(),看看它如何进行:

function throwTimeoutError() {
    connectionTimeout = setTimeout(() => {
        throw new Error('Redis connection failed');
    }, 10000);
}
function instanceEventListeners({ conn }) {
    conn.on('connect', () => {
        console.log('CacheStore - Connection status: connected');
        clearTimeout(connectionTimeout);
    });
    conn.on('end', () => {
        console.log('CacheStore - Connection status: disconnected');
        throwTimeoutError();
    });
    conn.on('reconnecting', () => {
        console.log('CacheStore - Connection status: reconnecting');
        clearTimeout(connectionTimeout);
    });
    conn.on('error', (err) => {
        console.log('CacheStore - Connection status: error ', { err });
        throwTimeoutError();
    });
}
module.exports.init = () => {
    const cacheInstance = redis.createClient('redis://connection-string');
    clients.cacheInstance = cacheInstance;
    instanceEventListeners({ conn: cacheInstance });
};

让我们分解一下
  • 我们定义connectionTimeoutnull是因为我们想在触发特定事件时开始超时,
  • 当我们收到结束事件时,超时将开始,然后Redis将尝试重新连接。我们将等到超时。setTimeout()将跟踪Redis尝试连接的时间。如果连接再次建立,则需要清除超时,因为我们不想在此之后引发错误。顺便说一下clearTimeout,connectionTimeout设置为null或未定义时不会影响任何内容。

下面看看管理关闭连接的流程和我如何管理打开的流程。因为如果您在Kubernetes中运行您的应用程序,那么正常关闭应用程序始终是最佳实践。

module.exports.closeConnections = () => _.forOwn(clients, (conn) => conn.quit());

forOwn() 会循环对象键,每个连接简单地调用了 quit().
如何使用这个连接呢?

module.exports.getClients = () => clients;

使用这个函数,您可以导入和使用您创建的连接。
 
最后
我们走到了尽头,为自己创建了一个漂亮的Redis连接处理程序。这是我们为微服务找到的最合适的方式。
处理连接状态并了解正在发生的事情将改善您的服务质量。如果您有任何疑问或建议,请随时在评论中告诉我,我随时欢迎您的想法。
如需完整的代码签出代码,