Запросы от дочернего процесса к API, вызывающие ECONNRESET - PullRequest
1 голос
/ 10 февраля 2020

Дочерний раздел процесса может быть релевантным или нет, это может быть просто количество параллельных / параллельных соединений / запросов, но даже не настолько высокое ( 50 max ).

Моя архитектура такова, что мое основное приложение запускает дочерний процесс по расписанию CRON. Каждый процесс, который порождается, проходит уникальное спортивное событие, чтобы сосредоточиться. Задание CRON основано на времени начала этого события. Если время события одинаковое, то порождение каждого дочернего процесса имеет интервал 1,2 секунд. Число дочерних процессов может быть разным, но число запущенных в любой момент времени не должно превышать 50. Каждый дочерний процесс создает новое соединение с внутренним API. Внутренний API имеет только 1 процесс, выполняющийся &, , насколько я понимаю, , не может масштабироваться с другими машинами или разветвляться дочерними процессами (, как предлагается здесь & здесь ) в качестве внутреннего API, в свою очередь , вызывает внешний API, который первоначально отбрасывал ECONNRESET с после много запросов. Поскольку я не знал природу внешних API, я поставил перед ними свой собственный, чтобы убедиться, что все запросы к внешнему интерфейсу проходят через одно соединение. Однако теперь я возвращаю ECONNRESETs из моего внутреннего API, даже если было запущено только 10 дочерних процессов.

Соединения с моим внутренним API поддерживаются , чтобы уменьшить время отклика и максимальное число сокетов 1 при использовании Ax ios. Диаграмма архитектуры ниже:

enter image description here

Дочерний процесс 'опрашивает внутренний API по расписанию, так что это возможно ( вероятно ) там параллельные запросы к нему. Однако, поскольку они создаются с интервалом не менее 1,2 секунды, я подумал, что это уменьшит вероятность параллельных запросов. В чем разница между способностью Express обрабатывать параллельных запросов и их способностью обрабатывать одновременных запросов? Как я знаю, Express может без проблем обрабатывать тысячи параллельных запросов.

ax ios. js ( worker )

module.exports = axios.create({
     baseURL: process.env.INTERNAL_API_ENDPOINT,
     httpAgent: new http.Agent({
         keepAlive: true,
         maxSockets: 1
     }),
     httpsAgent: new https.Agent({
         keepAlive: true,
         maxSockets: 1
     }),
     timeout: 60000, // 1 min timeout
     auth: {
         username: process.env.INTERNAL_API_USERNAME || 'user',
         password: process.env.INTERNAL_API_PASSWORD || 'pass'
     },
     headers: {
         Connection: 'keep-alive',
         'Content-Type': 'application/json',
         Accept: 'application/json'
     }
})

запрос. js

const API = require('./axios')

module.exports = async function(params) {
    try {
        return API.get('/api/events', { params })
    } catch(err) {
        throw err
    }
}

событие. js ( внутренний API )

const { Router } = require('express')
const external = require('../client/betting')
const router = Router()

/**
 * GET /api/events
 */
router.get('/events', async (req, res, next) => {
    const { query } = req

    try {
        // Call to External API
        const response = await external.GetEvents(query)

        res.send(response.data)
    } catch (err) {
        next(err)
    }
})

module.exports = router

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

Что может показаться проблемой здесь? Это мои параллельные запросы, которые вызывают ECONNRESETs? В этом случае я могу подумать о 3 возможных решениях ( ищет действительно лучший вариант ):

  1. Я мог бы ставить запросы в очередь на своей внутренней стороне API, как предлагается здесь
  2. Я мог бы реорганизовать свой код, чтобы не раскручивать дочерний процесс », и, следовательно, иметь только 1 процесс и впоследствии 1 соединение с API. Это не является предпочтительным, так как это большое изменение архитектуры, но оно подойдет, если это лучшее предложение
  3. Есть ли способ масштабировать мой внутренний API, где дочерний процесс может совместно использовать TCP-соединение мастера, так что, опять же, есть только 1 подключение к внешнему? Что-то вроде cluster-client и упомянутого там паттерна Лидер / Подписчик

Если ничего из этого не ясно, тогда я могу предоставить больше ясности в случае необходимости :) спасибо!

1 Ответ

0 голосов
/ 10 февраля 2020

Если я правильно читаю ваш вопрос, проблема заключается в строгом ограничении «внешнего API», которое является узким местом для вашего приложения.

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

Для начальной реализации я бы рассмотрел ваш первый подход:

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

I go сделает внутренний API реагирующим, чтобы он мог читать из очереди или потока событий. enter image description here

В этой архитектуре ваши работники ставят в очередь событие и затем продолжают. Внутренний API прослушивает события в очереди, он может либо извлекать отдельные события одно за другим, и каждое событие отправляет запрос на внешний API, либо, если вы начинаете перегружать внешний API, вы можете начинать пакетные события (ie pull 100 событий или за некоторый интервал).

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

...