我正试图妥善处理redis错误,以绕过错误并执行其他操作,而不是使我的应用程序崩溃。
但是到目前为止,我不能仅仅捕捉到ioredis引发的异常,该异常绕过了我的try/catch
并终止了当前进程。这种当前行为无法让我正常地处理错误,也无法从替代系统(而不是redis)中获取数据。
import { createLogger } from '@unly/utils-simple-logger';
import Redis from 'ioredis';
import epsagon from './epsagon';
const logger = createLogger({
label: 'Redis client',
});
/**
* Creates a redis client
*
* @param url Url of the redis client, must contain the port number and be of the form "localhost:6379"
* @param password Password of the redis client
* @param maxRetriesPerRequest By default, all pending commands will be flushed with an error every 20 retry attempts.
* That makes sure commands won't wait forever when the connection is down.
* Set to null to disable this behavior, and every command will wait forever until the connection is alive again.
* @return {Redis}
*/
export const getClient = (url = process.env.REDIS_URL, password = process.env.REDIS_PASSWORD, maxRetriesPerRequest = 20) => {
const client = new Redis(`redis://${url}`, {
password,
showFriendlyErrorStack: true, // See https://github.com/luin/ioredis#error-handling
lazyConnect: true, // XXX Don't attempt to connect when initializing the client, in order to properly handle connection failure on a use-case basis
maxRetriesPerRequest,
});
client.on('connect', function () {
logger.info('Connected to redis instance');
});
client.on('ready', function () {
logger.info('Redis instance is ready (data loaded from disk)');
});
// Handles redis connection temporarily going down without app crashing
// If an error is handled here, then redis will attempt to retry the request based on maxRetriesPerRequest
client.on('error', function (e) {
logger.error(`Error connecting to redis: "${e}"`);
epsagon.setError(e);
if (e.message === 'ERR invalid password') {
logger.error(`Fatal error occurred "${e.message}". Stopping server.`);
throw e; // Fatal error, don't attempt to fix
}
});
return client;
};
我正在模拟错误的密码/ URL,以查看错误配置时redis的反应。我已将lazyConnect
设置为true
以便处理呼叫者上的错误。
但是,当我将网址定义为localhoste:6379
(而不是localhost:6379
)时,出现以下错误:
server 2019-08-10T19:44:00.926Z [Redis client] error: Error connecting to redis: "Error: getaddrinfo ENOTFOUND localhoste localhoste:6379"
(x 20)
server 2019-08-10T19:44:11.450Z [Read cache] error: Reached the max retries per request limit (which is 20). Refer to "maxRetriesPerRequest" option for details.
这是我的代码:
// Fetch a potential query result for the given query, if it exists in the cache already
let cachedItem;
try {
cachedItem = await redisClient.get(queryString); // This emit an error on the redis client, because it fails to connect (that's intended, to test the behaviour)
} catch (e) {
logger.error(e); // It never goes there, as the error isn't "thrown", but rather "emitted" and handled by redis its own way
epsagon.setError(e);
}
// If the query is cached, return the results from the cache
if (cachedItem) {
// return item
} else {} // fetch from another endpoint (fallback backup)
我的理解是redis错误是通过client.emit('error', error)
处理的,:) resize.c and bmp.h exist.
:) resize.c compiles.
:) doesn't resize small.bmp when n is 1
:( resizes small.bmp correctly when n is 2
expected 0xae, not 0x5a in header field bfSize
:( resizes small.bmp correctly when n is 3
expected 0x132, not 0x5a in header field bfSize
:( resizes small.bmp correctly when n is 4
expected 0x1e6, not 0x5a in header field bfSize
:( resizes small.bmp correctly when n is 5
expected 0x306, not 0x5a in header field bfSize
:( resizes large.bmp correctly when n is 2
expected 0x6f6, not 0x1e6 in header field bfSize
:( resizes smiley.bmp correctly when n is 2
expected 0x336, not 0xf6 in header field bfSize
:( resizes smiley.bmp correctly when n is 3
expected 0x6f6, not 0xf6 in header field bfSize```
是异步的,被调用方不会抛出错误,这不允许调用方使用try / catch处理错误。
是否应该以非常特殊的方式处理redis错误?像我们通常对大多数错误所做的那样,是否有可能抓住它们?
此外,似乎redis重试20次连接(默认情况下),然后引发致命异常(进程已停止)。但我想处理任何异常并以自己的方式处理。
我已经通过提供错误的连接数据测试了Redis客户端的行为,由于该URL上没有可用的Redis实例,因此无法进行连接,我的目标是最终捕获各种Redis错误并优雅地处理它们。
答案 0 :(得分:2)
客户端import random
import numpy as np
import tensorflow as tf
from keras.optimizers import SGD
network = tf.keras.models.Sequential()
network.add(tf.keras.layers.Flatten())
network.add(tf.keras.layers.Dense(750, activation=tf.nn.relu))
network.add(tf.keras.layers.Dense(500, activation=tf.nn.relu))
network.add(tf.keras.layers.Dense(100, activation=tf.nn.relu))
network.add(tf.keras.layers.Dense(25, activation=tf.nn.softmax))
network.compile(optimizer='SGD',
loss='binary_crossentropy',
metrics=['accuracy'])
network.fit(scaled_x_train, y_train, epochs=100, batch_size=50)
对象上的连接错误are reported as an error
event。
根据"Auto-reconnect" section of the docs,当与Redis的连接丢失(或者可能首先无法建立)时,ioredis将自动尝试重新连接。仅在尝试import random
import numpy as np
from sklearn.preprocessing import MinMaxScaler
x_train = []
y_train = []
for m in range(100000): #creating a data set with m items in it
grid = [[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0]]
hints = [[[],[],[],[],[]],[[],[],[],[],[]]]
for i in range(5):
for j in range(5):
grid[i][j] = random.randint(0,1) #All items in the grid are random, either 0s or 1s
sub_y_train = []
for z in range(5):
for x in range(5):
sub_y_train.append(grid[z][x])
sub_y_train = np.array(sub_y_train)
y_train.append(sub_y_train) #the grids are added to the data set first
##figuring out the hints along the vertical axis
for i in range(5):
counter = 0
for j in range(4):
if grid[i][j] == 1:
counter += 1
if grid[i][j+1] == 0:
hints[0][i].append(counter)
counter = 0
if grid[i][4] == 1:
hints[0][i].append(counter+1)
counter = 0
##figuring out the hints along the horizontal axis
for i in range(5):
counter = 0
for j in range(4):
if grid[j][i] == 1:
counter += 1
if grid[j+1][i] == 0:
hints[1][i].append(counter)
counter = 0
if grid[4][i] == 1:
hints[1][i].append(counter+1)
counter = 0
for i in range(2):
for j in range(5):
while len(hints[i][j]) != 3:
hints[i][j].append(0)
new_hints = []
for i in range(2):
for j in range(5):
for k in range(3):
new_hints.append(hints[i][j][k])
new_hints.append(5)
x_train.append(new_hints) #Once the hints are created and formalized, they are added to x_train
x_train = np.array(x_train) #Both x_train and y_train are converted into numpy arrays
y_train = np.array(y_train)
scaler = MinMaxScaler(feature_range=(0,1))
scaled_x_train = scaler.fit_transform((x_train))
for i in range(5):
print(scaled_x_train[i])
print(y_train[i])
之后,才会“挂起有错误的命令”,即在此处进入Redis
:
maxRetriesPerRequest
由于您在遇到第一个错误时停止了程序:
catch
...重试以及随后的“出错刷新”都没有机会运行。
忽略 try {
cachedItem = await redisClient.get(queryString); // This emit an error on the redis client, because it fails to connect (that's intended, to test the behaviour)
} catch (e) {
logger.error(e); // It never goes there, as the error isn't "thrown", but rather "emitted" and handled by redis its own way
epsagon.setError(e);
}
中的错误,您应该得到 client.on('error', function (e) {
// ...
if (e.message === 'ERR invalid password') {
logger.error(`Fatal error occurred "${e.message}". Stopping server.`);
throw e; // Fatal error, don't attempt to fix
返回的错误。
答案 1 :(得分:2)
这是我的团队在TypeScript项目中对IORedis所做的工作:
let redis;
const redisConfig: Redis.RedisOptions = {
port: parseInt(process.env.REDIS_PORT, 10),
host: process.env.REDIS_HOST,
autoResubscribe: false,
lazyConnect: true,
maxRetriesPerRequest: 0, // <-- this seems to prevent retries and allow for try/catch
};
try {
redis = new Redis(redisConfig);
const infoString = await redis.info();
console.log(infoString)
} catch (err) {
console.log(chalk.red('Redis Connection Failure '.padEnd(80, 'X')));
console.log(err);
console.log(chalk.red(' Redis Connection Failure'.padStart(80, 'X')));
// do nothing
} finally {
await redis.disconnect();
}