SlideShare a Scribd company logo
1 of 87
Download to read offline
API 서버
성능 개선기
Outsider
2017.11.09 @ play.node
얘기할 내용
✓성능 테스트를 위한 준비
✓성능 테스트의 도구
✓성능 테스트의 결과 분석
얘기안할 내용
✓코드의 성능 개선
✓코드 작성 팁
✓잘못된 코드
인증 API 서버
https://flic.kr/p/4qLTdZ
인증 API 서버
https://flic.kr/p/4qLTdZ
✓ 회원 가입
✓ 로그인
✓ 권한부여
✓ 회원 정보 관리
https://flic.kr/p/4qLTdZ
왜 성능 테스트를?
✓ 서버 하나의 한계 파악
✓ 병목구간 확인
✓ 코드 개선 후 비교
Unit test에서도 확인 가능하지만
실제 트래픽과 유사한
성능이 궁금했다.
성능 테스트 도구
https://flic.kr/p/3jHfGs
✓ 사용자 시나리오로 작성
✓ 대량 트래픽 조절 가능
✓ 가능하면 Node.js로 사용
https://artillery.io/
Node.js 작성된 부하 테스트 도구
config:
target: 'http://localhost:3000'
http:
timeout: 20
phases:
-
duration: 240
arrivalCount: 8
name: "Warm-up"
-
duration: 240
arrivalCount: 24
-
duration: 240
arrivalCount: 48
-
duration: 600
arrivalCount: 150
-
duration: 240
arrivalCount: 48
-
duration: 240
arrivalCount: 24
processor: "./processor.js"
payload:
path: './payload.csv'
fields:
- 'email'
- 'password'
order: 'sequence'
YML
duration: 240
arrivalCount: 24
240초동안 24 유저(시나리오)를 생성한다.
-> 4분동안 10초에 한명씩 새로운 유저를 생성한다.
scenarios:
- name: ‘사용자 흐름'
flow:
# 회원 가입
- post:
url: '/signup'
json:
email: '{{ email }}'
password: '{{ password }}'
# 로그인
- post:
url: '/login'
json:
email: '{{ email }}'
password: '{{ password }}'
capture:
- json: '$.data.token'
as: 'token'
# 정보조회
- get:
url: '/user/info'
headers:
Authorization: 'Bearer {{ token }}'
#!/usr/bin/env node
const fs = require('fs');
const ROWS = process.env.PAYLOAD || 10000;
const FILE_NAME = './test/payload.csv'
fs.writeFileSync(FILE_NAME, '');
for(let i = 0; i < ROWS; i++) {
const u = generateUser();
fs.appendFileSync(FILE_NAME, `${u.email},${u.password}n`);
}
테스트 데이터 생성
{
"scripts": {
"preloadtest": "./test/generate-payloads",
"loadtest": "artillery run test/config.yml"
}
}
package.json
{
"scripts": {
"preloadtest": "./test/generate-payloads",
"loadtest": "artillery run test/config.yml"
}
}
package.json
$ npm run loadtest
$ artillery report 
artillery_report_20171103_185907.json
APM
: Application Performance Management
https://flic.kr/p/3bkGjq
대부분 유료
#!/usr/bin/env bash
curl -X POST 
’https://api.newrelic.com/v2/applications/APPID/deployments.json' 
-H ‘X-Api-Key:YOUR_API_KEY’ -i 
-H 'Content-Type: application/json' 
-d 
'{
"deployment": {
"revision": "1",
"changelog": "'"${MACHINE_ID} start"'",
"description": "'"${MACHINE_ID} start"'",
"user": “YOUR_EMAIL"
}
}'
New relic 배포 플래그
{
"scripts": {
"preloadtest": “./test/generate-payloads && ./test/mark-ended.sh",
"loadtest": "artillery run test/config.yml",
"portloadtest": "./test/mark-ended.sh"
}
}
package.json
테스트 서버 구성
https://flic.kr/p/3bkGjq
RDS
ECS cluster
Elastic
Load Balancer
HTTP
Request
타겟 서버
#!/bin/env ruby
Vagrant.configure(2) do |config|
config.vm.box = 'dummy'
TEST_MACHINE_COUNT = 1
1.upto(TEST_MACHINE_COUNT) do |i|
config.vm.define "test-machine-#{i}" do |machine|
machine.vm.provider :aws do |aws, override|
aws.tags = { 'Name' => "test-machine-#{i}" }
aws.access_key_id = ENV['AWS_ACCESS_KEY_ID']
aws.secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
aws.keypair_name = 'test'
aws.subnet_id = 'subnet-xxxxxx'
aws.instance_type = 'c4.xlarge'
aws.region = 'ap-northeast-1'
aws.ami = 'ami-ea4eae8c' # Ubuntu 16.04
aws.security_groups = ['sg-xxxxxx', 'sg-xxxxxx']
override.ssh.username = 'ubuntu'
override.ssh.private_key_path = '~/.ssh/test.pem'
override.ssh.pty = false
override.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'"
end
machine.nfs.functional = false
machine.vm.synced_folder '../', '/www', type: "rsync", rsync__exclude: "node_modules/"
machine.vm.provision "shell" do |s|
s.inline = "export MACHINE_ID=$1 && sudo apt-get update && sudo apt-get install -y python"
s.args = ["test-machine-#{i}"]
end
machine.vm.provision "ansible" do |ansible|
ansible.groups = {
"testnode" => ["test-machine-[0:#{$TEST_MACHINE_COUNT}]"]
}
ansible.playbook = './playbook.yml'
end
end
end
end
Vagrantfile
machine.vm.provider :aws do |aws, override|
aws.tags = { 'Name' => "test-machine-#{i}" }
aws.access_key_id = ENV['AWS_ACCESS_KEY_ID']
aws.secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
aws.keypair_name = 'test'
aws.subnet_id = 'subnet-xxxxxx'
aws.instance_type = 'c4.xlarge'
aws.region = 'ap-northeast-1'
aws.ami = 'ami-ea4eae8c' # Ubuntu 16.04
aws.security_groups = ['sg-xxxxxx', 'sg-xxxxxx']
override.ssh.username = 'ubuntu'
override.ssh.private_key_path = '~/.ssh/test.pem'
override.ssh.pty = false
override.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'"
end
machine.vm.synced_folder '../../', '/www',
type: "rsync", rsync__exclude: "node_modules/"
machine.vm.provision "shell" do |s|
s.inline = "export MACHINE_ID=$1 && sudo apt-get update && sudo
apt-get install -y python”
s.args = ["test-machine-#{i}"]
end
machine.vm.provision "ansible" do |ansible|
ansible.groups = {
"testnode" => ["test-machine-[0:#{$TEST_MACHINE_COUNT}]"]
}
ansible.playbook = './playbook.yml'
end
- name: Install prerequistes
become: yes
hosts:
- all
tasks:
- name: install node.js
shell: curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
- name: install apt packages
apt:
name: "{{ item }}"
update_cache: yes
with_items:
- nodejs
- name: install "artillery" nodejs package
npm:
name: artillery
version: '1.5.8-3'
path: /www
ansible: playbook.yml
$ vagrant plugin install vagrant-aws
플러그인 설치
서버 실행
$ vagrant up
부하 테스트 실행
$ ansible all -m shell -a "cd /www && npm run loadtest"
서버 종료
$ vagrant destroy
생각보다 서버 성능이...
https://flic.kr/p/4Ast6N
✓ 클러스터 인스턴스 변경
✓ 컨테이너 CPU, 메모리 조정
✓ DB Pool 사이즈 조정
테스트 결과
scenarios:
- name: ‘사용자 흐름'
flow:
# 회원 가입
- post:
url: '/signup'
json:
email: '{{ email }}'
password: '{{ password }}'
# 로그인
- post:
url: '/login'
json:
email: '{{ email }}'
password: '{{ password }}'
capture:
- json: '$.data.token'
as: 'token'
# 정보조회
- get:
url: '/user/info'
headers:
Authorization: 'Bearer {{ token }}'
# 정보 갱신
- patch:
url: '/user/info'
headers:
Authorization: 'Bearer {{ token }}'
json:
field1: 'blah blah'
field2: 'blah blah’
1 시나리오
총 890 요청
200 응답: 818
201 응답: 32
202 응답: 40
시나리오당 20초 정도
scenarios:
- name: ‘사용자 흐름'
flow:
# 회원 가입
- post:
url: '/signup'
json:
email: '{{ email }}'
password: '{{ password }}'
# 로그인
- post:
url: '/login'
json:
email: '{{ email }}'
password: '{{ password }}'
capture:
- json: '$.data.token'
as: 'token'
# 정보조회
- get:
url: '/user/info'
headers:
Authorization: 'Bearer {{ token }}'
# 정보 갱신
- patch:
url: '/user/info'
headers:
Authorization: 'Bearer {{ token }}'
json:
field1: 'blah blah'
field2: 'blah blah’
- 4분간 60초마다 1 유저
- 4분간 20초마다 1 유저
- 4분간 10초마다 1 유저
- 6분간 6초마다 1 유저
- 10분간 4초마다 1 유저
- 4분간 10초마다 1 유저
- 4분간 20초마다 1 유저
node.js V8
6.11.5 5.1.281.108
8.9.0 6.1.534.46
V8의 컴파일러는 Crankshaft
5.9 부터는 Ignition + Turbofan
10% 이상의 성능 향상
https://v8project.blogspot.kr/2017/05/launching-ignition-and-turbofan.html
RDS
ECS cluster
Elastic
Load Balancer
HTTP
Request
RDSnode 8.x
node 6.x
Elastic
Load Balancer
HTTP
Request
테스트 서버 1대
node 6.11.5 node 8.9.0
테스트 서버 1대
node 6.11.5 node 8.9.0
테스트 서버 2대
node 6.11.5 node 8.9.0
테스트 서버 1대
node 6.11.5 node 8.9.0
성능 병목 구간
유료 기능.....
프로파일링
$ node --inspect ./bin/www
Debugger listening on ws://127.0.0.1:9229/77128b6e-fe32-4da9-a1db
For help see https://nodejs.org/en/docs/inspector
Debugger attached.
node --inspect YOUR_APP.js
chrome://inspect
chrome-devtools
Heavy (Bottom Up)
Frame Chart
Frame Chart
Frame Chart
$ node --prof ./bin/api
V8 Tick Profiler
isolate-0x103800000-v8.log
$ node --prof-process isolate-0x103800000-v8.log > processed.txt
dropping: overflow
Code move event for unknown code: 0x2a2f8121cac0
Code move event for unknown code: 0x2a2f8124f9a0
Code move event for unknown code: 0x2a2f81254ae0
V8 Tick Processor
Statistical profiling result from isolate-0x103800000-v8.log, (147930 ticks, 31582 unaccounted, 0 excluded).
[Shared libraries]:
ticks total nonlib name
783 0.5% /usr/lib/system/libsystem_pthread.dylib
735 0.5% /usr/lib/system/libsystem_platform.dylib
[JavaScript]:
ticks total nonlib name
3358 2.3% 2.3% LoadIC: A load IC from the snapshot
2979 2.0% 2.0% Builtin: KeyedLoadIC_Megamorphic
1966 1.3% 1.3% Builtin: CallFunction_ReceiverIsAny
[C++]:
ticks total nonlib name
2253 1.5% 1.5% T ___channel_get_opt
1779 1.2% 1.2% T _mprotect
1545 1.0% 1.1% t v8::internal::LookupIterator::State v8::internal::LookupIterator::LookupInRegularHolder<false>(v8::internal::Map*, v8:
[Summary]:
ticks total nonlib name
60762 41.1% 41.5% JavaScript
53997 36.5% 36.9% C++
4560 3.1% 3.1% GC
1589 1.1% Shared libraries
31582 21.3% Unaccounted
[C++ entry points]:
ticks cpp total name
4305 10.3% 2.9% T v8::internal::Runtime_StoreIC_Miss(int, v8::internal::Object**, v8::internal::Isolate*)
3155 7.5% 2.1% T v8::internal::Builtin_FunctionConstructor(int, v8::internal::Object**, v8::internal::Isolate*)
[Bottom up (heavy) profile]:
Note: percentage shows a share of a particular caller in the total
amount of its parent calls.
Callers occupying less than 1.0% are not shown.
ticks parent name
31582 21.3% UNKNOWN
13500 42.7% LazyCompile: *Socket._writeGeneric net.js:708:42
11724 86.8% LazyCompile: *Writable.write _stream_writable.js:264:36
11662 99.5% LazyCompile: *Socket.write net.js:699:34
5453 46.8% Function: ~logRequest /Users/outsider/smartstudy/node_modules/morgan/index.js:116:25
processed.txt
[JavaScript]:
ticks total nonlib name
3358 2.3% 2.3% LoadIC: A load IC from the snapshot
2979 2.0% 2.0% Builtin: KeyedLoadIC_Megamorphic
1966 1.3% 1.3% Builtin: CallFunction_ReceiverIsAny
1866 1.3% 1.3% StoreIC: A store IC from the snapshot
1507 1.0% 1.0% Builtin: KeyedStoreIC_Megamorphic
1489 1.0% 1.0% Builtin: InterpreterEntryTrampoline
1341 0.9% 0.9% Builtin: FastNewClosure
1074 0.7% 0.7% Stub: GetPropertyStub
898 0.6% 0.6% Stub: StringAddStub
890 0.6% 0.6% KeyedLoadIC: A keyed load IC from the snapshot
717 0.5% 0.5% Builtin: ArgumentsAdaptorTrampoline
706 0.5% 0.5% LazyCompile: *Promise._settlePromises /Users/outsider/smartstudy/node_modules/blue
560 0.4% 0.4% LazyCompile: *emit events.js:156:44
516 0.3% 0.4% Builtin: CompileLazy
502 0.3% 0.3% Builtin: FunctionPrototypeHasInstance
492 0.3% 0.3% Builtin: ObjectHasOwnProperty
486 0.3% 0.3% StoreIC: A store IC from the snapshot {1}
472 0.3% 0.3% RegExp: (.*?)([[0-9]])
450 0.3% 0.3% LazyCompile: *<anonymous> :1:10
442 0.3% 0.3% Builtin: JSConstructStubGenericUnrestrictedReturn
425 0.3% 0.3% Builtin: RegExpPrototypeExec
398 0.3% 0.3% Builtin: KeyedStoreIC_Megamorphic_Strict
395 0.3% 0.3% Builtin: FastCloneRegExp
389 0.3% 0.3% LazyCompile: *Promise._then /Users/outsider/smartstudy/node_modules/bluebird/js/re
377 0.3% 0.3% Builtin: FastArrayPush
372 0.3% 0.3% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/pg/lib/connectio
352 0.2% 0.2% Builtin: RegExpPrototypeTest
347 0.2% 0.2% Builtin: StrictEqual
[Bottom up (heavy) profile]:
Note: percentage shows a share of a particular caller in the total
amount of its parent calls.
Callers occupying less than 1.0% are not shown.
ticks parent name
31582 21.3% UNKNOWN
13500 42.7% LazyCompile: *Socket._writeGeneric net.js:708:42
11724 86.8% LazyCompile: *Writable.write _stream_writable.js:264:36
11662 99.5% LazyCompile: *Socket.write net.js:699:34
5453 46.8% Function: ~logRequest /Users/outsider/smartstudy/node_modules/morgan/index.js:116:25
5296 97.1% Function: ~listener /Users/outsider/smartstudy/node_modules/on-finished/index.js:161
157 2.9% LazyCompile: *listener /Users/outsider/smartstudy/node_modules/on-finished/index.js:
3419 29.3% LazyCompile: *Client._pulseQueryQueue /Users/outsider/smartstudy/node_modules/pg/lib/c
3405 99.6% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/dialects/
2744 23.5% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/pg/lib/client.js:139
2363 86.1% LazyCompile: *emit events.js:156:44
380 13.8% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/bluebird/js/releas
925 6.9% LazyCompile: *clearBuffer _stream_writable.js:469:21
839 90.7% LazyCompile: *end _http_outgoing.js:726:45
839 100.0% LazyCompile: *send /Users/outsider/smartstudy/node_modules/express/lib/response.js:106
734 87.5% LazyCompile: *json /Users/outsider/smartstudy/node_modules/express/lib/response.js:2
105 12.5% Function: ~json /Users/outsider/smartstudy/node_modules/express/lib/response.js:229:
56 6.1% Function: ~Writable.uncork _stream_writable.js:302:37
56 100.0% Function: ~end _http_outgoing.js:726:45
51 91.1% Function: ~send /Users/outsider/smartstudy/node_modules/express/lib/response.js:106:
5 8.9% LazyCompile: *send /Users/outsider/smartstudy/node_modules/express/lib/response.js:1
30 3.2% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/dialects/post
30 100.0% Function: ~end _http_outgoing.js:726:45
19 63.3% LazyCompile: *send /Users/outsider/smartstudy/node_modules/express/lib/response.js:1
11 36.7% Function: ~send /Users/outsider/smartstudy/node_modules/express/lib/response.js:106:
3358 2.3% LoadIC: A load IC from the snapshot
333 9.9% LazyCompile: *emit events.js:156:44
43 12.9% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/runner.js:1
43 100.0% LazyCompile: *tryCatcher /Users/outsider/smartstudy/node_modules/bluebird/js/release
39 90.7% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/bluebird/js/rele
39 100.0% Function: ~<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/runner.j
3 7.0% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/runner.
3 100.0% LazyCompile: *tryCatcher /Users/outsider/smartstudy/node_modules/bluebird/js/rel
1 2.3% LazyCompile: *tryCatcher /Users/outsider/smartstudy/node_modules/bluebird/js/relea
1 100.0% Function: ~<anonymous> /Users/outsider/smartstudy/node_modules/bluebird/js/relea
30 9.0% Function: ~<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/runner.js:51:7
30 100.0% LazyCompile: *tryCatcher /Users/outsider/smartstudy/node_modules/bluebird/js/release
24 80.0% Function: ~<anonymous> /Users/outsider/smartstudy/node_modules/bluebird/js/release
24 100.0% LazyCompile: *tryCatcher /Users/outsider/smartstudy/node_modules/bluebird/js/rel
6 20.0% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/bluebird/js/rele
6 100.0% LazyCompile: *tryCatcher /Users/outsider/smartstudy/node_modules/bluebird/js/rel
29 8.7% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/pg/lib/connection.js
29 100.0% LazyCompile: *emit events.js:156:44
29 100.0% LazyCompile: *addChunk _stream_readable.js:261:18
29 100.0% LazyCompile: *onread net.js:576:16
22 6.6% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/util/make-k
22 100.0% LazyCompile: *emit events.js:156:44
22 100.0% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/runner.
22 100.0% LazyCompile: *tryCatcher /Users/outsider/smartstudy/node_modules/bluebird/js/rel
21 6.3% Function: ~<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/runner.js:152:
21 100.0% LazyCompile: *tryCatcher /Users/outsider/smartstudy/node_modules/bluebird/js/release
20 95.2% LazyCompile: *Promise._settlePromises /Users/outsider/smartstudy/node_modules/blue
20 100.0% LazyCompile: *processImmediate timers.js:697:26
1 4.8% LazyCompile: *Promise._settlePromiseFromHandler /Users/outsider/smartstudy/node_mo
496:56
const morgan = require('morgan');
app.use(morgan('dev'));
mogan 제거
$ npx autocannon -c 100 -H "Authorization: token" 
http://localhost:3000/api
Auto cannon 으로 비교
Stat Avg Stdve Max
Latency

(ms)
248.716 44.386 437.6
Req/Sec 398.72 40.022 472.4
Stat Avg Stdve Max
Latency

(ms)
235.728 38.748 404.4
Req/Sec 420.92 36.002 477.4
6.4.2 -> 7.4.0
node-postgres 업데이트
$ npx autocannon -c 100 -H "Authorization: token" 
http://localhost:3000/api
Auto cannon 으로 비교
Stat Avg Stdve Max
Latency

(ms)
235.728 38.748 404.4
Req/Sec 420.92 36.002 477.4
Stat Avg Stdve Max
Latency

(ms)
200.933 36.118 358.6
Req/Sec 495.78 45.058 594.8
Heap Dump
메모리 누수는 추적이 어렵다.
일주일마다 서버 재시작!!
Heap dump Heap dump
단위는 byte
Heap dump의 사이즈 = 메모리 용량
Shallow Size = 객체의 실제 크기
Retained Size = 객체의 레퍼런스가 있으면 이를 포함한 크기
Thank you

More Related Content

What's hot

What's hot (20)

[Play.node] node.js 를 사용한 대규모 글로벌(+중국) 서비스
[Play.node] node.js 를 사용한 대규모 글로벌(+중국) 서비스[Play.node] node.js 를 사용한 대규모 글로벌(+중국) 서비스
[Play.node] node.js 를 사용한 대규모 글로벌(+중국) 서비스
 
Event source 학습 내용 공유
Event source 학습 내용 공유Event source 학습 내용 공유
Event source 학습 내용 공유
 
MySQL GTID 시작하기
MySQL GTID 시작하기MySQL GTID 시작하기
MySQL GTID 시작하기
 
오픈 소스 도구를 활용한 성능 테스트 방법 및 사례
오픈 소스 도구를 활용한 성능 테스트 방법 및 사례오픈 소스 도구를 활용한 성능 테스트 방법 및 사례
오픈 소스 도구를 활용한 성능 테스트 방법 및 사례
 
[2D4]Python에서의 동시성_병렬성
[2D4]Python에서의 동시성_병렬성[2D4]Python에서의 동시성_병렬성
[2D4]Python에서의 동시성_병렬성
 
webservice scaling for newbie
webservice scaling for newbiewebservice scaling for newbie
webservice scaling for newbie
 
[D2] java 애플리케이션 트러블 슈팅 사례 & pinpoint
[D2] java 애플리케이션 트러블 슈팅 사례 & pinpoint [D2] java 애플리케이션 트러블 슈팅 사례 & pinpoint
[D2] java 애플리케이션 트러블 슈팅 사례 & pinpoint
 
[DEVIEW 2021] 1000만 글로벌 유저를 지탱하는 기술과 사람들
[DEVIEW 2021] 1000만 글로벌 유저를 지탱하는 기술과 사람들[DEVIEW 2021] 1000만 글로벌 유저를 지탱하는 기술과 사람들
[DEVIEW 2021] 1000만 글로벌 유저를 지탱하는 기술과 사람들
 
Sync async-blocking-nonblocking-io
Sync async-blocking-nonblocking-ioSync async-blocking-nonblocking-io
Sync async-blocking-nonblocking-io
 
CQRS and Event Sourcing for Java Developers
CQRS and Event Sourcing for Java DevelopersCQRS and Event Sourcing for Java Developers
CQRS and Event Sourcing for Java Developers
 
Mvcc in postgreSQL 권건우
Mvcc in postgreSQL 권건우Mvcc in postgreSQL 권건우
Mvcc in postgreSQL 권건우
 
도메인 주도 설계의 본질
도메인 주도 설계의 본질도메인 주도 설계의 본질
도메인 주도 설계의 본질
 
NGINX Back to Basics: Ingress Controller (Japanese Webinar)
NGINX Back to Basics: Ingress Controller (Japanese Webinar)NGINX Back to Basics: Ingress Controller (Japanese Webinar)
NGINX Back to Basics: Ingress Controller (Japanese Webinar)
 
예외처리가이드
예외처리가이드예외처리가이드
예외처리가이드
 
Fault Tolerance 소프트웨어 패턴
Fault Tolerance 소프트웨어 패턴Fault Tolerance 소프트웨어 패턴
Fault Tolerance 소프트웨어 패턴
 
이벤트 기반 분산 시스템을 향한 여정
이벤트 기반 분산 시스템을 향한 여정이벤트 기반 분산 시스템을 향한 여정
이벤트 기반 분산 시스템을 향한 여정
 
Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)
Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)
Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)
 
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
 
