#javascript #node.js #reactjs #autoscaling
#javascript #node.js #reactjs #автоматическое масштабирование
Вопрос:
У меня есть сервер, написанный на node, который использует mysql в качестве своей базы данных, а интерфейс написан на react. Мое приложение размещено на выделенном сервере с процессором с 4 ядрами. Интерфейс должен загружать коэффициенты крикета, для которых я использую сторонний API. Приложение react отправляет запрос на мой сервер узла в соответствии с идентификатором соответствия, а затем сервер отправляет запрос стороннему API и получает коэффициенты, а затем передает их интерфейсу. Код выглядит следующим образом:
router.get('/getSession/:matchId',(req,res)=>{
axios.get('http://178.62.105.201/api/v1/listMarketBookSession?match_id=' req.params.matchId)
.then(response => {
return res.status(200).json({
success:true,
data:response.data
})
})
.catch(error=>{
console.log(error);
return res.status(200).json({
success:false,
data:[]
})
});
})
Запрос отправляется каждые 500 мс. Приложение работает нормально, когда пользователей меньше. Когда число пользователей увеличилось до 400, он некоторое время отправляет ошибку 502, а затем снова начинает получать ответ. Это происходит в цикле.
GET example.com/oddsApi/getSession/30189407 502
(anonymous) @ 2.e2450141.chunk.js:2
e.exports @ 2.e2450141.chunk.js:2
e.exports @ 2.e2450141.chunk.js:2
Promise.then (async)
s.request @ 2.e2450141.chunk.js:2
r.forEach.s.<computed> @ 2.e2450141.chunk.js:2
(anonymous) @ 2.e2450141.chunk.js:2
value @ main.7f6055f1.chunk.js:1
setTimeout (async)
(anonymous) @ main.7f6055f1.chunk.js:1
Promise.catch (async)
value @ main.7f6055f1.chunk.js:1
setTimeout (async)
(anonymous) @ main.7f6055f1.chunk.js:1
Promise.catch (async)
value @ main.7f6055f1.chunk.js:1
main.7f6055f1.chunk.js:1 TypeError: Cannot read property 'data' of undefined
at main.7f6055f1.chunk.js:1
Когда я зарегистрировал эту ошибку на сервере, он печатает:
{ Error: connect ETIMEDOUT 178.62.105.201:80
0|app | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1107:14)
0|app | errno: 'ETIMEDOUT',
0|app | code: 'ETIMEDOUT',
0|app | syscall: 'connect',
0|app | address: '178.62.105.201',
0|app | port: 80,
0|app | config:
0|app | { url:
0|app | 'http://178.62.105.201/api/v1/listMarketBookSession?match_id=30189407',
0|app | method: 'get',
0|app | headers:
0|app | { Accept: 'application/json, text/plain, */*',
0|app | 'User-Agent': 'axios/0.20.0' },
0|app | transformRequest: [ [Function: transformRequest] ],
0|app | transformResponse: [ [Function: transformResponse] ],
0|app | timeout: 0,
0|app | adapter: [Function: httpAdapter],
0|app | xsrfCookieName: 'XSRF-TOKEN',
0|app | xsrfHeaderName: 'X-XSRF-TOKEN',
0|app | maxContentLength: -1,
0|app | maxBodyLength: -1,
0|app | validateStatus: [Function: validateStatus],
0|app | data: undefined },
0|app | request:
0|app | Writable {
0|app | _writableState:
0|app | WritableState {
0|app | objectMode: false,
0|app | highWaterMark: 16384,
0|app | finalCalled: false,
0|app | needDrain: false,
0|app | ending: false,
0|app | ended: false,
0|app | finished: false,
0|app | destroyed: false,
0|app | decodeStrings: true,
0|app | defaultEncoding: 'utf8',
0|app | length: 0,
0|app | writing: false,
0|app | corked: 0,
0|app | sync: true,
0|app | bufferProcessing: false,
0|app | onwrite: [Function: bound onwrite],
0|app | writecb: null,
0|app | writelen: 0,
0|app | bufferedRequest: null,
0|app | lastBufferedRequest: null,
0|app | pendingcb: 0,
0|app | prefinished: false,
0|app | errorEmitted: false,
0|app | emitClose: true,
0|app | autoDestroy: false,
0|app | bufferedRequestCount: 0,
0|app | corkedRequestsFree: [Object] },
0|app | writable: true,
0|app | _events:
0|app | [Object: null prototype] {
0|app | response: [Function: handleResponse],
0|app | error: [Function: handleRequestError] },
0|app | _eventsCount: 2,
0|app | _maxListeners: undefined,
0|app | _options:
0|app | { maxRedirects: 21,
0|app | maxBodyLength: 10485760,
0|app | protocol: 'http:',
0|app | path: '/api/v1/listMarketBookSession?match_id=30189407',
0|app | method: 'GET',
0|app | headers: [Object],
0|app | agent: undefined,
0|app | agents: [Object],
0|app | auth: undefined,
0|app | hostname: '178.62.105.201',
0|app | port: null,
0|app | nativeProtocols: [Object],
0|app | pathname: '/api/v1/listMarketBookSession',
0|app | search: '?match_id=30189407' },
0|app | _ended: true,
0|app | _ending: true,
0|app | _redirectCount: 0,
0|app | _redirects: [],
0|app | _requestBodyLength: 0,
0|app | _requestBodyBuffers: [],
0|app | _onNativeResponse: [Function],
0|app | _currentRequest:
0|app | ClientRequest {
0|app | _events: [Object],
0|app | _eventsCount: 7,
0|app | _maxListeners: undefined,
0|app | output: [],
0|app | outputEncodings: [],
0|app | outputCallbacks: [],
0|app | outputSize: 0,
0|app | writable: true,
0|app | _last: true,
0|app | chunkedEncoding: false,
0|app | shouldKeepAlive: false,
0|app | useChunkedEncodingByDefault: false,
0|app | sendDate: false,
0|app | _removedConnection: false,
0|app | _removedContLen: false,
0|app | _removedTE: false,
0|app | _contentLength: 0,
0|app | _hasBody: true,
0|app | _trailer: '',
0|app | finished: true,
0|app | _headerSent: true,
0|app | socket: [Socket],
0|app | connection: [Socket],
0|app | _header:
0|app | 'GET /api/v1/listMarketBookSession?match_id=30189407 HTTP/1.1rnAccept: application/json, text/plain, */*rnUser-Agent: axios/0.20.0rnHost: 178.62.105.201rnConnection: closernrn',
0|app | _onPendingData: [Function: noopPendingOutput],
0|app | agent: [Agent],
0|app | socketPath: undefined,
0|app | timeout: undefined,
0|app | method: 'GET',
0|app | insecureHTTPParser: undefined,
0|app | path: '/api/v1/listMarketBookSession?match_id=30189407',
0|app | _ended: false,
0|app | res: null,
0|app | aborted: undefined,
0|app | timeoutCb: null,
0|app | upgradeOrConnect: false,
0|app | parser: null,
0|app | maxHeadersCount: null,
0|app | _redirectable: [Circular],
0|app | [Symbol(isCorked)]: false,
0|app | [Symbol(outHeadersKey)]: [Object] },
0|app | _currentUrl:
0|app | 'http://178.62.105.201/api/v1/listMarketBookSession?match_id=30189407' },
0|app | response: undefined,
0|app | isAxiosError: true,
0|app | toJSON: [Function: toJSON] }
Код для вызова коэффициентов:-
getOdds() {
axios.get('/getSession/' this.props.eventId)
.then(response => {
if (response amp;amp; response.data.data.length amp;amp; response.data.data[0] !== "n") {
response.data.data.sort((a,b)=>a.SelectionId-b.SelectionId)
this.setState({ sessions: response.data.data });
if (this.flag)
this.intervalID = setTimeout(this.getOdds.bind(this), 300);
}
else if (!response.data.data.length) {
this.setState({ sessions: null });
}
})
.catch(error => {
if (this.flag)
this.intervalID = setTimeout(this.getOdds.bind(this), 500);
console.log(error);
})
}
который вызывается в componentDidMount
componentDidMount() {
this.getOdds();
}
Я также попытался зарегистрировать продолжительность ответа. Продолжительность времени была переменной. Ниже приведены некоторые ответы
Market.js:80 1752
Market.js:80 390
Market.js:80 310
Market.js:80 722
Market.js:80 16002
Market.js:80 15326
Market.js:80 330
Market.js:80 1758
Market.js:80 1144
Market.js:80 308
Market.js:80 709
Market.js:80 324
Market.js:80 351
Market.js:80 647
Market.js:80 375
Market.js:80 406
Market.js:80 701
Market.js:80 345
Market.js:80 1776
Market.js:80 1187
Market.js:80 414
Market.js:80 715
Market.js:80 20327
Как вы можете видеть, иногда для получения ответа требуется около 20 секунд, что вызывает у меня кошмар. Когда я связался со сторонним поставщиком API, они сказали мне, что их API может обрабатывать более 20000 пользователей. Я не могу устранить проблему. Возможно, я недостаточно хорошо подготовил свое приложение к масштабированию. Пожалуйста, помогите!
Комментарии:
1. Можете ли вы показать нам, как вы вызываете
getOdds
функцию?2. Было бы полезно увидеть шкалу производительности или диаграмму вашего сервера, если он достиг 400 пользователей. Я не являюсь администратором сервера, но я предполагаю, что если до 400 пользователей запускают все правильно, а от 400 не более, это может быть проблемой с производительностью. Конечно, тогда это должно быть перехвачено где-нибудь в коде вашего запроса.
3. getOdds вызывается в componentDidMount
4. Проверьте, выполняется ли ваш sql-запрос
count(*)
. Если это так, это может быть виновником.5. я не могу понять ваше решение @t348575