Кластеры узлов с очередью pm2 каждый второй запрос

Я использую pm2 для управления одновременными запросами к моему API, пока все хорошо, мне удалось заставить его работать.

Мой API имеет только один маршрут. Каждый запрос занимает от 1 до 2 минут, чтобы полностью решить и отправить ответ. Как только я делаю свой первый запрос, я вижу в журналах pm2, что запрос был принят, но если я делаю второй запрос на тот же маршрут, он ставится в очередь и обрабатывается только после завершения первого. Только в том случае, если я делаю третий запрос на тот же маршрут, пока второй запрос находится в очереди, вызывается другой рабочий процесс и принимает третий запрос, второй остается в очереди, пока первый не будет разрешен. Надеюсь, я ясно выразился

первый запрос немедленно принимается работником, второй запрос ставится в очередь, а третий запрос также быстро принимается другим работником, четвертый ставится в очередь, пятый принимается, шестой ставится в очередь и так далее.

У меня есть 24 свободных рабочих.

вот мой очень простой сервер:

const express = require('express');
const runner = require('./Rrunner2')
const moment = require('moment');
const bodyParser = require('body-parser');



const app = express();
app.use(express.json({limit: '50mb', extended: true}));
app.use(bodyParser.json())


app.post('/optimize', (req, res) => {
    try{
        
        const req_start = moment().format('DD/MM/YYYY h:mm a');
        console.log('Request received at ' + req_start)
        console.log(`Worker process ID - ${process.pid} has accepted the request.`);
    
        const data = req.body;
        
        const opt_start = moment().format('DD/MM/YYYY h:mm a')
        console.log('Optimization started at ' + opt_start)
        let result = runner.optimizer(data);

        const opt_end = moment().format('DD/MM/YYYY h:mm a')
        console.log('Optmization ended at ' + opt_end)
        
        const res_send = moment().format('DD/MM/YYYY h:mm a');
        console.log('Response sent at ' + res_send)
        return res.send(result)

    }catch(err){
        console.error(err)
        return res.status(500).send('Server error.')
    }


});

const PORT = 3000;
app.listen(PORT, () => console.log(`Server listening port ${PORT}.`))

мой файл экосистемы PM2:

module.exports = {
  apps : [{
    name: "Asset Optimizer",
    script: "server.js",
    watch: true,
    ignore_watch: ["optimizer", "outputData", "Rplots.pdf", "nodeSender.js", "errorLog"],
    instances: "max",
    autorestart: true,
    max_memory_restart: "1G",
    exec_mode: "cluster",
    watch_options:{
      "followSymlinks": false
      }
    }
  ]}

Я запускаю сервер с помощью pm2 start ecosystem.config.js

все работает просто отлично, но эта проблема с очередью сводит меня с ума. Я пробовал много грязных подходов, включая разделение маршрутов, разделение серверов. никакого успеха.

Даже если вы не знаете ответа на этот вопрос, пожалуйста, дайте мне несколько идей о том, как решить эту проблему. Большое спасибо.

ОБНОВЛЕНИЕ

Хорошо, мне удалось заставить это работать с собственным модулем кластера, установив:

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

cluster.schedulingPolicy = cluster.SCHED_RR;

Но как только я пытаюсь заставить pm2 запустить сервер, он больше не работает. Можно ли заставить pm2 принять подход Round Robin.

P.S.: Я использую Windows и обнаружил в документах узла, что это платформа onlu, которая не настроена по умолчанию.


person Omar Omeiri    schedule 04.07.2020    source источник


Ответы (2)


Единственным жизнеспособным решением этой проблемы было использование nginx в качестве обратного прокси и балансировщика нагрузки.

Я использовал nginx 1.18.0, и это файл конфигурации, который заставил его работать. Если кто-то сталкивается с этой проблемой, nginx + pm2 — это то, что нужно. С удовольствием уточню, если кто-то с этим столкнется. Это дало мне много работы.

worker_processes  5;
events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    upstream expressapi {
    least_conn;
    server localhost:3000;
    server localhost:3001;
    server localhost:3002;
    server localhost:3003;
    server localhost:3004;
}


    sendfile        on;

    keepalive_timeout  800;
    fastcgi_read_timeout 800;
    proxy_read_timeout 800;
    

    server {
        listen 8000;

        server_name optimizer;

        location / {
            proxy_pass http://expressapi/;
        }
        

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

}
person Omar Omeiri    schedule 16.07.2020

Как сказано выше, проблема не в PM2. Pm2 просто обрабатывает запросы, которые ему отправляются. Проблема заключается в том, что уровень выше, который отправляет запросы, он же nignx.

person Gibs LeFleur    schedule 15.10.2020