Javascript-форум (https://javascript.ru/forum/)
-   Node.JS (https://javascript.ru/forum/node-js-io-js/)
-   -   Падает localhost (https://javascript.ru/forum/node-js-io-js/80002-padaet-localhost.html)

SatanSeal 16.04.2020 16:04

Падает localhost
 
Настраиваю rest api на node.js с использованием express, postgreSQL, webpack и handlebars. Возникла следующая проблема: после 5-10 переходов по ссылкам внутри сайта, страница перестает загружаться, во вкладке network хрома (забегая вперед, в firefox проблема та же) висит статус pending, а после 4 минут ожидания выдает net::err_empty_response. В консоли тишина. Рестарт сервера помогает помогает опять на 5-10 переходов. Не понимаю в чем дело.

app.js:

const express =require('express'),
      pg = require('pg'),
      path = require('path'),
      exphbs = require('express-handlebars'),
      bodyParser = require('body-parser'),
      app = express();

var baseSize;
var page;
var booksPerPage = 3;

const hbs = exphbs.create({
    extname: 'hbs', 
    defaultLayout: 'main', 
    layoutsdir: __dirname + '/views/Layouts',

    helpers: {
        pagination: function(index) {
            if (index >= (page-1) * booksPerPage &&  index < (page * booksPerPage)) {
                return true;
            } else {
                return false;
            };
        }
    }

});


app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.set('views', path.join(__dirname, 'views'));
app.engine('hbs', hbs.engine);
app.set('view engine', 'hbs');
app.use(express.static('public'));

const { Pool } = require('pg');
const pool = new Pool({
    host: 'localhost',
    user: 'bookAdmin',
    database: 'Books',
    password: '666',
    port: 5432,
});

app.get('/', (req, res) => {
    res.render('index', {
        style: 'index1.css'
    });
});

app.get('/page=:page', (req, res) => {
    pool.connect((err, client, release) => {
        if (err) {
            return console.error('Error acquiring client', err.stack)
        }
        client.query('SELECT * from "Books" ORDER BY id', (err, result) => {
            if (err) {
                return console.error('Error executing query', err.stack)
            }
            baseSize = (result.rows).length;
            page = req.params.page;
            res.render('pagIndex', {
                Books: result.rows,
                style: 'index.css',
                baseSize: baseSize,
                booksPerPage: booksPerPage
            });
        })
    })
});

app.listen(3000, function(){
    console.log('serv started');
});

Nexus 16.04.2020 16:12

Дебажте. Расставьте console.log на ключевые позиции и смотрите на каком этапе у вас отваливается процесс.

Nexus 16.04.2020 16:28

У вас на каждый запрос к странице «/page=:page» происходит соединение пула соединений с DB, при этом пул соединения не закрывает.

Возможно у меня недостаточно компетенции, но задам вопросы, которые у меня возникли:
1. При повторной попытке соединения пула к бд закрываются ли предыдущие соединения?
2. Не слишком ли затратно на каждый запрос соединятся с БД?
3. Почему вы не закрываете соединение вручную, если каждый запрос пытаетесь подключится к БД?

Я думаю проблема в том, что у Вас просто превышается лимит соединений с Pg, поэтому ничего не работает.
Из этого следует, что используемый Вами драйвер не закрывает пул соединений перед попыткой повторно подключится к БД или создает и возвращает новый пул соединений.
Непонятно, почему при ошибке подключения к бд нет уведомления о проблеме от драйвера.
Под драйвером я подразумеваю библиотеку "pg".

SatanSeal 16.04.2020 16:44

Действительно!
Вы правы в том, что превышается лимит клиентов. серв падает после 10 переходов потому, что по дефолту в пуле 10 соединений максимум.
Просто это мой первый api, поэтому писал не сильно вдаваясь в подробности соединений.
Спасибо Вам огромное! буду разбираться с соединениями

Nexus 16.04.2020 16:45

Почитал доку «npm pg».
pool.connect - возвращает или создает нового клиента для работы с бд, если пул полон, то драйвер будет ожидать освобождения одного из клиентов.
Цитата:

Acquires a client from the pool. If the pool is 'full' and all clients are currently checked out, this will wait in a FIFO queue until a client becomes available by it being released back to the pool. If there are idle clients in the pool it will be returned to the callback on process.nextTick. If the pool is not full a new client will be created & returned to this callback.
Вы в своем коде постоянно запрашиваете нового клиента из пула, но не освобождаете его после того, как он перестает Вам быть нужным.
Через несколько запросов вы вытаскиваете из пула все соединения и в итоге pool.connect Вам ничего не возвращает, Вы просто остаетесь в вечной FIFO очереди.

Nexus 16.04.2020 16:47

Воспользуйтесь лучше методом пула «query».
Я думаю вам он идеально подойдет.

SatanSeal 16.04.2020 16:57

Сотню плюсов вам в карму!
на стэковерфлоу даже смотреть не стали, а самому понять опыта не хватает. уже неделю бьюсь в стену..
Теперь буду химичить с пулами

SuperZen 17.04.2020 10:54

app.get ждет что будет "возвращен" res, судя по тому что там написано, этого не происходит, независимо от того создается пул или нет при каждом запросе... )

Nexus 17.04.2020 12:19

Цитата:

Сообщение от SuperZen
app.get ждет что будет "возвращен" res

Можете привести цитату из документации, где это указано?

SuperZen 17.04.2020 18:17

https://expressjs.com/en/guide/routing.html
Routing refers to how an application’s endpoints (URIs) respond to client requests.
...
Response methods
The methods on the response object (res) in the following table can send a response to the client, and terminate the request-response cycle. If none of these methods are called from a route handler, the client request will be left hanging.


Часовой пояс GMT +3, время: 06:15.