서버 성능에 대한 정의와 이해
서버 성능에 대한 정의와 이해서버 성능에 대한 정의와 이해
서버 성능에 대한 정의와 이해
 
[2D1]Elasticsearch 성능 최적화
[2D1]Elasticsearch 성능 최적화[2D1]Elasticsearch 성능 최적화
[2D1]Elasticsearch 성능 최적화
 

Viewers also liked

234 deview2013 김형준
234 deview2013 김형준234 deview2013 김형준
234 deview2013 김형준
NAVER D2
 
우글우글[1] (1)
우글우글[1] (1)우글우글[1] (1)
우글우글[1] (1)
enfkclzk00
 

Viewers also liked (12)

234 deview2013 김형준
234 deview2013 김형준234 deview2013 김형준
234 deview2013 김형준
 
AWS 기반의 마이크로 서비스 아키텍쳐 구현 방안 :: 김필중 :: AWS Summit Seoul 20
AWS 기반의 마이크로 서비스 아키텍쳐 구현 방안 :: 김필중 :: AWS Summit Seoul 20AWS 기반의 마이크로 서비스 아키텍쳐 구현 방안 :: 김필중 :: AWS Summit Seoul 20
AWS 기반의 마이크로 서비스 아키텍쳐 구현 방안 :: 김필중 :: AWS Summit Seoul 20
 
