node.js 프로그래밍 책에 나와있는 예제를 고대로 따라해봤다. 이것만 따로 포스팅 한 이유는 node.js는 싱글 쓰레드 기반의 이벤트 루프 방식으로 알고 있어서 cpu가 노는 것이 비효율 적이지 않을까 싶었는데 스레드 대신 프로세스를 여러개 사용하는 방법이라 유용할 것 같아서이다.
cluster를 사용하면 fork()를 통해 프로세스를 생성하고 요청에 대한 처리를 각 프로세스에서 나눠서 처리할 수가 있다. 프로세스이기 때문에 스택을 공유하지 않지만 프로세스간 메시지 전달을 통해 데이터를 주고 받을 수 있다.
예제에서는 간단하게 cluster를 사용하지 않은 경우와 사용한 경우를 나눠 apache benchmark를 통해 응답 시간을 비교하는 것으로 cluster의 이점을 설명했다.
plain-server.js
var http = require('http');
http.Server(function(req, res){
var startTime = new Date();
res.writeHead(200);
for(var i=0; i<10000000000;i++){
}
res.end("hello world\n");
var endTime = new Date();
console.log('response complete, elapsed time : '+ (endTime - startTime));
}).listen(8000);
cluster-server.js
var cluster = require('cluster')
, http = require('http')
, numCPUs = require('os').cpus().length;
if(cluster.isMaster){
for(var i=0; i<numCPUs;++i){
var worker = cluster.fork();
}
} else {
var startTime = new Date();
http.Server(function(req, res){
res.writeHeader(200);
for(var i=0; i<10000000000; i++){
}
res.end('hello world\n');
var endTime = new Date();
console.log('response complete elapsed time '+(endTime-startTime));
}).listen(8000);
}
예제에 조금더 첨가를 해서 루프를 처리하는 시간을 남겨보았다.
벤치마크 커맨드 : $ ab -n 10 -c 2 http://127.0.0.1:8000/
plain-server.js 의 결과
response complete, elapsed time : 10902
response complete, elapsed time : 11178
response complete, elapsed time : 11076
response complete, elapsed time : 11114
response complete, elapsed time : 11143
response complete, elapsed time : 11249
response complete, elapsed time : 11272
response complete, elapsed time : 11288
response complete, elapsed time : 11157
response complete, elapsed time : 11201
plain-server.js의 벤치마크 결과
Benchmarking 127.0.0.1 (be patient).....done
Server Software:
Server Hostname: 127.0.0.1
Server Port: 8000
Document Path: /
Document Length: 12 bytes
Concurrency Level: 2
Time taken for tests: 111.608 seconds
Complete requests: 10
Failed requests: 0
Total transferred: 870 bytes
HTML transferred: 120 bytes
Requests per second: 0.09 [#/sec] (mean)
Time per request: 22321.617 [ms] (mean)
Time per request: 11160.809 [ms] (mean, across all concurrent requests)
Transfer rate: 0.01 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 0
Processing: 10924 21201 3613.9 22359 22561
Waiting: 10922 21201 3614.4 22359 22560
Total: 10924 21201 3613.8 22359 22561
Percentage of the requests served within a certain time (ms)
50% 22359
66% 22393
75% 22447
80% 22521
90% 22561
95% 22561
98% 22561
99% 22561
100% 22561 (longest request)
cluster-server.js 의 결과
response complete elapsed time 30844
response complete elapsed time 30876
response complete elapsed time 41729
response complete elapsed time 41775
response complete elapsed time 52929
response complete elapsed time 52973
response complete elapsed time 64053
response complete elapsed time 64127
response complete elapsed time 75193
response complete elapsed time 75236
cluster-server.js 의 벤치마크 결과
Benchmarking 127.0.0.1 (be patient).....done
Server Software:
Server Hostname: 127.0.0.1
Server Port: 8000
Document Path: /
Document Length: 12 bytes
Concurrency Level: 2
Time taken for tests: 55.280 seconds
Complete requests: 10
Failed requests: 0
Total transferred: 870 bytes
HTML transferred: 120 bytes
Requests per second: 0.18 [#/sec] (mean)
Time per request: 11055.982 [ms] (mean)
Time per request: 5527.991 [ms] (mean, across all concurrent requests)
Transfer rate: 0.02 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 0
Processing: 10887 11051 129.5 11127 11185
Waiting: 10882 11048 132.0 11127 11184
Total: 10888 11051 129.4 11127 11185
Percentage of the requests served within a certain time (ms)
50% 11127
66% 11136
75% 11164
80% 11184
90% 11185
95% 11185
98% 11185
99% 11185
100% 11185 (longest request)
결과를 보면 plain-server.js 는 각 요청 개별적으로 거의 동일하게 11초 정도씩 걸린 반면 cluster-server.js의 경우에는 걸린 시간이 점점 늘어나긴 하지만 전체적인 시간은 더 짧은 것을 볼 수 있었다. 여기서 각 요청별 경과시간이 길어지는걸 보니 각 요청에 대해 프로세스들이 cpu자원을 경쟁해가며 처리를 한다고 느꼈다. cluster를 잘 활용하면 더 좋은 성능으로 요청을 처리할 수 있을 것 같다.
댓글