Redis Windows Error: connect ECONNREFUSED 127.0.0.1:6379, но приложение работает - PullRequest
0 голосов
/ 22 января 2019

У меня проблема с моим приложением 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).

Спасибо

Ответы [ 2 ]

0 голосов
/ 23 января 2019

Я отвечаю на свой вопрос. Я нашел то, что вызывает проблему в моем коде. Фактически я начал использовать 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 - нет. Я бы понял это, если бы попытался использовать функцию, которая является частью процесса. Я также упростил свои файлы Dockerfile и docker-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 и ...

0 голосов
/ 22 января 2019

Порт привязан к 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');

...