간단한 변경으로 Express 서버에서 최대 300 % 향상된 성능.
원본 : https://itnext.io/how-json-stringify-killed-my-express-server-d8d0565a1a61
Express는 서버를 만들어야 할 때 가장 많이 사용되는 node.js 프레임 워크 중 하나입니다.
다음은 작은 정적 JSON 응답을 리턴 하는 하나의 엔드 포인트만 있는 단순 Express 서버의 예입니다.
const express = require('express') const app = express() const json = {a:1} app.get('/not_cached', (req,res)=>res.status(200).json(json)) app.listen(3000, ()=>console.log('Server started'))
위의 코드를 실행하고 여러 번 autocannon을 사용하여 벤치마킹 하면 2018 MacBook Pro에서 실행되는 서버가 11 초 만에 약 190K 요청을 처리합니다 ~ = 1900 RPS
➜ autocannon http://localhost:3000/not_cached
우리는 더 잘할 수 있습니다!
이 예제에는 코드가 거의 없기 때문에 소스 코드 표현, 응답 객체에 대한 json 함수의 정의 (전체 코드는 다음 위치에 있음)를 더 나은 성능으로 볼 수 있는 곳은 한 곳 뿐입니다.
https://github.com/expressjs/express/blob/master/lib/response.js
res.json = function json(obj) { var val = obj; // allow status / body if (arguments.length === 2) { // res.json(body, status) backwards compat if (typeof arguments[1] === 'number') { deprecate('res.json(obj, status): Use res.status(status).json(obj) instead'); this.statusCode = arguments[1]; } else { deprecate('res.json(status, obj): Use res.status(status).json(obj) instead'); this.statusCode = arguments[0]; val = arguments[1]; } } // settings var app = this.app; var escape = app.get('json escape') var replacer = app.get('json replacer'); var spaces = app.get('json spaces'); var body = stringify(val, replacer, spaces, escape) // content-type if (!this.get('Content-Type')) { this.set('Content-Type', 'application/json'); } return this.send(body); };
가장 중요한 부분은 22 행에서 엄격하게 발생합니다. 사용하는 모든 res.json에 대해 반환 된 값은 string 화 되어 http 응답으로 전송됩니다. 데이터를 문자열 화 한 후 컨텐츠 유형이 설정되고 응답이 전송됩니다.
JSON.stringify는 CPU와 결합 된 작업이며 노드의 가장 친한 친구가 아니므로 한 번만 시도해 봅시다.
결과를 문자열 화하고 변수에 저장할 수 있으며, 들어오는 각 요청에 대해 content-type을 application / json으로 설정하고 end 메소드를 사용하여 문자열을 소켓에 직접 쓸 수 있습니다.
const express = require('express') const app = express() const stringifedJson = JSON.stringify({a:1}) app.get('/cached', (req,res)=>{ res.setHeader('Content-Type', 'application/json'); res.end(stringifedJson) }) app.listen(3000, ()=>console.log('Server started'))
autocannon를 다시 실행하면 11 초 ~ = 3500 RPS로 약 350K 요청이 발생합니다. 80 % 개선
그러나 당신이 말하면, 당신은 나에게 300 % 개선을 약속했습니다! 그리고 당신은 옳을 것입니다!
성능 차이는 반환 된 객체에 따라 크게 다릅니다. 작은 물체의 작은 변화조차도 중요하다는 것을 보여주고 싶었습니다.
큰 json 객체 (예 : 500–600 Kb)로 동일한 작업을 수행하면 성능이 향상됩니다. 실제로 res.json을 사용하면 실제로 kubernetes에서 실행되는 컨테이너와 같은 제한된 환경에서 서버가 충돌 할 수 있습니다.
결론
Express를 사용할 때 서버의 RPS 성능이 좋지 않으면 공유 응답을 캐시하고 매번 JSON.stringify를 사용하는 res.json을 사용하는 대신 문자열을 응답 스트림에 직접 쓰십시오.
등록된 댓글이 없습니다.