0

我的 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)。

谢谢

4

2 回答 2

1

我正在回答我自己的问题。我在我的代码中找到了导致问题的原因。事实上,我开始使用npm agenda,它使用MongoDB,在我的应用程序中安排一些任务。我后来切换到npm bull,它正在使用Redis. 我创建了如下的队列实例。

const Queue = require("bull");

const emailQueue = new Queue("emails");

虽然它应该是

const Queue = require("bull");

const emailQueue = new Queue("emails", {
  redis: { port: 6379, host: "redis-server" }
});

因为我没有指定模块的redis设置,所以无法连接到服务器。我完全忘记了我有另一个使用 redis 的模块。该应用程序似乎工作的原因是因为express连接到 redis 而bull没有。如果我尝试使用公牛是该过程的一部分的功能,我会弄清楚这一点。我还简化了我的Dockerfiledocker-compose.yml文件,只包含必要的步骤。


/Dockerfile

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


/docker-compose.yml

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在我的应用程序中简单地提供服务名称,该模块将找出在哪里可以找到服务器。这就是这里links部​​分。在我的情况下,服务器名称是redis-server主机名,ioredis并且bull也是redis-server端口号6379。谢谢@DavidMaze @yeaseol,还有...

于 2019-01-23T12:43:57.233 回答
-1

端口是绑定的6378,所以需要访问6378
你可以使用主机名redis吗?(你设置了吗?)
试试这个:
module.exports = new Redis('redis://{docker-server-hostname}:6378');
或者
最好的选择是将 a 设置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');

于 2019-01-22T04:16:29.670 回答