我的nodejs-redis-docker-compose应用程序出现问题。该应用程序正常运行了几次。但是后来,它开始给我以下错误。我正在使用redis-server v3.2.100
docker 18.09.1 build 4c52b90
。我卸载了docker和redis并重新安装了它们,但是我仍然遇到相同的问题。这是错误。
REDIS_DB | 1:C 22 Jan 2019 02:24:00.208 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
REDIS_DB | 1:C 22 Jan 2019 02:24:00.208 # Redis version=5.0.3, bits=64, commit=00000000, modified=0, pid=1, just started
REDIS_DB | 1:C 22 Jan 2019 02:24:00.208 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
REDIS_DB | 1:M 22 Jan 2019 02:24:00.210 * Running mode=standalone, port=6379.
REDIS_DB | 1:M 22 Jan 2019 02:24:00.210 # WARNING: The TCP backlog setting of
511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
REDIS_DB | 1:M 22 Jan 2019 02:24:00.210 # Server initialized
REDIS_DB | 1:M 22 Jan 2019 02:24:00.210 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues
with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
REDIS_DB | 1:M 22 Jan 2019 02:24:00.211 * DB loaded from disk: 0.001 seconds
REDIS_DB | 1:M 22 Jan 2019 02:24:00.211 * Ready to accept connections
MAIN_API | [nodemon] starting `node --trace-warnings index.js`
MAIN_API | Unhandled Rejection at: Promise Promise {
MAIN_API | <rejected> { Error: connect ECONNREFUSED 127.0.0.1:6379
MAIN_API | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1117:14)
MAIN_API | errno: 'ECONNREFUSED',
MAIN_API | code: 'ECONNREFUSED',
MAIN_API | syscall: 'connect',
MAIN_API | address: '127.0.0.1',
MAIN_API | port: 6379 } } reason: Error: connect ECONNREFUSED 127.0.0.1:6379
MAIN_API | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1117:14)
MAIN_API | Unhandled Rejection at: Promise Promise {
MAIN_API | <rejected> { Error: connect ECONNREFUSED 127.0.0.1:6379
MAIN_API | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1117:14)
MAIN_API | errno: 'ECONNREFUSED',
MAIN_API | code: 'ECONNREFUSED',
MAIN_API | syscall: 'connect',
MAIN_API | address: '127.0.0.1',
MAIN_API | port: 6379 } } reason: Error: connect ECONNREFUSED 127.0.0.1:6379
MAIN_API | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1117:14)
MAIN_API | ✓-- Redis client pid=>37 Connected
MAIN_API | --- Redis server pid=>37 is ready
MAIN_API | ~~~ Testing local redis storage...
MAIN_API | ✓-- Redis pid=>37 startup test succeeded
MAIN_API | ✓-- MongoDB pid=>37 Connected
MAIN_API | ✓-- Server pid=>48 running at port: 5555
MAIN_API | Unhandled Rejection at: Promise Promise {
MAIN_API | <rejected> { Error: connect ECONNREFUSED 127.0.0.1:6379
MAIN_API | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1117:14)
MAIN_API | errno: 'ECONNREFUSED',
MAIN_API | code: 'ECONNREFUSED',
MAIN_API | syscall: 'connect',
MAIN_API | address: '127.0.0.1',
MAIN_API | port: 6379 } } reason: Error: connect ECONNREFUSED 127.0.0.1:6379
MAIN_API | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1117:14)
MAIN_API | Unhandled Rejection at: Promise Promise {
MAIN_API | <rejected> { Error: connect ECONNREFUSED 127.0.0.1:6379
MAIN_API | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1117:14)
MAIN_API | errno: 'ECONNREFUSED',
MAIN_API | code: 'ECONNREFUSED',
MAIN_API | syscall: 'connect',
MAIN_API | address: '127.0.0.1',
MAIN_API | port: 6379 } } reason: Error: connect ECONNREFUSED 127.0.0.1:6379
MAIN_API | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1117:14)
MAIN_API | ✓-- Redis client pid=>48 Connected
MAIN_API | --- Redis server pid=>48 is ready
MAIN_API | ~~~ Testing local redis storage...
MAIN_API | ✓-- Redis pid=>48 startup test succeeded
MAIN_API | ✓-- MongoDB pid=>48 Connected
启动nodejs应用程序时会引发错误,但在应用程序启动并运行时它将连接到Redis服务器。
Redis控制台日志
[16308] 21 Jan 18:03:25.425 # Server started, Redis version 3.2.100
[16308] 21 Jan 18:03:25.426 * DB loaded from disk: 0.000 seconds
[16308] 21 Jan 18:03:25.426 * The server is now ready to accept connections on port 6379
我在控制台上运行了netstat -a -n -o
,这是相关的部分(我相信)。
TCP 0.0.0.0:6379 0.0.0.0:0 LISTENING 16308
TCP [::]:6379 [::]:0 LISTENING 16308
以下是我的文件。
./Dockerfile
FROM node:10.15.0
RUN mkdir -p ./usr/src/MainAPI
WORKDIR /usr/src/MainAPI
COPY ./ ./usr/src/MainAPI
RUN npm install
ARG NODE_VERSION=10.15.0
./docker-compose.yml
version: "3.7"
services:
# Redis
redis:
container_name: REDIS_DB
image: redis
ports:
- "6378:6379"
# API
main-api:
container_name: MAIN_API
build: ./
command: ["npm", "start"]
working_dir: /usr/src/MainAPI
ports:
- "5555:5555"
volumes:
- ./:/usr/src/MainAPI
./redisClient.js
const Redis = require("ioredis");
//module.exports = require("redis").createClient(...); => same errors with this module as well
module.exports = new Redis('redis://redis:6379/0');
//module.exports = new Redis('redis://127.0.0.1:6379/0'); =>crashes the app
//module.exports = new Redis('redis://redis:6378/0'); =>crashes the app also
./app.js
"use strict";
const express = require("express");
const { red, green, cyan, yellow } = require("kleur");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const morgan = require("morgan");
const cors = require("cors");
const path = require("path");
const helmet = require("helmet");
const redisClient = require("./redisClient");
const { CLIENT_BASE_URL, API_BASE_URL, MONGO_URI } = process.env;
const isProduction = process.env.NODE_ENV === "production";
const server = express();
const whitelist = [CLIENT_BASE_URL, API_BASE_URL];
const corsOptions = {
origin: function(origin, callback) {
if (whitelist.indexOf(origin) !== -1 || !origin) {
return callback(null, true);
} else {
return callback(new Error("Not allowed by CORS"), false);
}
}
};
server.use(helmet());
if (isProduction) {
server.use(cors(corsOptions));
server.use(morgan("combined"));
} else {
server.use(morgan("dev"));
}
server.set("trust proxy", 1);
/**
* Test redis storage on deploy
*/
redisClient.on("connect", function() {
console.log(
green("✓-- ") + "Redis client pid=>" + process.pid + " Connected"
);
});
redisClient.on("ready", function() {
console.log(cyan("--- Redis server pid=>" + process.pid + " is ready"));
console.log(cyan("~~~ Testing local redis storage..."));
const testKey = "key";
const testValue = "value";
redisClient.set(testKey, testValue).then(() => {
redisClient.get(testKey, (error, result) => {
if (error) {
console.log(red("✗-- An error occured while testing redis storage"));
console.error(error);
return process.exit(1);
}
if (!result || result !== testValue) {
console.log(
red(
"✗-- Redis pid=>" + process.pid + " did not pass the startup test"
)
);
console.error(result);
return process.exit(1);
}
console.log(
green("✓-- Redis pid=>" + process.pid + " startup test succeeded")
);
});
});
});
redisClient.on("error", function(err) {
console.log(red("✗-- Something went wrong with redis"));
console.error(err);
process.exit(1);
});
redisClient.on("end", function() {
console.log(
yellow("--- ") + "Redis client pid=>" + process.pid + " closed connection"
);
});
mongoose.set("useCreateIndex", true);
mongoose.Promise = global.Promise;
mongoose
.connect(
MONGO_URI,
{
useNewUrlParser: true
}
)
.then(() => {
console.log(green("✓-- ") + "MongoDB pid=>" + process.pid + " Connected");
})
.catch(err => {
console.log(red("✗--Database Connection"));
console.error(err);
process.exit(1);
});
server.use(
bodyParser.urlencoded({
extended: false
})
);
server.use(bodyParser.json());
require("./controlers/home")(server);
require("./controlers/user")(server);
require("./controlers/admin")(server);
if (isProduction) {
server.use(express.static("client/build"));
server.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
});
}
module.exports = server;
我没有在服务器上调用.listen(...),因为它已导出到另一个文件(index.js)。
谢谢
答案 0 :(得分:0)
我正在回答自己的问题。我在代码中找到了导致此问题的原因。实际上,我开始使用npm agenda
和MongoDB
来调度应用程序中的某些任务。后来我切换到使用npm bull
的{{1}}。我创建了如下队列实例。
Redis
应该是
const Queue = require("bull");
const emailQueue = new Queue("emails");
因为我没有为模块指定redis设置,所以它无法连接到服务器。我完全忘记了我有另一个使用Redis的模块。该应用似乎正常运行的原因是,const Queue = require("bull");
const emailQueue = new Queue("emails", {
redis: { port: 6379, host: "redis-server" }
});
已连接到Redis,而express
未连接。我会弄清楚,如果我尝试使用功能,那么Bull是过程的一部分。我还简化了bull
和Dockerfile
文件,使其仅包含必要的步骤。
/ Dockerfile
docker-compose.yml
/docker-compose.yml
FROM node:alpine # create image with NodeJS version alpine included
WORKDIR /usr/app # set working directory of the app to be /usr/app/. create folder /usr/app if it does not exist already. The following operations would then happen inside /usr/app
COPY ./package.json ./ # copy package.json file into current directory, which is /usr/app according to previous step
RUN npm install # install dependencies
COPY ./ ./ # add the rest of the files to /usr/app
CMD ["npm", "start"] # run 'npm start' when the container is starting
我不需要其他任何东西来运行该应用程序。通过在我的应用程序中将服务名称简单地赋予version: "3"
services:
# Redis
redis-server: # the name of the redis service becomes the host name in my application
container_name: REDIS_SERVER
image: 'redis'
# API
main-api:
container_name: MAIN_API
build: ./
ports:
- "5555:5555"
,该模块将确定在哪里可以找到服务器。即在ioredis
部分中的here。在我的情况下,服务器名称为links
,因此redis-server
和ioredis
的主机名也将为bull
,端口号为redis-server
。谢谢@DavidMaze @yeaseol和...
答案 1 :(得分:-1)
该端口已绑定到6378
,因此您需要访问6378
。
您可以使用主机名redis
吗? (设置了吗?)
试试这个:
module.exports = new Redis('redis://{docker-server-hostname}:6378');
或
最好的选择是将link
设置为docker-compose。
main-api:
container_name: MAIN_API
build: ./
command: ["npm", "start"]
working_dir: /usr/src/MainAPI
ports:
- "5555:5555"
volumes:
- ./:/usr/src/MainAPI
links:
- {your-redis-container-name}
尝试一下:
module.exports = new Redis('redis://{your-redis-container-name}:6379');