Fullstack End-to-end test automation with Node.js, one year later
Fullstack End-to-end test automation with Node.js, one year laterFullstack End-to-end test automation with Node.js, one year later
Fullstack End-to-end test automation with Node.js, one year later
 
ForwardJS 2017 - Fullstack end-to-end Test Automation with node.js
ForwardJS 2017 -  Fullstack end-to-end Test Automation with node.jsForwardJS 2017 -  Fullstack end-to-end Test Automation with node.js
ForwardJS 2017 - Fullstack end-to-end Test Automation with node.js
 
우글우글[1] (1)
우글우글[1] (1)우글우글[1] (1)
우글우글[1] (1)
 
Wolfgang hilpert scaling agile war stories - scrum germany 2017-11-17
Wolfgang hilpert   scaling agile war stories - scrum germany 2017-11-17Wolfgang hilpert   scaling agile war stories - scrum germany 2017-11-17
Wolfgang hilpert scaling agile war stories - scrum germany 2017-11-17
 
자기소개서, 이력서 쓰는 법
자기소개서, 이력서 쓰는 법자기소개서, 이력서 쓰는 법
자기소개서, 이력서 쓰는 법
 
TypeScript와 Flow: 
자바스크립트 개발에 정적 타이핑 도입하기
TypeScript와 Flow: 
자바스크립트 개발에 정적 타이핑 도입하기TypeScript와 Flow: 
자바스크립트 개발에 정적 타이핑 도입하기
TypeScript와 Flow: 
자바스크립트 개발에 정적 타이핑 도입하기
 
