Содержание
- Redis client handling
- Accepting Client Connections
- What Order are Client Requests Served In?
- Maximum Concurrent Connected Clients
- Output Buffer Limits
- Query Buffer Hard Limit
- Client Eviction
- Client Timeouts
- The CLIENT Command
- TCP keepalive
- On This Page
- Error passed to callbacks is not an instance of «Error» class on connection refused #374
- Comments
Redis client handling
How the Redis server manages client connections
This document provides information about how Redis handles clients at the network layer level: connections, timeouts, buffers, and other similar topics are covered here.
The information contained in this document is only applicable to Redis version 2.6 or greater.
Accepting Client Connections
Redis accepts clients connections on the configured TCP port and on the Unix socket if enabled. When a new client connection is accepted the following operations are performed:
- The client socket is put in the non-blocking state since Redis uses multiplexing and non-blocking I/O.
- The TCP_NODELAY option is set in order to ensure that there are no delays to the connection.
- A readable file event is created so that Redis is able to collect the client queries as soon as new data is available to read on the socket.
After the client is initialized, Redis checks if it is already at the limit configured for the number of simultaneous clients (configured using the maxclients configuration directive, see the next section of this document for further information).
When Redis can’t accept a new client connection because the maximum number of clients has been reached, it tries to send an error to the client in order to make it aware of this condition, closing the connection immediately. The error message will reach the client even if the connection is closed immediately by Redis because the new socket output buffer is usually big enough to contain the error, so the kernel will handle transmission of the error.
What Order are Client Requests Served In?
The order is determined by a combination of the client socket file descriptor number and order in which the kernel reports events, so the order should be considered as unspecified.
However, Redis does the following two things when serving clients:
- It only performs a single read() system call every time there is something new to read from the client socket. This ensures that if we have multiple clients connected, and a few send queries at a high rate, other clients are not penalized and will not experience latency issues.
- However once new data is read from a client, all the queries contained in the current buffers are processed sequentially. This improves locality and does not need iterating a second time to see if there are clients that need some processing time.
Maximum Concurrent Connected Clients
In Redis 2.4 there was a hard-coded limit for the maximum number of clients that could be handled simultaneously.
In Redis 2.6 and newer, this limit is dynamic: by default it is set to 10000 clients, unless otherwise stated by the maxclients directive in redis.conf .
However, Redis checks with the kernel what the maximum number of file descriptors that we are able to open is (the soft limit is checked). If the limit is less than the maximum number of clients we want to handle, plus 32 (that is the number of file descriptors Redis reserves for internal uses), then the maximum number of clients is updated to match the number of clients it is really able to handle under the current operating system limit.
When maxclients is set to a number greater than Redis can support, a message is logged at startup:
When Redis is configured in order to handle a specific number of clients it is a good idea to make sure that the operating system limit for the maximum number of file descriptors per process is also set accordingly.
Under Linux these limits can be set both in the current session and as a system-wide setting with the following commands:
- ulimit -Sn 100000 # This will only work if hard limit is big enough.
- sysctl -w fs.file-max=100000
Output Buffer Limits
Redis needs to handle a variable-length output buffer for every client, since a command can produce a large amount of data that needs to be transferred to the client.
However it is possible that a client sends more commands producing more output to serve at a faster rate than that which Redis can send the existing output to the client. This is especially true with Pub/Sub clients in case a client is not able to process new messages fast enough.
Both conditions will cause the client output buffer to grow and consume more and more memory. For this reason by default Redis sets limits to the output buffer size for different kind of clients. When the limit is reached the client connection is closed and the event logged in the Redis log file.
There are two kind of limits Redis uses:
- The hard limit is a fixed limit that when reached will make Redis close the client connection as soon as possible.
- The soft limit instead is a limit that depends on the time, for instance a soft limit of 32 megabytes per 10 seconds means that if the client has an output buffer bigger than 32 megabytes for, continuously, 10 seconds, the connection gets closed.
Different kind of clients have different default limits:
- Normal clients have a default limit of 0, that means, no limit at all, because most normal clients use blocking implementations sending a single command and waiting for the reply to be completely read before sending the next command, so it is always not desirable to close the connection in case of a normal client.
- Pub/Sub clients have a default hard limit of 32 megabytes and a soft limit of 8 megabytes per 60 seconds.
- Replicas have a default hard limit of 256 megabytes and a soft limit of 64 megabyte per 60 seconds.
It is possible to change the limit at runtime using the CONFIG SET command or in a permanent way using the Redis configuration file redis.conf . See the example redis.conf in the Redis distribution for more information about how to set the limit.
Query Buffer Hard Limit
Every client is also subject to a query buffer limit. This is a non-configurable hard limit that will close the connection when the client query buffer (that is the buffer we use to accumulate commands from the client) reaches 1 GB, and is actually only an extreme limit to avoid a server crash in case of client or server software bugs.
Client Eviction
Redis is built to handle a very large number of client connections. Client connections tend to consume memory, and when there are many of them, the aggregate memory consumption can be extremely high, leading to data eviction or out-of-memory errors. These cases can be mitigated to an extent using output buffer limits, but Redis allows us a more robust configuration to limit the aggregate memory used by all clients’ connections.
This mechanism is called client eviction, and it’s essentially a safety mechanism that will disconnect clients once the aggregate memory usage of all clients is above a threshold. The mechanism first attempts to disconnect clients that use the most memory. It disconnects the minimal number of clients needed to return below the maxmemory-clients threshold.
maxmemory-clients defines the maximum aggregate memory usage of all clients connected to Redis. The aggregation takes into account all the memory used by the client connections: the query buffer, the output buffer, and other intermediate buffers.
Note that replica and master connections aren’t affected by the client eviction mechanism. Therefore, such connections are never evicted.
maxmemory-clients can be set permanently in the configuration file ( redis.conf ) or via the CONFIG SET command. This setting can either be 0 (meaning no limit), a size in bytes (possibly with mb / gb suffix), or a percentage of maxmemory by using the % suffix (e.g. setting it to 10% would mean 10% of the maxmemory configuration).
The default setting is 0, meaning client eviction is turned off by default. However, for any large production deployment, it is highly recommended to configure some non-zero maxmemory-clients value. A value 5% , for example, can be a good place to start.
It is possible to flag a specific client connection to be excluded from the client eviction mechanism. This is useful for control path connections. If, for example, you have an application that monitors the server via the INFO command and alerts you in case of a problem, you might want to make sure this connection isn’t evicted. You can do so using the following command (from the relevant client’s connection):
And you can revert that with:
For more information and an example refer to the maxmemory-clients section in the default redis.conf file.
Client eviction is available from Redis 7.0.
Client Timeouts
By default recent versions of Redis don’t close the connection with the client if the client is idle for many seconds: the connection will remain open forever.
However if you don’t like this behavior, you can configure a timeout, so that if the client is idle for more than the specified number of seconds, the client connection will be closed.
You can configure this limit via redis.conf or simply using CONFIG SET timeout .
Note that the timeout only applies to normal clients and it does not apply to Pub/Sub clients, since a Pub/Sub connection is a push style connection so a client that is idle is the norm.
Even if by default connections are not subject to timeout, there are two conditions when it makes sense to set a timeout:
- Mission critical applications where a bug in the client software may saturate the Redis server with idle connections, causing service disruption.
- As a debugging mechanism in order to be able to connect with the server if a bug in the client software saturates the server with idle connections, making it impossible to interact with the server.
Timeouts are not to be considered very precise: Redis avoids setting timer events or running O(N) algorithms in order to check idle clients, so the check is performed incrementally from time to time. This means that it is possible that while the timeout is set to 10 seconds, the client connection will be closed, for instance, after 12 seconds if many clients are connected at the same time.
The CLIENT Command
The Redis CLIENT command allows you to inspect the state of every connected client, to kill a specific client, and to name connections. It is a very powerful debugging tool if you use Redis at scale.
CLIENT LIST is used in order to obtain a list of connected clients and their state:
In the above example two clients are connected to the Redis server. Let’s look at what some of the data returned represents:
- addr: The client address, that is, the client IP and the remote port number it used to connect with the Redis server.
- fd: The client socket file descriptor number.
- name: The client name as set by CLIENT SETNAME .
- age: The number of seconds the connection existed for.
- idle: The number of seconds the connection is idle.
- flags: The kind of client (N means normal client, check the full list of flags).
- omem: The amount of memory used by the client for the output buffer.
- cmd: The last executed command.
See the [ CLIENT LIST ](https://redis.io/commands/client-list) documentation for the full listing of fields and their purpose.
Once you have the list of clients, you can close a client’s connection using the CLIENT KILL command, specifying the client address as its argument.
The commands CLIENT SETNAME and CLIENT GETNAME can be used to set and get the connection name. Starting with Redis 4.0, the client name is shown in the SLOWLOG output, to help identify clients that create latency issues.
TCP keepalive
From version 3.2 onwards, Redis has TCP keepalive ( SO_KEEPALIVE socket option) enabled by default and set to about 300 seconds. This option is useful in order to detect dead peers (clients that cannot be reached even if they look connected). Moreover, if there is network equipment between clients and servers that need to see some traffic in order to take the connection open, the option will prevent unexpected connection closed events.
On This Page
This is a community website sponsored by Redis Ltd. © 2023. Redis and the cube logo are registered trademarks of Redis Ltd. Terms of use & privacy policy.
Источник
Error passed to callbacks is not an instance of «Error» class on connection refused #374
When redis connection is refused the client callback is invoked with something that is not an instance of Error. This has been tested with 0.7.1, dunno if it changed lately (but I saw no sign of that in the changelog.md)
The text was updated successfully, but these errors were encountered:
Hey, changelog.md is not reliable anymore; might want to check again with whatever version of redis you use now.
Also, there is a PR in progress that involves its own type of Error, you might have something to say about that (see #361)
I don’t think this one is related to #361 necessarily. It would be great if you could provide an example, or better a test to illustrate the issue.
I tried but cannot confirm my report. Closing. Will re-open if I’ve something that can be demonstrated. Sorry for the noise.
Ok, I succeeded in reproducing this. It’s an error passed as first argument to a callback to .keys (in this test) when the connection wasn’t successful:
http://strk.keybit.net/tmp/test374.js
I haven’t tried more commands but I suspect any command passed to a «bad» connection (be it still unconnected or otherwise broken [ socket hangup? ]) would result in such non-Error argument.
Writing the test inline, as it’s more likely to remain stable:
@brycebaril did you try the test ?
This test definitely works to illustrate the problem. I’ll look into a solution.
Actually this test is no good — it’s a trick because the port of 0000 is ignored due to this line:
In this case the keys command succeeds and the test fails because err is expected to be null, because there is no error.
In my case err is non-null, and an exception is thrown.
Code:
Things don’t change if I set a more likely port:
The docs recommend you attach a on error handler to the redis client
itself. Not sure if this would change the behavior however.
Sent via phone—please excuse typos and brevity
On Mar 11, 2013 5:26 AM, «strk» notifications@github.com wrote:
In my case err is non-null, and an exception is thrown.
Code:
var Redis = require(‘./index’);
var PORT = 0000;
var HOST = ‘127.0.0.1’;
var client = Redis.createClient(PORT, HOST);
client.keys(«*», function(err, data) <
if (err instanceof Error) console.log(«Proper Error: » + err);
else console.log(«non-Error passed to ‘error’ event: » + err);
>);
non-Error passed to ‘error’ event: Redis connection to 127.0.0.1:6379 failed — connect ECONNREFUSED
events.js:71
throw arguments[1]; // Unhandled ‘error’ event
^
Error: Redis connection to 127.0.0.1:6379 failed — connect ECONNREFUSED
at RedisClient.on_error (/home/src/node/modules/node_redis/index.js:148:24)
at Socket. (/home/src/node/modules/node_redis/index.js:83:14)
at Socket.EventEmitter.emit (events.js:96:17)
at Socket._destroy.self.errorEmitted (net.js:329:14)
at process.startup.processNextTick.process._tickCallback (node.js:244:9)
Things don’t change if I set a more likely port:
non-Error passed to ‘error’ event: Redis connection to 127.0.0.1:6666 failed — connect ECONNREFUSED
Источник
Some errors still not handled by: client.on('error', function(err){});
Ex:
var redis = require('redis'); var redisClient = redis.createClient(port, host); redisClient.on('connect', function(){ console.log('Connected to Redis'); }); redisClient.on('error', function(err) { console.log('Redis error: ' + err); }); app.use(session({ store: new RedisStore({ client: redisClient }), secret: '***', resave: false, saveUninitialized: true, cookie: { secure: false }, name: '***' + app.get('env') }));
Cause:
[11:48:37.809] [LOG] Error: MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
at Error (native)
at HiredisReplyParser.execute (/Users/bushev/IdeaProjects/org/app/node_modules/redis/lib/parser/hiredis.js:30:33)
at RedisClient.on_data (/Users/bushev/IdeaProjects/org/app/node_modules/redis/index.js:549:27)
at Socket.<anonymous> (/Users/bushev/IdeaProjects/org/app/node_modules/redis/index.js:102:14)
at emitOne (events.js:77:13)
at Socket.emit (events.js:169:7)
at readableAddChunk (_stream_readable.js:146:16)
at Socket.Readable.push (_stream_readable.js:110:10)
at TCP.onread (net.js:523:20)
How can I handle the Redis connection error gracefully in nodejs? I would like to return data from database not only when the redis cache is missed but even when the redis server is not connected. The main use case is that I would like to switch on the Redis server only during the peak hours and switch off during off-peak hours. Even with redis server off, I would like my nodejs application running without exiting.
I am trying to setup a file with redis connection so that other modules can import and can use the connections. Following codes are using ioredis (4.19.4) but I also tried with node-redis (3.0.2) and similar result too.
#redis_connection.js
const redis = require("ioredis");
const client = new redis.createClient("redisurl", {
connectTimeout: 2000,
lazyConnect: true,
maxRetriesPerRequest: 2,
reconnectOnError: function(err) {
return false
},
retryStrategy: function(times) {
return null
}
});
client
.on('error', (e) => {
console.log('Redis error >', e)
});
module.exports = {
client,
}
Then, in my other modules, I am importing as following and use in some of my express functions.
import { client } from './redis_connection.js';
const getRealData = async () => {
let article_data = null;
try {
client.get("key", function(err, data) {
if (err) {
console.log("ERR IN TRY");
console.error(err)
} else {
article_data = data;
}
});
} catch (error) {
console.log("CATCH");
console.log(error);
}
if (article_data) {
return article_data
} else {
// get the data from database
return data_from_database
}
}
When I run my application with invalid redis URL, the Redis error > is shown. Hence, the listener is working. Then, ERR IN TRY is shown. So far so good.
Then, the nodejs application exit with following error:
events.js:287
throw er; // Unhandled 'error' event
^
Error: Redis connection to connection_url:6379 failed - connect ETIMEDOUT xx.xx.x.x:6379
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1141:16)
Emitted 'error' event on RedisClient instance at:
at RedisClient.on_error (/Users/aungmt/project/node_modules/redis/index.js:341:14)
at Socket.<anonymous> (/Users/aungmt/project/node_modules/redis/index.js:222:14)
at Socket.emit (events.js:310:20)
at Socket.EventEmitter.emit (domain.js:482:12)
at emitErrorNT (internal/streams/destroy.js:92:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
errno: 'ETIMEDOUT',
code: 'ETIMEDOUT',
syscall: 'connect',
address: 'xx.xx.x.x',
port: 6379
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! project@1.0.0 start: `node server.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the project@1.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
Update
Since I was trying with both ioredis and node-redis, look like it is conflicting. I uninstalled both and installed only ioredis. Now the nodejs application won’t exit. However, ioredis keeps trying to reconnect as following although I tried with configs AND tried calling disconnect() manually. Thanks.
[ioredis] Unhandled error event: Error: connect ETIMEDOUT
at Socket.<anonymous> (/Users/aungmt/project/node_modules/ioredis/built/redis/index.js:308:37)
at Object.onceWrapper (events.js:416:28)
at Socket.emit (events.js:310:20)
at Socket.EventEmitter.emit (domain.js:482:12)
at Socket._onTimeout (net.js:479:8)
at listOnTimeout (internal/timers.js:549:17)
at processTimers (internal/timers.js:492:7)
[ioredis] Unhandled error event: Error: connect ETIMEDOUT
at Socket.<anonymous> (/Users/aungmt/project/node_modules/ioredis/built/redis/index.js:308:37)
at Object.onceWrapper (events.js:416:28)
at Socket.emit (events.js:310:20)
at Socket.EventEmitter.emit (domain.js:482:12)
at Socket._onTimeout (net.js:479:8)
at listOnTimeout (internal/timers.js:549:17)
at processTimers (internal/timers.js:492:7)
Environment:
- Node.js Version: v17.6.0
- Redis Server Version: Redis server v=6.2.6 sha=00000000:0 malloc=libc bits=64 build=c6f3693d1aced7d9
- Node Redis Version: 4.0.4
- Platform: mac
i open a redis connection from l
const client = createClient({ url: envVars.REDIS_URL, retry_strategy: (options) => { if (error?.code === 'ECONNREFUSED' || error?.code === 'NR_CLOSED' || error?.code === '??') { console.error(error.code); // take actions or throw exception console.error('The server refused the connection. Retrying connection...'); return 5000; } // [...]
and later the connection is made somewhat lazy:
if (!queueClient.isOpen) { await queueClient.connect(); console.info('connected to redis at', envVars.REDIS_URL); }
(BTW it’s sveletekit app, and isOpen is in the hooks.js…)
It works if the app is started with or without a running redis server.
if redis is started after the app it reconnects fine (on the next try).
if i stop redis while the app is running, the app crashes with this error:
node:events:505
throw er; // Unhandled 'error' event
^
SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> ([...]/node_modules/.pnpm/@node-redis+client@1.0.4/node_modules/@node-redis/client/dist/lib/client/socket.js:182:118)
at Object.onceWrapper (node:events:642:26)
at Socket.emit (node:events:527:28)
at TCP.<anonymous> (node:net:688:12)
Emitted 'error' event on Commander instance at:
at RedisSocket.<anonymous> ([...]node_modules/.pnpm/@node-redis+client@1.0.4/node_modules/@node-redis/client/dist/lib/client/index.js:339:14)
at RedisSocket.emit (node:events:527:28)
at RedisSocket._RedisSocket_onSocketError (/[...]node_modules/.pnpm/@node-redis+client@1.0.4/node_modules/@node-redis/client/dist/lib/client/socket.js:205:10)
at Socket.<anonymous> (/[...]node_modules/.pnpm/@node-redis+client@1.0.4/node_modules/@node-redis/client/dist/lib/client/socket.js:182:107)
at Object.onceWrapper (node:events:642:26)
at Socket.emit (node:events:527:28)
at TCP.<anonymous> (node:net:688:12)
I have an on error handler, see above, still the error states there is none.
As #1559 there could be an other client without an error handler,
but redis is only used in one place in may code …
where should that missing handler be?
How the Redis server manages client connections
This document provides information about how Redis handles clients at the network layer level: connections, timeouts, buffers, and other similar topics are covered here.
The information contained in this document is only applicable to Redis version 2.6 or greater.
Accepting Client Connections
Redis accepts clients connections on the configured TCP port and on the Unix socket if enabled. When a new client connection is accepted the following operations are performed:
- The client socket is put in the non-blocking state since Redis uses multiplexing and non-blocking I/O.
- The
TCP_NODELAYoption is set in order to ensure that there are no delays to the connection. - A readable file event is created so that Redis is able to collect the client queries as soon as new data is available to read on the socket.
After the client is initialized, Redis checks if it is already at the limit
configured for the number of simultaneous clients (configured using the maxclients configuration directive, see the next section of this document for further information).
When Redis can’t accept a new client connection because the maximum number of clients
has been reached, it tries to send an error to the client in order to
make it aware of this condition, closing the connection immediately.
The error message will reach the client even if the connection is
closed immediately by Redis because the new socket output buffer is usually
big enough to contain the error, so the kernel will handle transmission
of the error.
What Order are Client Requests Served In?
The order is determined by a combination of the client socket file descriptor
number and order in which the kernel reports events, so the order should be
considered as unspecified.
However, Redis does the following two things when serving clients:
- It only performs a single
read()system call every time there is something new to read from the client socket. This ensures that if we have multiple clients connected, and a few send queries at a high rate, other clients are not penalized and will not experience latency issues. - However once new data is read from a client, all the queries contained in the current buffers are processed sequentially. This improves locality and does not need iterating a second time to see if there are clients that need some processing time.
Maximum Concurrent Connected Clients
In Redis 2.4 there was a hard-coded limit for the maximum number of clients
that could be handled simultaneously.
In Redis 2.6 and newer, this limit is dynamic: by default it is set to 10000 clients, unless
otherwise stated by the maxclients directive in redis.conf.
However, Redis checks with the kernel what the maximum number of file
descriptors that we are able to open is (the soft limit is checked). If the
limit is less than the maximum number of clients we want to handle, plus
32 (that is the number of file descriptors Redis reserves for internal uses),
then the maximum number of clients is updated to match the number
of clients it is really able to handle under the current operating system
limit.
When maxclients is set to a number greater than Redis can support, a message is logged at startup:
$ ./redis-server --maxclients 100000
[41422] 23 Jan 11:28:33.179 # Unable to set the max number of files limit to 100032 (Invalid argument), setting the max clients configuration to 10112.
When Redis is configured in order to handle a specific number of clients it
is a good idea to make sure that the operating system limit for the maximum
number of file descriptors per process is also set accordingly.
Under Linux these limits can be set both in the current session and as a
system-wide setting with the following commands:
ulimit -Sn 100000 # This will only work if hard limit is big enough.sysctl -w fs.file-max=100000
Output Buffer Limits
Redis needs to handle a variable-length output buffer for every client, since
a command can produce a large amount of data that needs to be transferred to the
client.
However it is possible that a client sends more commands producing more output
to serve at a faster rate than that which Redis can send the existing output to the
client. This is especially true with Pub/Sub clients in case a client is not
able to process new messages fast enough.
Both conditions will cause the client output buffer to grow and consume
more and more memory. For this reason by default Redis sets limits to the
output buffer size for different kind of clients. When the limit is reached
the client connection is closed and the event logged in the Redis log file.
There are two kind of limits Redis uses:
- The hard limit is a fixed limit that when reached will make Redis close the client connection as soon as possible.
- The soft limit instead is a limit that depends on the time, for instance a soft limit of 32 megabytes per 10 seconds means that if the client has an output buffer bigger than 32 megabytes for, continuously, 10 seconds, the connection gets closed.
Different kind of clients have different default limits:
- Normal clients have a default limit of 0, that means, no limit at all, because most normal clients use blocking implementations sending a single command and waiting for the reply to be completely read before sending the next command, so it is always not desirable to close the connection in case of a normal client.
- Pub/Sub clients have a default hard limit of 32 megabytes and a soft limit of 8 megabytes per 60 seconds.
- Replicas have a default hard limit of 256 megabytes and a soft limit of 64 megabyte per 60 seconds.
It is possible to change the limit at runtime using the CONFIG SET command or in a permanent way using the Redis configuration file redis.conf. See the example redis.conf in the Redis distribution for more information about how to set the limit.
Query Buffer Hard Limit
Every client is also subject to a query buffer limit. This is a non-configurable hard limit that will close the connection when the client query buffer (that is the buffer we use to accumulate commands from the client) reaches 1 GB, and is actually only an extreme limit to avoid a server crash in case of client or server software bugs.
Client Eviction
Redis is built to handle a very large number of client connections.
Client connections tend to consume memory, and when there are many of them, the aggregate memory consumption can be extremely high, leading to data eviction or out-of-memory errors.
These cases can be mitigated to an extent using output buffer limits, but Redis allows us a more robust configuration to limit the aggregate memory used by all clients’ connections.
This mechanism is called client eviction, and it’s essentially a safety mechanism that will disconnect clients once the aggregate memory usage of all clients is above a threshold.
The mechanism first attempts to disconnect clients that use the most memory.
It disconnects the minimal number of clients needed to return below the maxmemory-clients threshold.
maxmemory-clients defines the maximum aggregate memory usage of all clients connected to Redis.
The aggregation takes into account all the memory used by the client connections: the query buffer, the output buffer, and other intermediate buffers.
Note that replica and master connections aren’t affected by the client eviction mechanism. Therefore, such connections are never evicted.
maxmemory-clients can be set permanently in the configuration file (redis.conf) or via the CONFIG SET command.
This setting can either be 0 (meaning no limit), a size in bytes (possibly with mb/gb suffix),
or a percentage of maxmemory by using the % suffix (e.g. setting it to 10% would mean 10% of the maxmemory configuration).
The default setting is 0, meaning client eviction is turned off by default.
However, for any large production deployment, it is highly recommended to configure some non-zero maxmemory-clients value.
A value 5%, for example, can be a good place to start.
It is possible to flag a specific client connection to be excluded from the client eviction mechanism.
This is useful for control path connections.
If, for example, you have an application that monitors the server via the INFO command and alerts you in case of a problem, you might want to make sure this connection isn’t evicted.
You can do so using the following command (from the relevant client’s connection):
CLIENT NO-EVICT on
And you can revert that with:
CLIENT NO-EVICT off
For more information and an example refer to the maxmemory-clients section in the default redis.conf file.
Client eviction is available from Redis 7.0.
Client Timeouts
By default recent versions of Redis don’t close the connection with the client
if the client is idle for many seconds: the connection will remain open forever.
However if you don’t like this behavior, you can configure a timeout, so that
if the client is idle for more than the specified number of seconds, the client connection will be closed.
You can configure this limit via redis.conf or simply using CONFIG SET timeout <value>.
Note that the timeout only applies to normal clients and it does not apply to Pub/Sub clients, since a Pub/Sub connection is a push style connection so a client that is idle is the norm.
Even if by default connections are not subject to timeout, there are two conditions when it makes sense to set a timeout:
- Mission critical applications where a bug in the client software may saturate the Redis server with idle connections, causing service disruption.
- As a debugging mechanism in order to be able to connect with the server if a bug in the client software saturates the server with idle connections, making it impossible to interact with the server.
Timeouts are not to be considered very precise: Redis avoids setting timer events or running O(N) algorithms in order to check idle clients, so the check is performed incrementally from time to time. This means that it is possible that while the timeout is set to 10 seconds, the client connection will be closed, for instance, after 12 seconds if many clients are connected at the same time.
The CLIENT Command
The Redis CLIENT command allows you to inspect the state of every connected client, to kill a specific client, and to name connections. It is a very powerful debugging tool if you use Redis at scale.
CLIENT LIST is used in order to obtain a list of connected clients and their state:
redis 127.0.0.1:6379> client list
addr=127.0.0.1:52555 fd=5 name= age=855 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client
addr=127.0.0.1:52787 fd=6 name= age=6 idle=5 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping
In the above example two clients are connected to the Redis server. Let’s look at what some of the data returned represents:
- addr: The client address, that is, the client IP and the remote port number it used to connect with the Redis server.
- fd: The client socket file descriptor number.
- name: The client name as set by
CLIENT SETNAME. - age: The number of seconds the connection existed for.
- idle: The number of seconds the connection is idle.
- flags: The kind of client (N means normal client, check the full list of flags).
- omem: The amount of memory used by the client for the output buffer.
- cmd: The last executed command.
See the [CLIENT LIST](https://redis.io/commands/client-list) documentation for the full listing of fields and their purpose.
Once you have the list of clients, you can close a client’s connection using the CLIENT KILL command, specifying the client address as its argument.
The commands CLIENT SETNAME and CLIENT GETNAME can be used to set and get the connection name. Starting with Redis 4.0, the client name is shown in the
SLOWLOG output, to help identify clients that create latency issues.
TCP keepalive
From version 3.2 onwards, Redis has TCP keepalive (SO_KEEPALIVE socket option) enabled by default and set to about 300 seconds. This option is useful in order to detect dead peers (clients that cannot be reached even if they look connected). Moreover, if there is network equipment between clients and servers that need to see some traffic in order to take the connection open, the option will prevent unexpected connection closed events.
how can I handle error event in connect-redis? #11
Comments
vlapan commented Jan 2, 2011
how can I handle error event in connect-redis?
from node-redis readme:
«client will emit error when encountering an error connecting to the Redis server. Note that «error» is a special event type in node. If there are no listeners for an «error» event, node will exit.»
The text was updated successfully, but these errors were encountered:
tj commented Jan 2, 2011
if you named the instance «store»:
store.client.on(‘error’, function(err)<>);
vlapan commented Jan 2, 2011
ghost commented Jan 8, 2012
If I am trying to capture an event within my express app when a different redis server (which is the current session store) becomes unreachable for any reason. I’ve tried store.client.on(‘error’, function(err)<>); but store is undefined.
I have
app.use(express.session());
I tried app.store.on(«error», function(err)<>); can I get cannot call method on.
bushev commented Feb 4, 2016
Some errors still not handled by: client.on(‘error’, function(err)<>);
Footer
© 2023 GitHub, Inc.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Источник
Redis ( node-redis ) — Unhandled ‘error’ event #1559
Comments
kernellpanic commented Jan 27, 2021 •
CLIENT: 3.0.2
REDIS: 5.0.3
- Running within GCLOUD RUN ( Docker / node:14.15.4-alpine3.12 )
- Latency
10ms
‘, client.name, client.index ); console.error( error ); > else < if( __.DEBUG )< console.log( ‘n
LOG
TEST WITH SIMPLE SOCKETS
I did a test to make sure nothing is wrong with the network or with the server.
I created a simple PING with native sockets. The App worked just fine without node-redis
Unfortunately I can’t replicate the error in my dev machine. So maybe something is really happening on my production environment. But I think that whatever the error is I should be able to handle it. This error keeps killing my app.
The text was updated successfully, but these errors were encountered:
Источник
Crashes upon failing to connect to Redis even though Redis isn’t configured #1516
Comments
Hedova928 commented Dec 26, 2020
Commit #1390 seems to have added some functionality that expects a Redis server to be available by default.
The text was updated successfully, but these errors were encountered:
msakallah commented Dec 26, 2020
I also have received an error, and once I reverted back the redis change #1390, I was able to run the project without any errors (see screenshot beow)
imtn commented Dec 26, 2020
I also receive this error, and if I also revert back the redis change mentioned earlier, then it runs fine again.
gigi2006 commented Dec 26, 2020 •
I also receive this error, and if I also revert back the redis change mentioned earlier, then it runs fine again.
can you explain how you discarded the redis change?
//edit2: Maybe next time i must read better 🙂
I have Not read that i must this Here to Put in the dotenv
REDIS_URL=»redis://localhost:6379/1″
But @jef and @BaileyMillerSSI you have forgot to Put example in the dotenv-example
gianmarcotoso commented Dec 26, 2020 •
The issue is due to the Redis client being initialized within the module scope, while it should be initialized separately and only on-demand. You can hotfix this by changing the first few lines of the notification/redis.ts file to this:
(where //. means that you should leave the rest of the code before/after the comment as is). This is not the most elegant solution but I haven’t delved into the codebase deep enough to see if there is an init method, an IoC container or something else where to initialize the Redis client «properly» 🙂
Edit: I’ve added a check to terminate immediately if the Redis client URL is not set or empty, again this can probably be done better, I’ve just pasted a quick fix!
Источник
Receiving «Unhandled error event» with error handler #1386
Comments
didomenicom commented Jul 16, 2021
In a similar situation as described in #896 and #969, I am receiving the following error.
My code looks like this
From what I can tell, this function has no event listeners defined (count == 0) and is falling into the console.error().
How do I setup the code so that my error handling code will catch this error and it will not hit the console.error() section of code in silentEmit()?
The text was updated successfully, but these errors were encountered:
esatterwhite commented Jul 16, 2021 •
Yes, I’m seeing this too, w/ sentinels and I wound up at the same place in the code.
In my case we are running sentinels in kubernetes and connecting to them directly. If a pod goes down, it’ll get recreated, but the IP may have changed, so the connect to the sentinel will start emitting ETIMEDOUT errors, but the error handler on the main instance is never triggered.
For a stand alone connection, I would expect the error handler here to be triggered on these timeout errors.
For sentinels, I would expect the connection w/ error to be marked as dead or have some number of reconnection attempts.
And the error handler should be tripped when all of the sentinels are unreachable. Timeout errors on connections should probably be handled similarly to unreachable errors.
Источник
Error: connect ECONNREFUSED 127.0.0.1:6379 #1036
Comments
hckhanh commented Jan 2, 2020 •
I received this error when I try to start my Node server in k8s
I am using bullmq that using ioredis
The text was updated successfully, but these errors were encountered:
davalapar commented Jan 5, 2020
in your redis config:
hckhanh commented Jan 9, 2020
fadel01 commented Sep 28, 2020
JoeLago commented Apr 18, 2021
My issue was pretty silly. I didn’t realize I needed to install redis and start it on my machine.
QUDUSKUNLE commented May 28, 2021
While trying to connect to Redis right from inside a container, one can use this host.docker.internal as host and 6379 as the port.
Arpit6055 commented Feb 11, 2022
can you explain a bit, How our we gonna define our hst as host.docker.internal. I’m building a micrservice(A nodejs app served by nginx). I have .yml with 3 services right now, The 1 for node app, 1 nginx container and 1 redis conatiner, the nginx and nodejs integration is perfectly working But I’m unable t connect to redis container
`
My compose.yml file looks like
services:
testRedis:
image: redis:7.0-rc1-alpine3.15
expose:
— «6379»
nginx:
build:
context: ./nginx/
ports:
— 3000:80
depends_on:
— adminapp
app:
build: .
volumes:
— ./:/usr/src/app/
— /usr/src/app/node_modules
env_file:
— ./.env
ports:
— «12000:12000″`
and In nodejs I’m connecting to the client like this
`const redis = require(«redis»);
Источник
- Table of contents
- Redis container doesn’t connect with expressJs application
- Using Redis with Docker and NodeJS/Express
- Node.js app not connect to docker redis container
- How to use Redis with Express
- Nodejs container won’t connect to redis container docker-compose
- Creating an Expressjs app using Ejs, Express-session with Redis
- How to connect app container to Redis container with docker compose
- The Proper Way To Connect Redis — Node.js
Find the data you need here
We provide programming data of 20 most popular languages, hope to help you!
Previous PostNext Post
Redis container doesn’t connect with expressJs application
But when I start express application, it does not connect with the Redis container. [email protected] test % npm run test > [email protected] test > nodemon server.js [nodemon] 2.0.16 [nodemon] to restart at any time, enter `rs` [nodemon] watching path(s): *.* [nodemon] watching extensions: js,mjs,json [nodemon] starting `node server.js
[email protected] ~ % docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
redis alpine 9dcd83a87127 3 weeks ago 36.5MB
alpine latest 3fb3c9af89a9 7 weeks ago 5.32MB
[email protected] ~ %
[email protected] ~ % docker run -dt --name redis_cache -p3307:6379 9dcd83a87127
8f44169e8c73938845319463c83f63048c5051bcbbfca7809a1300446b415ae3
[email protected] ~ %
[email protected] ~ % docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8f44169e8c73 9dcd83a87127 "docker-entrypoint.s…" 56 seconds ago Up 55 seconds 0.0.0.0:3307->6379/tcp redis_cache
[email protected] ~ %
const express = require('express');
const app = express();
const redis = require('redis');
const redisClient = redis.createClient(3307, '0.0.0.0');
redisClient.on('connect', () => {
console.log("Redis connected");
})
redisClient.on('error', () => {
console.log("Error");
})
app.listen(8080, () => {
console.log('listening on port 8080');
})
[email protected] test % npm run test
> [email protected] test
> nodemon server.js
[nodemon] 2.0.16
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node server.js`
listening on port 8080
const express = require('express');
const app = express();
const redis = require('redis');
const redisClient = redis.createClient({
url: 'redis://127.0.0.1:3307'
});
const redisConnect = async () => {
try {
await redisClient.connect()
console.log('Redis Connected');
} catch (error) {
console.log(error)
}
}
redisConnect()
app.listen(8080, () => {
console.log('listening on port 8080');
})
const redisClient = redis.createClient(3307, 'localhost');
Using Redis with Docker and NodeJS/Express
Accessing REDIS via Application. To access REDIS, we need access to the REDIS client within our application. Go to your terminal -> App Root Folder. npm i -P redis. This installs REDIS support to
docker run -d --name <CONTAINER_NAME> -p 127.0.0.1:6379:6379 redis
docker ps -a
docker exec -it <CONTAINER_NAME|ID> sh
# redis-cli127.0.0.1:6379> pingPONG127.0.0.1:6379> set customer_name "John Doe"OK127.0.0.1:6379> get customer_name"John Doe"127.0.0.1:6379> del customer_name(integer) 1127.0.0.1:6379> exit# exit
npm init
npm i -P expressnpm i -D nodemon
"dev": "nodemon server"
const express = require('express');const PORT = 5001;const app = express();const router = express.Router();app.use(express.json());router.get('/', (req,res) => { res.status(200).json({ message : "Sample Docker Redis Application" });});app.listen(PORT, () => { console.log(`Server running on PORT ${PORT}`);});
npm run dev
HTTP/1.1 200 OKX-Powered-By: ExpressContent-Type: application/json; charset=utf-8Content-Length: 45ETag: W/"2d-bO6czhAp6+qsrxSQWqx38pGjRvo"Date: Thu, 15 Apr 2021 18:14:24 GMTConnection: keep-aliveKeep-Alive: timeout=5{"message":"Sample Docker Redis Application"}
npm i -P redis
const redis = require('redis');const redisClient = redis.createClient(6379,'127.0.0.1');redisClient.on('error', (err) => { console.log('Error occured while connecting or accessing redis server');});if(!redisClient.get('customer_name',redis.print)) { //create a new record redisClient.set('customer_name','John Doe', redis.print); console.log('Writing Property : customer_name');} else { let val = redisClient.get('customer_name',redis.print); console.log(`Reading property : customer_name - ${val}`);}
[nodemon] starting `node server.js`Writing Property : customer_nameServer running on PORT 5001Reply: nullReply: OK
[nodemon] restarting due to changes...[nodemon] starting `node server.js`Writing Property : customer_nameServer running on PORT 5001Reply: John DoeReply: OK
Node.js app not connect to docker redis container
Node.js app not connect to docker redis container. I connected with docker redis container.The redis working in the docker.If I execute the docker file with docker exec -it 96e199a8badf sh, I connected to redis server. My node.js application like …
version: '3'
services:
app:
container_name: delivery-app
build:
dockerfile: 'Dockerfile'
context: .
ports:
- "3000:3000"
volumes:
- .:/app,
- '/app/node_modules'
networks:
- redis
redis:
image: "redis"
ports:
- "6379:6379"
networks:
- redis
networks:
redis:
driver: bridge
FROM node:16-alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY . ./
EXPOSE 3000
CMD ["node","server.js"]
const redisClient = redis.createClient({
socket: {
port: 6379,
host: "redis"
}
});
await redisClient.connect();
redisClient.on('connect',function(){
return res.status(200).json({
success: true
})
}).on('error',function(error){
return res.status(400).json({
success: false
})
});
"redis": "^4.1.0"
{
socket: {
host: "redis"
}
}
How to use Redis with Express
To work with Redis inside of a node server, we need a Redis driver and we are going to use the official Redis package. Let’s install the dependencies: npm i express mongoose redis dotenv npm i -D nodemon. Once we have the set up complete, we can go ahead and configure our .env file. MONGODB_URI=<your mongodb connection string>.
npm i express mongoose redis dotenv
npm i -D nodemon
MONGODB_URI=<your mongodb connection string>
docker run --name some-redis -d -p 63791:6379 redis
REDIS_HOST=<your Redis HOST>
REDIS_PORT=<your Redis PORT>
REDIS_PASSWORD=<your config PASSWORD>
import redis from "redis";
import { promisify } from "util";
// create redis client
const client = redis.createClient({
host: process.env.REDIS_HOST,
port: parseInt(process.env.REDIS_PORT),
password: process.env.REDIS_PASSWORD,
});
// redis.js doesn't support async utils as of writing this article
// we can use the recommended workaround
export const getAsync = promisify(client.get).bind(client);
export const setAsync = promisify(client.set).bind(client);
app.get("/api/<resource>", async (req, res) => {
try {
// Get from cache using the "Key"
const getRes = await getAsync("resourceKey" );
if (getRes)
return res.json({ success: true, data: JSON.parse(getRes) });
// On cache-miss => query database
const users = await <Model>.find({});
// Set cache
await setAsync("resourceKey", // Key
JSON.stringify({res}), // Value
"EX", // Set explicit expiry
60 // TTL in seconds
);
return res.status(200).json({success: true, data: <resource>});
} catch (error) {
// Handle errors
}
});
Nodejs container won’t connect to redis container docker-compose
1. Just to close the question, when trying to connect to localhost inside the container it assumes the container itself and because the node.js container doesnt publish on the redis port the connection is refused. On the other hand because using docker-compose, you get a default docker network binding them together so using the container
api_1 | events.js:291
api_1 | throw er; // Unhandled 'error' event
api_1 | ^
api_1 |
api_1 | Error: Redis connection to localhost:6379 failed - connect ECONNREFUSED 127.0.0.1:6379
api_1 | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1144:16)
api_1 | Emitted 'error' event on RedisAdapter instance at:
api_1 | at RedisClient.onError (/usr/src/api/node_modules/socket.io-redis/dist/index.js:65:22)
api_1 | at RedisClient.emit (events.js:314:20)
api_1 | at RedisClient.on_error (/usr/src/api/node_modules/redis/index.js:342:14)
api_1 | at Socket.<anonymous> (/usr/src/api/node_modules/redis/index.js:223:14)
api_1 | at Socket.emit (events.js:314:20)
api_1 | at emitErrorNT (internal/streams/destroy.js:92:8)
api_1 | at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
api_1 | at processTicksAndRejections (internal/process/task_queues.js:84:21) {
api_1 | errno: 'ECONNREFUSED',
api_1 | code: 'ECONNREFUSED',
api_1 | syscall: 'connect',
api_1 | address: '127.0.0.1',
api_1 | port: 6379
api_1 | }
const redisClient = require("redis").createClient({host: process.env.REDIS_HOST ? process.env.REDIS_HOST : 'localhost'});
api:
build: ./api
ports:
- "3004:3004"
volumes:
- type: bind
source: ./api
target: /usr/src/api
working_dir: /usr/src/api
depends_on:
- redis
networks:
- backend
redis:
image: "redis:latest"
ports:
- "6379:6379"
hostname: redis
networks:
- backend
```
What could this be. All the "solutions" that I've managed to find through research don't work for me.
Creating an Expressjs app using Ejs, Express-session with Redis
Today we are going to learn how to create simple login app using expressjs, Ejs and express-session with redis. Let’s first have a look on technologies what we are using. Expressjs. Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.
$ npm install -g express-generator
$ express --view=ejs '$project-name'
$ wget http://download.redis.io/redis-stable.tar.gz$ tar xvzf redis-stable.tar.gz$ cd redis-stable$ make
$ ./redis-server --port 6380 --slaveof 127.0.0.1 6379
$ npm i redis --save
$ npm i connect-redis --save
$ npm i express-session --save
How to connect app container to Redis container with docker compose
The redis host name looks right, but it doesn’t seem like it’s having an effect; the application container is connecting to 127.0.0.1 instead (localhost, which is to say, the application container itself). Do you have the syntax of the createClient() call correct? –
const { createClient } = require("redis");
const { createAdapter } = require("@socket.io/redis-adapter");
const pubClient = createClient({ host: "redis", port: 6379 }); // <- this host
const subClient = pubClient.duplicate();
FROM node:16.8
WORKDIR /home/node/app
COPY app /home/node/app/
RUN npm install
CMD npm run app
EXPOSE 9999 6379
const express = require("express");
const app = express();
const server = require("http").createServer(app);
const bodyParser = require("body-parser");
const appid = process.env.APPID;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const cors = require("cors");
app.use(cors());
app.use(express.json({ limit: "8mb" }));
const { createClient } = require("redis");
const { createAdapter } = require("@socket.io/redis-adapter");
const pubClient = createClient({ host: "redis", port: 6379 });
const subClient = pubClient.duplicate();
const io = require("socket.io")(server, {
cors: {
origin: "*",
methods: ["GET", "POST"],
},
});
Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
io.adapter(createAdapter(pubClient, subClient));
});
var allUsers = {};
app.get("/", async (req, res) => {
res.send(`Hello from server ${appid}`);
});
io.on("connection", (socket) => {
console.log("User connected: " + socket.id);
socket.emit("port", appid);
socket.on("message", (message) => {
socket.broadcast.emit("new-message", message);
});
socket.on("disconnecting", (socket) => {
console.log("User disconnected: ", socket.id);
});
});
server.listen(appid, () => console.log(`Server running on port ${appid}`));
defaults
mode http
timeout client 35s
timeout connect 5s
timeout server 35s
timeout tunnel 120s
timeout http-keep-alive 1s
timeout http-request 15s
timeout queue 30s
timeout tarpit 60s
timeout http-request 10s
frontend http
bind *:8080
timeout client 10s
use_backend all
backend all
server s1 nodeapp1:1111
server s2 nodeapp2:2222
version : '3'
services:
redis:
image: redis
ports:
- "6379:6379"
lb:
image: haproxy
ports:
- "8080:8080"
volumes:
- ./haproxy:/usr/local/etc/haproxy
nodeapp1:
image: nodeapp
environment:
- APPID=1111
depends_on:
- redis lb
nodeapp2:
image: nodeapp
environment:
- APPID=2222
depends_on:
- redis lb
docker-redis-1 | 1:M 13 Apr 2022 03:31:07.857 * Ready to accept connections
docker-nodeapp2-1 |
docker-nodeapp2-1 | > [email protected] app
docker-nodeapp2-1 | > node index.js
docker-nodeapp2-1 |
docker-nodeapp1-1 |
docker-nodeapp1-1 | > [email protected] app
docker-nodeapp1-1 | > node index.js
docker-nodeapp1-1 |
docker-nodeapp2-1 | Server running on port 2222
docker-nodeapp2-1 | node:internal/process/promises:246
docker-nodeapp2-1 | triggerUncaughtException(err, true /* fromPromise */);
docker-nodeapp2-1 | ^
docker-nodeapp2-1 |
docker-nodeapp2-1 | Error: connect ECONNREFUSED 127.0.0.1:6379
docker-nodeapp2-1 | at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1146:16)
docker-nodeapp2-1 | Emitted 'error' event on Commander instance at:
docker-nodeapp2-1 | at RedisSocket.<anonymous> (/home/node/app/node_modules/@node-redis/client/dist/lib/client/index.js:339:14)
docker-nodeapp2-1 | at RedisSocket.emit (node:events:394:28)
docker-nodeapp2-1 | at RedisSocket._RedisSocket_connect (/home/node/app/node_modules/@node-redis/client/dist/lib/client/socket.js:117:14)
docker-nodeapp2-1 | at processTicksAndRejections (node:internal/process/task_queues:96:5)
docker-nodeapp2-1 | at async Commander.connect (/home/node/app/node_modules/@node-redis/client/dist/lib/client/index.js:162:9)
docker-nodeapp2-1 | at async Promise.all (index 0) {
docker-nodeapp2-1 | errno: -111,
docker-nodeapp2-1 | code: 'ECONNREFUSED',
docker-nodeapp2-1 | syscall: 'connect',
docker-nodeapp2-1 | address: '127.0.0.1',
docker-nodeapp2-1 | port: 6379
docker-nodeapp2-1 | }
docker-nodeapp1-1 | Server running on port 1111
docker-lb-1 | [NOTICE] (1) : New worker (9) forked
docker-lb-1 | [NOTICE] (1) : Loading success.
docker-nodeapp1-1 | node:internal/process/promises:246
docker-nodeapp1-1 | triggerUncaughtException(err, true /* fromPromise */);
docker-nodeapp1-1 | ^
docker-nodeapp1-1 |
docker-nodeapp1-1 | Error: connect ECONNREFUSED 127.0.0.1:6379
docker-nodeapp1-1 | at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1146:16)
docker-nodeapp1-1 | Emitted 'error' event on Commander instance at:
docker-nodeapp1-1 | at RedisSocket.<anonymous> (/home/node/app/node_modules/@node-redis/client/dist/lib/client/index.js:339:14)
docker-nodeapp1-1 | at RedisSocket.emit (node:events:394:28)
docker-nodeapp1-1 | at RedisSocket._RedisSocket_connect (/home/node/app/node_modules/@node-redis/client/dist/lib/client/socket.js:117:14)
docker-nodeapp1-1 | at processTicksAndRejections (node:internal/process/task_queues:96:5)
docker-nodeapp1-1 | at async Commander.connect (/home/node/app/node_modules/@node-redis/client/dist/lib/client/index.js:162:9)
docker-nodeapp1-1 | at async Promise.all (index 0) {
docker-nodeapp1-1 | errno: -111,
docker-nodeapp1-1 | code: 'ECONNREFUSED',
docker-nodeapp1-1 | syscall: 'connect',
docker-nodeapp1-1 | address: '127.0.0.1',
docker-nodeapp1-1 | port: 6379
docker-nodeapp1-1 | }
docker-nodeapp2-1 exited with code 1
docker-nodeapp1-1 exited with code 1
nodeapp2:
image: nodeapp
environment:
- APPID=2222
depends_on:
- redis
- lb
restart: always
let pubClient;
const pubClient = connectRedis();
function connectRedis() {
try {
return createClient({ host: "redis", port: 6379 });
} catch {
return connectRedis();
}
}
The Proper Way To Connect Redis — Node.js
docker run -d —name redis_srv -p 6379:6379 redis. If you do not want to install Docker, we can simply use Redis Labs. Open this link to create an account. Alright, we are ready to go! Follow these steps to create an environment: Create an empty folder to work in: mkdir connect-redis&& cd connect-redis. Init a Node.js project, -y will skip the
docker run -d --name redis_srv -p 6379:6379 redis
mkdir connect-redis&& cd connect-redis
npm init -y
touch index.js
{ "name": "connect-redis", "version": "0.0.0", "private": true, "scripts": { "start": "node index", }, "dependencies": {}, "devDependencies": {}}
npm install --save redis lodash
const redis = require('redis');const _ = require('lodash');const clients = {};let connectionTimeout;module.exports.init = () => {};module.exports.getClients = () => {};module.exports.closeConnections = () => {};
module.exports.init = () => { const cacheInstance = redis.createClient('redis://connection-string'); clients.cacheInstance = cacheInstance;};
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 });};
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 });};
module.exports.closeConnections = () => _.forOwn(clients, (conn) => conn.quit());
module.exports.getClients = () => clients;
Previous PostNext Post
Type Parameters
-
M extends RedisModules
-
F extends RedisFunctions
-
S extends RedisScripts
Hierarchy
- EventEmitter
- default
Index
Constructors
constructor
- new default<M, F, S>(options?: RedisClientOptions<M, F, S>): default<M, F, S>
-
Type Parameters
-
M extends RedisModules
-
F extends RedisFunctions
-
S extends RedisScripts
Returns default<M, F, S>
-
Properties
Private Readonly #isolationPool
Private Optional Readonly #options
Private Optional #pingTimer
#pingTimer?: Timer
Private Readonly #queue
Private #selectedDB
#selectedDB: number = 0
Private Readonly #socket
Private Readonly #v4
#v4: Record<string, any> = {}
commandOptions
commandOptions: (<T>(options: T) => CommandOptions<T>) = RedisClient.commandOptions
Type declaration
-
- <T>(options: T): CommandOptions<T>
-
Type Parameters
-
T extends ClientCommandOptions
Parameters
-
options: T
Returns CommandOptions<T>
-
multi
Type declaration
-
- (): RedisClientMultiCommandType<M, F, S>
-
Returns RedisClientMultiCommandType<M, F, S>
pSubscribe
pSubscribe: (<T>(patterns: string | string[], listener: PubSubListener<T>, bufferMode?: T) => Promise<void>) = …
Type declaration
-
- <T>(patterns: string | string[], listener: PubSubListener<T>, bufferMode?: T): Promise<void>
-
Type Parameters
-
T extends boolean = false
Parameters
-
patterns: string | string[]
-
listener: PubSubListener<T>
-
OptionalbufferMode: T
Returns Promise<void>
-
pUnsubscribe
pUnsubscribe: (<T>(patterns?: string | string[], listener?: PubSubListener<T>, bufferMode?: T) => Promise<void>) = …
Type declaration
-
- <T>(patterns?: string | string[], listener?: PubSubListener<T>, bufferMode?: T): Promise<void>
-
Type Parameters
-
T extends boolean = false
Parameters
-
Optionalpatterns: string | string[] -
Optionallistener: PubSubListener<T> -
OptionalbufferMode: T
Returns Promise<void>
-
quit
quit: (() => Promise<string>) = …
Type declaration
-
- (): Promise<string>
-
Returns Promise<string>
sSubscribe
sSubscribe: (<T>(channels: string | string[], listener: PubSubListener<T>, bufferMode?: T) => Promise<void>) = …
Type declaration
-
- <T>(channels: string | string[], listener: PubSubListener<T>, bufferMode?: T): Promise<void>
-
Type Parameters
-
T extends boolean = false
Parameters
-
channels: string | string[]
-
listener: PubSubListener<T>
-
OptionalbufferMode: T
Returns Promise<void>
-
sUnsubscribe
sUnsubscribe: (<T>(channels?: string | string[], listener?: PubSubListener<T>, bufferMode?: T) => Promise<void>) = …
Type declaration
-
- <T>(channels?: string | string[], listener?: PubSubListener<T>, bufferMode?: T): Promise<void>
-
Type Parameters
-
T extends boolean = false
Parameters
-
Optionalchannels: string | string[] -
Optionallistener: PubSubListener<T> -
OptionalbufferMode: T
Returns Promise<void>
-
select
Type declaration
-
- (db: number): Promise<void>
-
Parameters
-
db: number
Returns Promise<void>
-
- (options: CommandOptions<ClientCommandOptions>, db: number): Promise<void>
-
Returns Promise<void>
subscribe
subscribe: (<T>(channels: string | string[], listener: PubSubListener<T>, bufferMode?: T) => Promise<void>) = …
Type declaration
-
- <T>(channels: string | string[], listener: PubSubListener<T>, bufferMode?: T): Promise<void>
-
Type Parameters
-
T extends boolean = false
Parameters
-
channels: string | string[]
-
listener: PubSubListener<T>
-
OptionalbufferMode: T
Returns Promise<void>
-
unsubscribe
unsubscribe: (<T>(channels?: string | string[], listener?: PubSubListener<T>, bufferMode?: T) => Promise<void>) = …
Type declaration
-
- <T>(channels?: string | string[], listener?: PubSubListener<T>, bufferMode?: T): Promise<void>
-
Type Parameters
-
T extends boolean = false
Parameters
-
Optionalchannels: string | string[] -
Optionallistener: PubSubListener<T> -
OptionalbufferMode: T
Returns Promise<void>
-
Static Readonly captureRejectionSymbol
Static captureRejections
captureRejections: boolean
Static defaultMaxListeners
defaultMaxListeners: number
Static Readonly errorMonitor
Accessors
isOpen
- get isOpen(): boolean
-
Returns boolean
isPubSubActive
- get isPubSubActive(): boolean
-
Returns boolean
isReady
- get isReady(): boolean
-
Returns boolean
options
- get options(): undefined | RedisClientOptions<M, F, S>
-
Returns undefined | RedisClientOptions<M, F, S>
v4
- get v4(): Record<string, any>
-
Returns Record<string, any>
Methods
Private #defineLegacyCommand
- #defineLegacyCommand(name: string, command?: RedisCommand): void
-
Returns void
Private #destroyIsolationPool
- #destroyIsolationPool(): Promise<void>
-
Returns Promise<void>
Private #initiateOptions
- #initiateOptions(options?: RedisClientOptions<M, F, S>): undefined | RedisClientOptions<M, F, S>
-
Returns undefined | RedisClientOptions<M, F, S>
Private #initiateQueue
- #initiateQueue(): default
-
Returns default
Private #initiateSocket
- #initiateSocket(): default
-
Returns default
Private #legacyMode
- #legacyMode(): void
-
Returns void
Private #legacySendCommand
- #legacySendCommand(…args: any[]): undefined | {
callback: ClientLegacyCallback;
promise: Promise<RedisCommandRawReply>;
} -
Parameters
-
Rest…args: any[]
Returns undefined | {
callback: ClientLegacyCallback;
promise: Promise<RedisCommandRawReply>;
} -
Private #pubSubCommand
- #pubSubCommand(promise: undefined | Promise<void>): Promise<void>
-
Parameters
-
promise: undefined | Promise<void>
Returns Promise<void>
-
Private #sendCommand
- #sendCommand<T>(args: RedisCommandArguments, options?: ClientCommandOptions): Promise<T>
-
Type Parameters
-
T = RedisCommandRawReply
Returns Promise<T>
-
Private #setPingTimer
- #setPingTimer(): void
-
Returns void
Private #tick
- #tick(force?: boolean): void
-
Parameters
-
force: boolean = false
Returns void
-
MULTI
- MULTI(): RedisClientMultiCommandType<M, F, S>
-
Returns RedisClientMultiCommandType<M, F, S>
PSUBSCRIBE
- PSUBSCRIBE<T>(patterns: string | string[], listener: PubSubListener<T>, bufferMode?: T): Promise<void>
-
Type Parameters
-
T extends boolean = false
Parameters
-
patterns: string | string[]
-
listener: PubSubListener<T>
-
OptionalbufferMode: T
Returns Promise<void>
-
PUNSUBSCRIBE
- PUNSUBSCRIBE<T>(patterns?: string | string[], listener?: PubSubListener<T>, bufferMode?: T): Promise<void>
-
Type Parameters
-
T extends boolean = false
Parameters
-
Optionalpatterns: string | string[] -
Optionallistener: PubSubListener<T> -
OptionalbufferMode: T
Returns Promise<void>
-
QUIT
- QUIT(): Promise<string>
-
Returns Promise<string>
SELECT
- SELECT(db: number): Promise<void>
-
Parameters
-
db: number
Returns Promise<void>
-
- SELECT(options: CommandOptions<ClientCommandOptions>, db: number): Promise<void>
-
Returns Promise<void>
SSUBSCRIBE
- SSUBSCRIBE<T>(channels: string | string[], listener: PubSubListener<T>, bufferMode?: T): Promise<void>
-
Type Parameters
-
T extends boolean = false
Parameters
-
channels: string | string[]
-
listener: PubSubListener<T>
-
OptionalbufferMode: T
Returns Promise<void>
-
SUBSCRIBE
- SUBSCRIBE<T>(channels: string | string[], listener: PubSubListener<T>, bufferMode?: T): Promise<void>
-
Type Parameters
-
T extends boolean = false
Parameters
-
channels: string | string[]
-
listener: PubSubListener<T>
-
OptionalbufferMode: T
Returns Promise<void>
-
SUNSUBSCRIBE
- SUNSUBSCRIBE<T>(channels?: string | string[], listener?: PubSubListener<T>, bufferMode?: T): Promise<void>
-
Type Parameters
-
T extends boolean = false
Parameters
-
Optionalchannels: string | string[] -
Optionallistener: PubSubListener<T> -
OptionalbufferMode: T
Returns Promise<void>
-
UNSUBSCRIBE
- UNSUBSCRIBE<T>(channels?: string | string[], listener?: PubSubListener<T>, bufferMode?: T): Promise<void>
-
Type Parameters
-
T extends boolean = false
Parameters
-
Optionalchannels: string | string[] -
Optionallistener: PubSubListener<T> -
OptionalbufferMode: T
Returns Promise<void>
-
addListener
- addListener(eventName: string | symbol, listener: ((…args: any[]) => void)): default<M, F, S>
-
Parameters
-
eventName: string | symbol
-
listener: ((…args: any[]) => void)
-
- (…args: any[]): void
-
Parameters
-
Rest…args: any[]
Returns void
-
-
Returns default<M, F, S>
-
commandsExecutor
- commandsExecutor<C>(command: C, args: unknown[]): Promise<RedisCommandReply<C>>
-
Type Parameters
-
C extends RedisCommand
Parameters
-
command: C
-
args: unknown[]
Returns Promise<RedisCommandReply<C>>
-
connect
- connect(): Promise<void>
-
Returns Promise<void>
disconnect
- disconnect(): Promise<void>
-
Returns Promise<void>
duplicate
- duplicate(overrides?: Partial<RedisClientOptions<M, F, S>>): RedisClientType<M, F, S>
-
Returns RedisClientType<M, F, S>
emit
- emit(eventName: string | symbol, …args: any[]): boolean
-
Parameters
-
eventName: string | symbol
-
Rest…args: any[]
Returns boolean
-
eventNames
- eventNames(): (string | symbol)[]
-
Returns (string | symbol)[]
executeFunction
- executeFunction(name: string, fn: RedisFunction, args: RedisCommandArguments, options?: ClientCommandOptions): Promise<RedisCommandRawReply>
-
Returns Promise<RedisCommandRawReply>
executeIsolated
- executeIsolated<T>(fn: ((client: RedisClientType<M, F, S>) => T | Promise<T>)): Promise<T>
-
Type Parameters
-
T
Parameters
-
fn: ((client: RedisClientType<M, F, S>) => T | Promise<T>)
-
- (client: RedisClientType<M, F, S>): T | Promise<T>
-
Returns T | Promise<T>
-
Returns Promise<T>
-
executeScript
- executeScript(script: RedisScript, args: RedisCommandArguments, options?: ClientCommandOptions): Promise<RedisCommandRawReply>
-
Returns Promise<RedisCommandRawReply>
extendPubSubChannelListeners
- extendPubSubChannelListeners(type: PubSubType, channel: string, listeners: ChannelListeners): Promise<void>
-
Returns Promise<void>
extendPubSubListeners
- extendPubSubListeners(type: PubSubType, listeners: PubSubTypeListeners): Promise<void>
-
Returns Promise<void>
functionsExecuter
- functionsExecuter<F>(fn: F, args: unknown[], name: string): Promise<RedisCommandReply<F>>
-
Type Parameters
-
F extends RedisFunction
Parameters
-
fn: F
-
args: unknown[]
-
name: string
Returns Promise<RedisCommandReply<F>>
-
getMaxListeners
- getMaxListeners(): number
-
Returns number
getPubSubListeners
- getPubSubListeners(type: PubSubType): PubSubTypeListeners
-
Returns PubSubTypeListeners
hScanIterator
- hScanIterator(key: string, options?: ScanOptions): AsyncIterable<{
field: string;
value: string;
}> -
Returns AsyncIterable<{
field: string;
value: string;
}>
listenerCount
- listenerCount(eventName: string | symbol): number
-
Parameters
-
eventName: string | symbol
Returns number
-
listeners
- listeners(eventName: string | symbol): Function[]
-
Parameters
-
eventName: string | symbol
Returns Function[]
-
multiExecutor
- multiExecutor(commands: RedisMultiQueuedCommand[], selectedDB?: number, chainId?: symbol): Promise<RedisCommandRawReply[]>
-
Returns Promise<RedisCommandRawReply[]>
off
- off(eventName: string | symbol, listener: ((…args: any[]) => void)): default<M, F, S>
-
Parameters
-
eventName: string | symbol
-
listener: ((…args: any[]) => void)
-
- (…args: any[]): void
-
Parameters
-
Rest…args: any[]
Returns void
-
-
Returns default<M, F, S>
-
on
- on(eventName: string | symbol, listener: ((…args: any[]) => void)): default<M, F, S>
-
Parameters
-
eventName: string | symbol
-
listener: ((…args: any[]) => void)
-
- (…args: any[]): void
-
Parameters
-
Rest…args: any[]
Returns void
-
-
Returns default<M, F, S>
-
once
- once(eventName: string | symbol, listener: ((…args: any[]) => void)): default<M, F, S>
-
Parameters
-
eventName: string | symbol
-
listener: ((…args: any[]) => void)
-
- (…args: any[]): void
-
Parameters
-
Rest…args: any[]
Returns void
-
-
Returns default<M, F, S>
-
prependListener
- prependListener(eventName: string | symbol, listener: ((…args: any[]) => void)): default<M, F, S>
-
Parameters
-
eventName: string | symbol
-
listener: ((…args: any[]) => void)
-
- (…args: any[]): void
-
Parameters
-
Rest…args: any[]
Returns void
-
-
Returns default<M, F, S>
-
prependOnceListener
- prependOnceListener(eventName: string | symbol, listener: ((…args: any[]) => void)): default<M, F, S>
-
Parameters
-
eventName: string | symbol
-
listener: ((…args: any[]) => void)
-
- (…args: any[]): void
-
Parameters
-
Rest…args: any[]
Returns void
-
-
Returns default<M, F, S>
-
rawListeners
- rawListeners(eventName: string | symbol): Function[]
-
Parameters
-
eventName: string | symbol
Returns Function[]
-
ref
- ref(): void
-
Returns void
removeAllListeners
- removeAllListeners(event?: string | symbol): default<M, F, S>
-
Parameters
-
Optionalevent: string | symbol
Returns default<M, F, S>
-
removeListener
- removeListener(eventName: string | symbol, listener: ((…args: any[]) => void)): default<M, F, S>
-
Parameters
-
eventName: string | symbol
-
listener: ((…args: any[]) => void)
-
- (…args: any[]): void
-
Parameters
-
Rest…args: any[]
Returns void
-
-
Returns default<M, F, S>
-
sScanIterator
- sScanIterator(key: string, options?: ScanOptions): AsyncIterable<string>
-
Returns AsyncIterable<string>
scanIterator
- scanIterator(options?: ScanCommandOptions): AsyncIterable<string>
-
Returns AsyncIterable<string>
scriptsExecuter
- scriptsExecuter<S>(script: S, args: unknown[]): Promise<RedisCommandReply<S>>
-
Type Parameters
-
S extends RedisScript
Parameters
-
script: S
-
args: unknown[]
Returns Promise<RedisCommandReply<S>>
-
sendCommand
- sendCommand<T>(args: RedisCommandArguments, options?: ClientCommandOptions): Promise<T>
-
Type Parameters
-
T = RedisCommandRawReply
Returns Promise<T>
-
setMaxListeners
- setMaxListeners(n: number): default<M, F, S>
-
Parameters
-
n: number
Returns default<M, F, S>
-
unref
- unref(): void
-
Returns void
zScanIterator
- zScanIterator(key: string, options?: ScanOptions): AsyncIterable<{
score: number;
value: string;
}> -
Returns AsyncIterable<{
score: number;
value: string;
}>
Static commandOptions
- commandOptions<T>(options: T): CommandOptions<T>
-
Type Parameters
-
T extends ClientCommandOptions
Parameters
-
options: T
Returns CommandOptions<T>
-
Static create
- create<M, F, S>(options?: RedisClientOptions<M, F, S>): RedisClientType<M, F, S>
-
Type Parameters
-
M extends RedisModules
-
F extends RedisFunctions
-
S extends RedisScripts
Returns RedisClientType<M, F, S>
-
Static extend
- extend<M, F, S>(extensions?: RedisExtensions<M, F, S>): InstantiableRedisClient<M, F, S>
-
Type Parameters
-
M extends RedisModules
-
F extends RedisFunctions
-
S extends RedisScripts
Returns InstantiableRedisClient<M, F, S>
-
Static getEventListeners
- getEventListeners(emitter: EventEmitter | _DOMEventTarget, name: string | symbol): Function[]
-
Parameters
-
emitter: EventEmitter | _DOMEventTarget
-
name: string | symbol
Returns Function[]
-
Static listenerCount
- listenerCount(emitter: EventEmitter, eventName: string | symbol): number
-
Parameters
-
emitter: EventEmitter
-
eventName: string | symbol
Returns number
-
Static on
- on(emitter: EventEmitter, eventName: string, options?: StaticEventEmitterOptions): AsyncIterableIterator<any>
-
Parameters
-
emitter: EventEmitter
-
eventName: string
-
Optionaloptions: StaticEventEmitterOptions
Returns AsyncIterableIterator<any>
-
Static once
- once(emitter: _NodeEventTarget, eventName: string | symbol, options?: StaticEventEmitterOptions): Promise<any[]>
-
Parameters
-
emitter: _NodeEventTarget
-
eventName: string | symbol
-
Optionaloptions: StaticEventEmitterOptions
Returns Promise<any[]>
-
- once(emitter: _DOMEventTarget, eventName: string, options?: StaticEventEmitterOptions): Promise<any[]>
-
Parameters
-
emitter: _DOMEventTarget
-
eventName: string
-
Optionaloptions: StaticEventEmitterOptions
Returns Promise<any[]>
-
Static parseURL
- parseURL(url: string): RedisClientOptions<RedisModules, RedisFunctions, RedisScripts>
-
Parameters
-
url: string
Returns RedisClientOptions<RedisModules, RedisFunctions, RedisScripts>
-
Static setMaxListeners
- setMaxListeners(n?: number, …eventTargets: (EventEmitter | _DOMEventTarget)[]): void
-
Parameters
-
Optionaln: number -
Rest…eventTargets: (EventEmitter | _DOMEventTarget)[]
Returns void
-
View community ranking In the Top 1% of largest communities on Reddit
Redis Help
I am trying to get two containers to talk to one another, one with redis-server, and one with my web app.
Here is the Dockerfile for the redis image:
FROM redis:3.2.1 EXPOSE 6379 CMD [ "redis-server" ]
Very simple, and it seems to run fine when I create the container like this:
docker run -d --rm -p 6379:6379 e71a5e1b0f03
(I’m not sure if I need to have `EXPOSE 6379` and the `-p 6379:6379` as well. Part of my problem is I don’t understand the ports well enough.)
When I create the container for my (NodeJs) webapp, I get this error:
Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED 127.0.0.1:6379
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1129:14)
Emitted 'error' event on RedisClient instance at:
at RedisClient.on_error (/usr/src/app/node_modules/redis/index.js:406:14)
at Socket.<anonymous> (/usr/src/app/node_modules/redis/index.js:279:14)
at Socket.emit (events.js:210:5)
at emitErrorNT (internal/streams/destroy.js:92:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
at processTicksAndRejections (internal/process/task_queues.js:80:21) {
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 6379
}
I am using boilerplate redis code in my js file:
const redis = require('redis')
const client = redis.createClient({
port: 6379
})
As far as I understand it, my webapp container should be able to communicate with the redis container through port 6379. What am I not understanding?
I eventually will set this up with docker-compose, but I want to understand the basics before I start using tools to make things easier.
Any help is much appreciated.

