При ожидании HTTPS-запроса цикл событий зависает и не отвечает на проверку работоспособности — NodeJS+kubernetes

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

Краткое текстовое объяснение:

Worker берет задание из очереди, использует модуль и передает ему всю необходимую информацию. Затем модуль отправляет Promise.all для всех запросов другому микросервису с помощью axios. Затем этот микросервис делает еще один https-запрос к службе, которую я не контролирую, что очень часто занимает много времени для ответа (1-10 минут). Сервис должен вернуть документ, который микросервис затем вернет в модуль, используемый воркером.

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

Код:

Рабочий модуль:

const axios = require('axios');
const { getVariableValue } = require("redacted");
const logger = require('redacted');
const https = require('https')

module.exports = webApiOptiDocService = {

    async getDocuments(docIDs, transactionId, timeStamp) {

        try {

            var documents = [];

            await Promise.all(docIDs.map(async (docID) => {

                var document = await axios.post(getVariableValue("GET_DOCUMENT_SERVICE_URL"), docID, {
                    httpsAgent: new https.Agent({
                        rejectUnauthorized: false,
                        keepAlive: true
                    }),
                    auth: {
                        username: getVariableValue("WEBAPI_OPTIDOCS_SERVICE_USERNAME"),
                        password: getVariableValue("WEBAPI_OPTIDOCS_SERVICE_PASSWORD")
                    },
                    headers: {
                        "x-global-transaction-id": transactionId,
                        "timeStamp": timeStamp
                    }

                });

                documents.push(document.data.content);

            }));

            return documents

        }
        catch (err) {

            const responseData = err.response ? err.response.data : err.message

            throw Error(responseData)

        }

    }

}

Это микросервис, который затем получает следующие запросы:

API:

const express = require('express');
const router = express.Router();
const logger = require('redacted');
const getDocuemntService = require('./getDocumentService')
var clone = require('clone')

module.exports = router.post('/getDocument', async (req, res, next) => {

    try {

        var transactionId = req.headers["x-global-transaction-id"]

        var timeStamp = req.headers["timestamp"]

        var document = await getDocuemntService(req.body, transactionId, timeStamp);

        var cloneDocument = clone(document)

        res.status(200);

        res.json({
            statusDesc: "Success",
            status: true,
            content: cloneDocument
        });

    }
    catch (err) {

         res.status(500).send("stack: " + err.stack + "err: " + err.message + " fromgetdocument")

    }

});


Это модуль getDocument.js, который он затем использует:

const axios = require('axios');
const { getVariableValue } = require("redacted");
const logger = require('redacted');
const https = require('https')
const fileType = require('file-type')
var request = require('request-promise-native')

module.exports = async (docID, transactionId, timeStamp) => {

    try {



        var startTime = Date.now();



        const documentBeforeParse = await request.get(getVariableValue("WEBAPI_OPTIDOCS_SERVICE_URL_GET") + docID.docID, {

            strictSSL: false,
            headers: {
                'x-global-transaction-id': transactionId
            },
            timeout: Infinity
        }).auth(getVariableValue("WEBAPI_OPTIDOCS_SERVICE_USERNAME"), getVariableValue("WEBAPI_OPTIDOCS_SERVICE_PASSWORD"))
        const parsedDocument = JSON.parse(documentBeforeParse)

        var document = {
            data: {
                mimeType: parsedDocument.mimeType,
                fileName: "",
                content: parsedDocument.content
            }
        }

        // const document = await axios.get(getVariableValue("WEBAPI_OPTIDOCS_SERVICE_URL_GET") + docID.docID, {
        //     maxContentLength: 524288000, //500 MB in Bytes
        //     maxBodyLength: 524288000, //500 MB in Bytes
        //     method: 'get',
        //     httpsAgent: new https.Agent({
        //         rejectUnauthorized: false
        //     }),
        //     auth: {
        //         username: getVariableValue("WEBAPI_OPTIDOCS_SERVICE_USERNAME"),
        //         password: getVariableValue("WEBAPI_OPTIDOCS_SERVICE_PASSWORD")
        //     },
        //     headers: {
        //         'x-global-transaction-id': transactionId
        //     }
        // });

        if (document.data.mimeType == "") {

            if (recoverMimeType(document.data.content)) {

                document.data.mimeType = recoverMimeType(document.data.content).ext

            }
            else {

                throw Error("Missing mime type can not be recovered.")

            }

        }

        var fixedMimeType = fixMimeType(document.data.mimeType);

        document.data.fileName = docID.docPartsPrefixName + fixedMimeType

        var returnDocument = {
            fileName: document.data.fileName,
            content: document.data.content,
            mimeType: document.data.mimeType
        }

        return returnDocument;

    }
    catch (error) {

        throw Error(error);

    }

}

function fixMimeType(mimeType) {
    return "." + mimeType
}

function recoverMimeType(content) {

    return fileType.fromBuffer(Buffer.from(content[0], "base64"))

}

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

В основном микросервис получает 50-150 запросов через Promise.all, и после получения довольно большого количества запросов он в конечном итоге умирает на очень медленных ответах, потому что он не отвечает на проверки работоспособности.


person adame21    schedule 21.01.2020    source источник


Ответы (2)


Для тех, кто натыкается на это и ищет ответ, то, что я, наконец, исправил, резко увеличил объем памяти, который мое приложение получало от kubernetes. кажется, это была не проблема с циклом событий, а проблема с производительностью. удачи!

person adame21    schedule 25.02.2020

В вашем рабочем модуле вы используете await с обещанием всего,

promise all работает асинхронно, а await предназначен для синхронного кода, который блокирует цикл обработки событий.

вы можете использовать ключевое слово await для вызова функций, которые возвращают обещания для их синхронной работы

PFA для асинхронного/ожидающего использования

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

person Manasi Agte    schedule 21.01.2020
comment
Привет, спасибо за ответ! Я просмотрел вашу ссылку и, прежде чем задать этот вопрос, я изучил всю асинхронность/ожидание. Я видел это: stackoverflow.com/questions/46004290/ что заставило меня поверить, что это не то, что происходит. Если это так, есть идеи, как я могу это решить? - person adame21; 21.01.2020