나의 이직 이야기
나의 이직 이야기나의 이직 이야기
나의 이직 이야기
 
시간당 수백만 요청을 처리하는 node.js 서버 운영기 - Playnode 2015
시간당 수백만 요청을 처리하는 node.js 서버 운영기 - Playnode 2015시간당 수백만 요청을 처리하는 node.js 서버 운영기 - Playnode 2015
시간당 수백만 요청을 처리하는 node.js 서버 운영기 - Playnode 2015
 
인공지능추천시스템 airs개발기_모델링과시스템
인공지능추천시스템 airs개발기_모델링과시스템인공지능추천시스템 airs개발기_모델링과시스템
인공지능추천시스템 airs개발기_모델링과시스템
 
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
 

Similar to Node.js API 서버 성능 개선기

Assurer - a pluggable server testing/monitoring framework
Assurer - a pluggable server testing/monitoring frameworkAssurer - a pluggable server testing/monitoring framework
Assurer - a pluggable server testing/monitoring framework
Gosuke Miyashita
 
[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho
[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho
[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho
CODE BLUE
 
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
Wesley Beary
 
Presentation iv implementasi 802x eap tls peap mscha pv2
Presentation iv implementasi  802x eap tls peap mscha pv2Presentation iv implementasi  802x eap tls peap mscha pv2
Presentation iv implementasi 802x eap tls peap mscha pv2
Hell19
 

Similar to Node.js API 서버 성능 개선기 (20)

Assurer - a pluggable server testing/monitoring framework
Assurer - a pluggable server testing/monitoring frameworkAssurer - a pluggable server testing/monitoring framework
Assurer - a pluggable server testing/monitoring framework
 
Webinar - 2020-09-23 - Escape the ticketing turmoil with Teleport PagerDuty &...
Webinar - 2020-09-23 - Escape the ticketing turmoil with Teleport PagerDuty &...Webinar - 2020-09-23 - Escape the ticketing turmoil with Teleport PagerDuty &...
Webinar - 2020-09-23 - Escape the ticketing turmoil with Teleport PagerDuty &...
 
FwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsFwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.js
 
[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho
[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho
[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho
 
fog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloudfog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloud
 
Debugging & profiling node.js
Debugging & profiling node.jsDebugging & profiling node.js
Debugging & profiling node.js
 
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
 
Central LogFile Storage. ELK stack Elasticsearch, Logstash and Kibana.
Central LogFile Storage. ELK stack Elasticsearch, Logstash and Kibana.Central LogFile Storage. ELK stack Elasticsearch, Logstash and Kibana.
Central LogFile Storage. ELK stack Elasticsearch, Logstash and Kibana.
 
Security in NodeJS applications
Security in NodeJS applicationsSecurity in NodeJS applications
Security in NodeJS applications
 
Webauthn Tutorial
Webauthn TutorialWebauthn Tutorial
Webauthn Tutorial
 
Monitoring with Syslog and EventMachine
Monitoring with Syslog and EventMachineMonitoring with Syslog and EventMachine
Monitoring with Syslog and EventMachine
 
Monkey man
Monkey manMonkey man
Monkey man
 
Data Validation models
Data Validation modelsData Validation models
Data Validation models
 
Presentation iv implementasi 802x eap tls peap mscha pv2
Presentation iv implementasi  802x eap tls peap mscha pv2Presentation iv implementasi  802x eap tls peap mscha pv2
Presentation iv implementasi 802x eap tls peap mscha pv2
 
How I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine Yard
How I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine YardHow I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine Yard
How I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine Yard
 
OSCamp #4 on Foreman | CLI tools with Foreman by Martin Bačovský
OSCamp #4 on Foreman | CLI tools with Foreman by Martin BačovskýOSCamp #4 on Foreman | CLI tools with Foreman by Martin Bačovský
OSCamp #4 on Foreman | CLI tools with Foreman by Martin Bačovský
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
 
IBM Cloud University: Build, Deploy and Scale Node.js Microservices
IBM Cloud University: Build, Deploy and Scale Node.js MicroservicesIBM Cloud University: Build, Deploy and Scale Node.js Microservices
IBM Cloud University: Build, Deploy and Scale Node.js Microservices
 
Solving anything in VCL
Solving anything in VCLSolving anything in VCL
Solving anything in VCL
 
Mastering Spring Boot's Actuator with Madhura Bhave
Mastering Spring Boot's Actuator with Madhura BhaveMastering Spring Boot's Actuator with Madhura Bhave
Mastering Spring Boot's Actuator with Madhura Bhave
 

More from JeongHun Byeon

More from JeongHun Byeon (20)

당근 개발자 플랫폼은 어떤 문제를 해결하고 있는가?
당근 개발자 플랫폼은 어떤 문제를 해결하고 있는가?당근 개발자 플랫폼은 어떤 문제를 해결하고 있는가?
당근 개발자 플랫폼은 어떤 문제를 해결하고 있는가?
 
오픈소스에 기여할 때 알면 좋을 개발 프로세스
오픈소스에 기여할 때 알면 좋을 개발 프로세스오픈소스에 기여할 때 알면 좋을 개발 프로세스
오픈소스에 기여할 때 알면 좋을 개발 프로세스
 
DevOps를 가속화하는 플랫폼 엔지니어링
DevOps를 가속화하는 플랫폼 엔지니어링DevOps를 가속화하는 플랫폼 엔지니어링
DevOps를 가속화하는 플랫폼 엔지니어링
 
클라우드 시대에 맞는 사이트 신뢰성 엔지니어
클라우드 시대에 맞는 사이트 신뢰성 엔지니어클라우드 시대에 맞는 사이트 신뢰성 엔지니어
클라우드 시대에 맞는 사이트 신뢰성 엔지니어
 
디자인에 이어 코딩까지 AI가 프로그램 개발을 척척? : GitHub Copilot, 어디까지 알아보셨나요
디자인에 이어 코딩까지 AI가 프로그램 개발을 척척? : GitHub Copilot, 어디까지 알아보셨나요 디자인에 이어 코딩까지 AI가 프로그램 개발을 척척? : GitHub Copilot, 어디까지 알아보셨나요
디자인에 이어 코딩까지 AI가 프로그램 개발을 척척? : GitHub Copilot, 어디까지 알아보셨나요
 
Citizen 개발기
Citizen 개발기Citizen 개발기
Citizen 개발기
 
오픈소스 뒤에 메인테이너 있어요
오픈소스 뒤에 메인테이너 있어요오픈소스 뒤에 메인테이너 있어요
오픈소스 뒤에 메인테이너 있어요
 
오픈소스에 기여할 때 해도 되는 일과 하면 안되는 일
오픈소스에 기여할 때 해도 되는 일과 하면 안되는 일오픈소스에 기여할 때 해도 되는 일과 하면 안되는 일
오픈소스에 기여할 때 해도 되는 일과 하면 안되는 일
 
Lessons from maintaining Mocha, an open source project
Lessons from maintaining Mocha, an open source projectLessons from maintaining Mocha, an open source project
Lessons from maintaining Mocha, an open source project
 
개발 관련 기술 블로그 운영하기
개발 관련 기술 블로그 운영하기개발 관련 기술 블로그 운영하기
개발 관련 기술 블로그 운영하기
 
Terraform을 이용한 Infrastructure as Code 실전 구성하기
Terraform을 이용한 Infrastructure as Code 실전 구성하기Terraform을 이용한 Infrastructure as Code 실전 구성하기
Terraform을 이용한 Infrastructure as Code 실전 구성하기
 
오픈소스 생태계 일원으로서의 개발자(자막 버전)
오픈소스 생태계 일원으로서의 개발자(자막 버전)오픈소스 생태계 일원으로서의 개발자(자막 버전)
오픈소스 생태계 일원으로서의 개발자(자막 버전)
 
오픈소스 생태계 일원으로서의 개발자
오픈소스 생태계 일원으로서의 개발자오픈소스 생태계 일원으로서의 개발자
오픈소스 생태계 일원으로서의 개발자
 
더 나은 개발자 되기
더 나은 개발자 되기더 나은 개발자 되기
더 나은 개발자 되기
 
블로그 주도 개발
블로그 주도 개발블로그 주도 개발
블로그 주도 개발
 
Front-end Development Process - 어디까지 개선할 수 있나
Front-end Development Process - 어디까지 개선할 수 있나Front-end Development Process - 어디까지 개선할 수 있나
Front-end Development Process - 어디까지 개선할 수 있나
 
Node.js 현재와 미래
Node.js 현재와 미래Node.js 현재와 미래
Node.js 현재와 미래
 
Nodejs Production 적용기
Nodejs Production 적용기Nodejs Production 적용기
Nodejs Production 적용기
 
Sublime Text tips & trikcs
Sublime Text tips & trikcsSublime Text tips & trikcs
Sublime Text tips & trikcs
 
Popular Convention 개발기
Popular Convention 개발기Popular Convention 개발기
Popular Convention 개발기
 

Recently uploaded

Kuwait City MTP kit ((+919101817206)) Buy Abortion Pills Kuwait
Kuwait City MTP kit ((+919101817206)) Buy Abortion Pills KuwaitKuwait City MTP kit ((+919101817206)) Buy Abortion Pills Kuwait
Kuwait City MTP kit ((+919101817206)) Buy Abortion Pills Kuwait
jaanualu31
 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
ssuser89054b
 

Recently uploaded (20)

Kuwait City MTP kit ((+919101817206)) Buy Abortion Pills Kuwait
Kuwait City MTP kit ((+919101817206)) Buy Abortion Pills KuwaitKuwait City MTP kit ((+919101817206)) Buy Abortion Pills Kuwait
Kuwait City MTP kit ((+919101817206)) Buy Abortion Pills Kuwait
 
Introduction to Serverless with AWS Lambda
Introduction to Serverless with AWS LambdaIntroduction to Serverless with AWS Lambda
Introduction to Serverless with AWS Lambda
 
AIRCANVAS[1].pdf mini project for btech students
AIRCANVAS[1].pdf mini project for btech studentsAIRCANVAS[1].pdf mini project for btech students
AIRCANVAS[1].pdf mini project for btech students
 
Design For Accessibility: Getting it right from the start
Design For Accessibility: Getting it right from the startDesign For Accessibility: Getting it right from the start
Design For Accessibility: Getting it right from the start
 
Online food ordering system project report.pdf
Online food ordering system project report.pdfOnline food ordering system project report.pdf
Online food ordering system project report.pdf
 
Bhubaneswar🌹Call Girls Bhubaneswar ❤Komal 9777949614 💟 Full Trusted CALL GIRL...
Bhubaneswar🌹Call Girls Bhubaneswar ❤Komal 9777949614 💟 Full Trusted CALL GIRL...Bhubaneswar🌹Call Girls Bhubaneswar ❤Komal 9777949614 💟 Full Trusted CALL GIRL...
Bhubaneswar🌹Call Girls Bhubaneswar ❤Komal 9777949614 💟 Full Trusted CALL GIRL...
 
HOA1&2 - Module 3 - PREHISTORCI ARCHITECTURE OF KERALA.pptx
HOA1&2 - Module 3 - PREHISTORCI ARCHITECTURE OF KERALA.pptxHOA1&2 - Module 3 - PREHISTORCI ARCHITECTURE OF KERALA.pptx
HOA1&2 - Module 3 - PREHISTORCI ARCHITECTURE OF KERALA.pptx
 
NO1 Top No1 Amil Baba In Azad Kashmir, Kashmir Black Magic Specialist Expert ...
NO1 Top No1 Amil Baba In Azad Kashmir, Kashmir Black Magic Specialist Expert ...NO1 Top No1 Amil Baba In Azad Kashmir, Kashmir Black Magic Specialist Expert ...
NO1 Top No1 Amil Baba In Azad Kashmir, Kashmir Black Magic Specialist Expert ...
 
School management system project Report.pdf
School management system project Report.pdfSchool management system project Report.pdf
School management system project Report.pdf
 
Block diagram reduction techniques in control systems.ppt
Block diagram reduction techniques in control systems.pptBlock diagram reduction techniques in control systems.ppt
Block diagram reduction techniques in control systems.ppt
 
Unleashing the Power of the SORA AI lastest leap
Unleashing the Power of the SORA AI lastest leapUnleashing the Power of the SORA AI lastest leap
Unleashing the Power of the SORA AI lastest leap
 
Employee leave management system project.
Employee leave management system project.Employee leave management system project.
Employee leave management system project.
 
HAND TOOLS USED AT ELECTRONICS WORK PRESENTED BY KOUSTAV SARKAR
HAND TOOLS USED AT ELECTRONICS WORK PRESENTED BY KOUSTAV SARKARHAND TOOLS USED AT ELECTRONICS WORK PRESENTED BY KOUSTAV SARKAR
HAND TOOLS USED AT ELECTRONICS WORK PRESENTED BY KOUSTAV SARKAR
 
Double Revolving field theory-how the rotor develops torque
Double Revolving field theory-how the rotor develops torqueDouble Revolving field theory-how the rotor develops torque
Double Revolving field theory-how the rotor develops torque
 
Thermal Engineering Unit - I & II . ppt
Thermal Engineering  Unit - I & II . pptThermal Engineering  Unit - I & II . ppt
Thermal Engineering Unit - I & II . ppt
 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 
Thermal Engineering -unit - III & IV.ppt
Thermal Engineering -unit - III & IV.pptThermal Engineering -unit - III & IV.ppt
Thermal Engineering -unit - III & IV.ppt
 
Hostel management system project report..pdf
Hostel management system project report..pdfHostel management system project report..pdf
Hostel management system project report..pdf
 
Orlando’s Arnold Palmer Hospital Layout Strategy-1.pptx
Orlando’s Arnold Palmer Hospital Layout Strategy-1.pptxOrlando’s Arnold Palmer Hospital Layout Strategy-1.pptx
Orlando’s Arnold Palmer Hospital Layout Strategy-1.pptx
 
PE 459 LECTURE 2- natural gas basic concepts and properties
PE 459 LECTURE 2- natural gas basic concepts and propertiesPE 459 LECTURE 2- natural gas basic concepts and properties
PE 459 LECTURE 2- natural gas basic concepts and properties
 

Node.js API 서버 성능 개선기

  • 2. 얘기할 내용 ✓성능 테스트를 위한 준비 ✓성능 테스트의 도구 ✓성능 테스트의 결과 분석
  • 3. 얘기안할 내용 ✓코드의 성능 개선 ✓코드 작성 팁 ✓잘못된 코드
  • 5. 인증 API 서버 https://flic.kr/p/4qLTdZ ✓ 회원 가입 ✓ 로그인 ✓ 권한부여 ✓ 회원 정보 관리
  • 6.
  • 8. ✓ 서버 하나의 한계 파악 ✓ 병목구간 확인 ✓ 코드 개선 후 비교
  • 9. Unit test에서도 확인 가능하지만 실제 트래픽과 유사한 성능이 궁금했다.
  • 11. ✓ 사용자 시나리오로 작성 ✓ 대량 트래픽 조절 가능 ✓ 가능하면 Node.js로 사용
  • 13. config: target: 'http://localhost:3000' http: timeout: 20 phases: - duration: 240 arrivalCount: 8 name: "Warm-up" - duration: 240 arrivalCount: 24 - duration: 240 arrivalCount: 48 - duration: 600 arrivalCount: 150 - duration: 240 arrivalCount: 48 - duration: 240 arrivalCount: 24 processor: "./processor.js" payload: path: './payload.csv' fields: - 'email' - 'password' order: 'sequence' YML
  • 14. duration: 240 arrivalCount: 24 240초동안 24 유저(시나리오)를 생성한다. -> 4분동안 10초에 한명씩 새로운 유저를 생성한다.
  • 15. scenarios: - name: ‘사용자 흐름' flow: # 회원 가입 - post: url: '/signup' json: email: '{{ email }}' password: '{{ password }}' # 로그인 - post: url: '/login' json: email: '{{ email }}' password: '{{ password }}' capture: - json: '$.data.token' as: 'token' # 정보조회 - get: url: '/user/info' headers: Authorization: 'Bearer {{ token }}'
  • 16. #!/usr/bin/env node const fs = require('fs'); const ROWS = process.env.PAYLOAD || 10000; const FILE_NAME = './test/payload.csv' fs.writeFileSync(FILE_NAME, ''); for(let i = 0; i < ROWS; i++) { const u = generateUser(); fs.appendFileSync(FILE_NAME, `${u.email},${u.password}n`); } 테스트 데이터 생성
  • 17. { "scripts": { "preloadtest": "./test/generate-payloads", "loadtest": "artillery run test/config.yml" } } package.json
  • 18. { "scripts": { "preloadtest": "./test/generate-payloads", "loadtest": "artillery run test/config.yml" } } package.json $ npm run loadtest
  • 19.
  • 20. $ artillery report artillery_report_20171103_185907.json
  • 21. APM : Application Performance Management https://flic.kr/p/3bkGjq
  • 22.
  • 24.
  • 25. #!/usr/bin/env bash curl -X POST ’https://api.newrelic.com/v2/applications/APPID/deployments.json' -H ‘X-Api-Key:YOUR_API_KEY’ -i -H 'Content-Type: application/json' -d '{ "deployment": { "revision": "1", "changelog": "'"${MACHINE_ID} start"'", "description": "'"${MACHINE_ID} start"'", "user": “YOUR_EMAIL" } }' New relic 배포 플래그
  • 26.
  • 27. { "scripts": { "preloadtest": “./test/generate-payloads && ./test/mark-ended.sh", "loadtest": "artillery run test/config.yml", "portloadtest": "./test/mark-ended.sh" } } package.json
  • 30.
  • 31. #!/bin/env ruby Vagrant.configure(2) do |config| config.vm.box = 'dummy' TEST_MACHINE_COUNT = 1 1.upto(TEST_MACHINE_COUNT) do |i| config.vm.define "test-machine-#{i}" do |machine| machine.vm.provider :aws do |aws, override| aws.tags = { 'Name' => "test-machine-#{i}" } aws.access_key_id = ENV['AWS_ACCESS_KEY_ID'] aws.secret_access_key = ENV['AWS_SECRET_ACCESS_KEY'] aws.keypair_name = 'test' aws.subnet_id = 'subnet-xxxxxx' aws.instance_type = 'c4.xlarge' aws.region = 'ap-northeast-1' aws.ami = 'ami-ea4eae8c' # Ubuntu 16.04 aws.security_groups = ['sg-xxxxxx', 'sg-xxxxxx'] override.ssh.username = 'ubuntu' override.ssh.private_key_path = '~/.ssh/test.pem' override.ssh.pty = false override.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'" end machine.nfs.functional = false machine.vm.synced_folder '../', '/www', type: "rsync", rsync__exclude: "node_modules/" machine.vm.provision "shell" do |s| s.inline = "export MACHINE_ID=$1 && sudo apt-get update && sudo apt-get install -y python" s.args = ["test-machine-#{i}"] end machine.vm.provision "ansible" do |ansible| ansible.groups = { "testnode" => ["test-machine-[0:#{$TEST_MACHINE_COUNT}]"] } ansible.playbook = './playbook.yml' end end end end Vagrantfile
  • 32. machine.vm.provider :aws do |aws, override| aws.tags = { 'Name' => "test-machine-#{i}" } aws.access_key_id = ENV['AWS_ACCESS_KEY_ID'] aws.secret_access_key = ENV['AWS_SECRET_ACCESS_KEY'] aws.keypair_name = 'test' aws.subnet_id = 'subnet-xxxxxx' aws.instance_type = 'c4.xlarge' aws.region = 'ap-northeast-1' aws.ami = 'ami-ea4eae8c' # Ubuntu 16.04 aws.security_groups = ['sg-xxxxxx', 'sg-xxxxxx'] override.ssh.username = 'ubuntu' override.ssh.private_key_path = '~/.ssh/test.pem' override.ssh.pty = false override.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'" end
  • 33. machine.vm.synced_folder '../../', '/www', type: "rsync", rsync__exclude: "node_modules/" machine.vm.provision "shell" do |s| s.inline = "export MACHINE_ID=$1 && sudo apt-get update && sudo apt-get install -y python” s.args = ["test-machine-#{i}"] end
  • 34. machine.vm.provision "ansible" do |ansible| ansible.groups = { "testnode" => ["test-machine-[0:#{$TEST_MACHINE_COUNT}]"] } ansible.playbook = './playbook.yml' end
  • 35. - name: Install prerequistes become: yes hosts: - all tasks: - name: install node.js shell: curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - - name: install apt packages apt: name: "{{ item }}" update_cache: yes with_items: - nodejs - name: install "artillery" nodejs package npm: name: artillery version: '1.5.8-3' path: /www ansible: playbook.yml
  • 36. $ vagrant plugin install vagrant-aws 플러그인 설치 서버 실행 $ vagrant up 부하 테스트 실행 $ ansible all -m shell -a "cd /www && npm run loadtest" 서버 종료 $ vagrant destroy
  • 38. ✓ 클러스터 인스턴스 변경 ✓ 컨테이너 CPU, 메모리 조정 ✓ DB Pool 사이즈 조정
  • 40. scenarios: - name: ‘사용자 흐름' flow: # 회원 가입 - post: url: '/signup' json: email: '{{ email }}' password: '{{ password }}' # 로그인 - post: url: '/login' json: email: '{{ email }}' password: '{{ password }}' capture: - json: '$.data.token' as: 'token' # 정보조회 - get: url: '/user/info' headers: Authorization: 'Bearer {{ token }}' # 정보 갱신 - patch: url: '/user/info' headers: Authorization: 'Bearer {{ token }}' json: field1: 'blah blah' field2: 'blah blah’ 1 시나리오 총 890 요청 200 응답: 818 201 응답: 32 202 응답: 40 시나리오당 20초 정도
  • 41. scenarios: - name: ‘사용자 흐름' flow: # 회원 가입 - post: url: '/signup' json: email: '{{ email }}' password: '{{ password }}' # 로그인 - post: url: '/login' json: email: '{{ email }}' password: '{{ password }}' capture: - json: '$.data.token' as: 'token' # 정보조회 - get: url: '/user/info' headers: Authorization: 'Bearer {{ token }}' # 정보 갱신 - patch: url: '/user/info' headers: Authorization: 'Bearer {{ token }}' json: field1: 'blah blah' field2: 'blah blah’ - 4분간 60초마다 1 유저 - 4분간 20초마다 1 유저 - 4분간 10초마다 1 유저 - 6분간 6초마다 1 유저 - 10분간 4초마다 1 유저 - 4분간 10초마다 1 유저 - 4분간 20초마다 1 유저
  • 42.
  • 43.
  • 45. V8의 컴파일러는 Crankshaft 5.9 부터는 Ignition + Turbofan
  • 46. 10% 이상의 성능 향상 https://v8project.blogspot.kr/2017/05/launching-ignition-and-turbofan.html
  • 47. RDS ECS cluster Elastic Load Balancer HTTP Request RDSnode 8.x node 6.x Elastic Load Balancer HTTP Request
  • 48. 테스트 서버 1대 node 6.11.5 node 8.9.0
  • 49. 테스트 서버 1대 node 6.11.5 node 8.9.0
  • 50. 테스트 서버 2대 node 6.11.5 node 8.9.0
  • 51. 테스트 서버 1대 node 6.11.5 node 8.9.0
  • 55. $ node --inspect ./bin/www Debugger listening on ws://127.0.0.1:9229/77128b6e-fe32-4da9-a1db For help see https://nodejs.org/en/docs/inspector Debugger attached. node --inspect YOUR_APP.js
  • 62.
  • 63. $ node --prof ./bin/api V8 Tick Profiler isolate-0x103800000-v8.log
  • 64. $ node --prof-process isolate-0x103800000-v8.log > processed.txt dropping: overflow Code move event for unknown code: 0x2a2f8121cac0 Code move event for unknown code: 0x2a2f8124f9a0 Code move event for unknown code: 0x2a2f81254ae0 V8 Tick Processor
  • 65. Statistical profiling result from isolate-0x103800000-v8.log, (147930 ticks, 31582 unaccounted, 0 excluded). [Shared libraries]: ticks total nonlib name 783 0.5% /usr/lib/system/libsystem_pthread.dylib 735 0.5% /usr/lib/system/libsystem_platform.dylib [JavaScript]: ticks total nonlib name 3358 2.3% 2.3% LoadIC: A load IC from the snapshot 2979 2.0% 2.0% Builtin: KeyedLoadIC_Megamorphic 1966 1.3% 1.3% Builtin: CallFunction_ReceiverIsAny [C++]: ticks total nonlib name 2253 1.5% 1.5% T ___channel_get_opt 1779 1.2% 1.2% T _mprotect 1545 1.0% 1.1% t v8::internal::LookupIterator::State v8::internal::LookupIterator::LookupInRegularHolder<false>(v8::internal::Map*, v8: [Summary]: ticks total nonlib name 60762 41.1% 41.5% JavaScript 53997 36.5% 36.9% C++ 4560 3.1% 3.1% GC 1589 1.1% Shared libraries 31582 21.3% Unaccounted [C++ entry points]: ticks cpp total name 4305 10.3% 2.9% T v8::internal::Runtime_StoreIC_Miss(int, v8::internal::Object**, v8::internal::Isolate*) 3155 7.5% 2.1% T v8::internal::Builtin_FunctionConstructor(int, v8::internal::Object**, v8::internal::Isolate*) [Bottom up (heavy) profile]: Note: percentage shows a share of a particular caller in the total amount of its parent calls. Callers occupying less than 1.0% are not shown. ticks parent name 31582 21.3% UNKNOWN 13500 42.7% LazyCompile: *Socket._writeGeneric net.js:708:42 11724 86.8% LazyCompile: *Writable.write _stream_writable.js:264:36 11662 99.5% LazyCompile: *Socket.write net.js:699:34 5453 46.8% Function: ~logRequest /Users/outsider/smartstudy/node_modules/morgan/index.js:116:25 processed.txt
  • 66. [JavaScript]: ticks total nonlib name 3358 2.3% 2.3% LoadIC: A load IC from the snapshot 2979 2.0% 2.0% Builtin: KeyedLoadIC_Megamorphic 1966 1.3% 1.3% Builtin: CallFunction_ReceiverIsAny 1866 1.3% 1.3% StoreIC: A store IC from the snapshot 1507 1.0% 1.0% Builtin: KeyedStoreIC_Megamorphic 1489 1.0% 1.0% Builtin: InterpreterEntryTrampoline 1341 0.9% 0.9% Builtin: FastNewClosure 1074 0.7% 0.7% Stub: GetPropertyStub 898 0.6% 0.6% Stub: StringAddStub 890 0.6% 0.6% KeyedLoadIC: A keyed load IC from the snapshot 717 0.5% 0.5% Builtin: ArgumentsAdaptorTrampoline 706 0.5% 0.5% LazyCompile: *Promise._settlePromises /Users/outsider/smartstudy/node_modules/blue 560 0.4% 0.4% LazyCompile: *emit events.js:156:44 516 0.3% 0.4% Builtin: CompileLazy 502 0.3% 0.3% Builtin: FunctionPrototypeHasInstance 492 0.3% 0.3% Builtin: ObjectHasOwnProperty 486 0.3% 0.3% StoreIC: A store IC from the snapshot {1} 472 0.3% 0.3% RegExp: (.*?)([[0-9]]) 450 0.3% 0.3% LazyCompile: *<anonymous> :1:10 442 0.3% 0.3% Builtin: JSConstructStubGenericUnrestrictedReturn 425 0.3% 0.3% Builtin: RegExpPrototypeExec 398 0.3% 0.3% Builtin: KeyedStoreIC_Megamorphic_Strict 395 0.3% 0.3% Builtin: FastCloneRegExp 389 0.3% 0.3% LazyCompile: *Promise._then /Users/outsider/smartstudy/node_modules/bluebird/js/re 377 0.3% 0.3% Builtin: FastArrayPush 372 0.3% 0.3% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/pg/lib/connectio 352 0.2% 0.2% Builtin: RegExpPrototypeTest 347 0.2% 0.2% Builtin: StrictEqual
  • 67. [Bottom up (heavy) profile]: Note: percentage shows a share of a particular caller in the total amount of its parent calls. Callers occupying less than 1.0% are not shown. ticks parent name 31582 21.3% UNKNOWN 13500 42.7% LazyCompile: *Socket._writeGeneric net.js:708:42 11724 86.8% LazyCompile: *Writable.write _stream_writable.js:264:36 11662 99.5% LazyCompile: *Socket.write net.js:699:34 5453 46.8% Function: ~logRequest /Users/outsider/smartstudy/node_modules/morgan/index.js:116:25 5296 97.1% Function: ~listener /Users/outsider/smartstudy/node_modules/on-finished/index.js:161 157 2.9% LazyCompile: *listener /Users/outsider/smartstudy/node_modules/on-finished/index.js: 3419 29.3% LazyCompile: *Client._pulseQueryQueue /Users/outsider/smartstudy/node_modules/pg/lib/c 3405 99.6% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/dialects/ 2744 23.5% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/pg/lib/client.js:139 2363 86.1% LazyCompile: *emit events.js:156:44 380 13.8% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/bluebird/js/releas 925 6.9% LazyCompile: *clearBuffer _stream_writable.js:469:21 839 90.7% LazyCompile: *end _http_outgoing.js:726:45 839 100.0% LazyCompile: *send /Users/outsider/smartstudy/node_modules/express/lib/response.js:106 734 87.5% LazyCompile: *json /Users/outsider/smartstudy/node_modules/express/lib/response.js:2 105 12.5% Function: ~json /Users/outsider/smartstudy/node_modules/express/lib/response.js:229: 56 6.1% Function: ~Writable.uncork _stream_writable.js:302:37 56 100.0% Function: ~end _http_outgoing.js:726:45 51 91.1% Function: ~send /Users/outsider/smartstudy/node_modules/express/lib/response.js:106: 5 8.9% LazyCompile: *send /Users/outsider/smartstudy/node_modules/express/lib/response.js:1 30 3.2% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/dialects/post 30 100.0% Function: ~end _http_outgoing.js:726:45 19 63.3% LazyCompile: *send /Users/outsider/smartstudy/node_modules/express/lib/response.js:1 11 36.7% Function: ~send /Users/outsider/smartstudy/node_modules/express/lib/response.js:106:
  • 68. 3358 2.3% LoadIC: A load IC from the snapshot 333 9.9% LazyCompile: *emit events.js:156:44 43 12.9% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/runner.js:1 43 100.0% LazyCompile: *tryCatcher /Users/outsider/smartstudy/node_modules/bluebird/js/release 39 90.7% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/bluebird/js/rele 39 100.0% Function: ~<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/runner.j 3 7.0% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/runner. 3 100.0% LazyCompile: *tryCatcher /Users/outsider/smartstudy/node_modules/bluebird/js/rel 1 2.3% LazyCompile: *tryCatcher /Users/outsider/smartstudy/node_modules/bluebird/js/relea 1 100.0% Function: ~<anonymous> /Users/outsider/smartstudy/node_modules/bluebird/js/relea 30 9.0% Function: ~<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/runner.js:51:7 30 100.0% LazyCompile: *tryCatcher /Users/outsider/smartstudy/node_modules/bluebird/js/release 24 80.0% Function: ~<anonymous> /Users/outsider/smartstudy/node_modules/bluebird/js/release 24 100.0% LazyCompile: *tryCatcher /Users/outsider/smartstudy/node_modules/bluebird/js/rel 6 20.0% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/bluebird/js/rele 6 100.0% LazyCompile: *tryCatcher /Users/outsider/smartstudy/node_modules/bluebird/js/rel 29 8.7% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/pg/lib/connection.js 29 100.0% LazyCompile: *emit events.js:156:44 29 100.0% LazyCompile: *addChunk _stream_readable.js:261:18 29 100.0% LazyCompile: *onread net.js:576:16 22 6.6% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/util/make-k 22 100.0% LazyCompile: *emit events.js:156:44 22 100.0% LazyCompile: *<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/runner. 22 100.0% LazyCompile: *tryCatcher /Users/outsider/smartstudy/node_modules/bluebird/js/rel 21 6.3% Function: ~<anonymous> /Users/outsider/smartstudy/node_modules/knex/lib/runner.js:152: 21 100.0% LazyCompile: *tryCatcher /Users/outsider/smartstudy/node_modules/bluebird/js/release 20 95.2% LazyCompile: *Promise._settlePromises /Users/outsider/smartstudy/node_modules/blue 20 100.0% LazyCompile: *processImmediate timers.js:697:26 1 4.8% LazyCompile: *Promise._settlePromiseFromHandler /Users/outsider/smartstudy/node_mo 496:56
  • 69. const morgan = require('morgan'); app.use(morgan('dev')); mogan 제거
  • 70. $ npx autocannon -c 100 -H "Authorization: token" http://localhost:3000/api Auto cannon 으로 비교 Stat Avg Stdve Max Latency
 (ms) 248.716 44.386 437.6 Req/Sec 398.72 40.022 472.4 Stat Avg Stdve Max Latency
 (ms) 235.728 38.748 404.4 Req/Sec 420.92 36.002 477.4
  • 72. $ npx autocannon -c 100 -H "Authorization: token" http://localhost:3000/api Auto cannon 으로 비교 Stat Avg Stdve Max Latency
 (ms) 235.728 38.748 404.4 Req/Sec 420.92 36.002 477.4 Stat Avg Stdve Max Latency
 (ms) 200.933 36.118 358.6 Req/Sec 495.78 45.058 594.8
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 82.
  • 83.
  • 84. 단위는 byte Heap dump의 사이즈 = 메모리 용량 Shallow Size = 객체의 실제 크기 Retained Size = 객체의 레퍼런스가 있으면 이를 포함한 크기
  • 85.
  • 86.