2017년 3월 10일, 작성한 서버 증설관련 내용을 정리하여 올립니다. 서버 증설을 사전에 측정하여, 추후 서버가 더 늘었을 때를 대응하기 위한 조치였습니다.

TPS(Transaction Per Second)란?

  • 1초에 시스템이 처리할 수 있는 트랜잭션의 수를 의미하는 TPS가 성능 테스트의 중요한 지표로 사용됩니다.
  • 시스템의 특정 기능에 대한 성능을 측정한 결과, 30 TPS가 나왔다면, 1초에 30개의 트랜잭션을 처리할 수 있다는 의미입니다.

측정방안

현제 TPS 는 초당 800~900 건입니다. 서버에서 가장 유입이 많은 시간대가 17시로 해당 시간을 기준으로 1초에 유입된 request의 count를 계산했습니다.

  1. 제가 만든 시스템은 꾸준한 성능 개선을 통해, 하나의 request 를 처리하는데 100ms 안에 처리하도록 작업이 되어있습니다. 평균적으로 1ms ~ 10ms 안에 응답이 나가야지 정상입니다.

  2. 현재 서버 15대를 기준으로 작성되하며, TPS 계산은 현재 라이브되고 있는 서버의 access.log를 참고로 하여 계산되었습니다.
    203.133.xxx.xxx - - [09/Mar/2017:17:02:09 +0900] "POST /xxx/xxx HTTP/1.1" 200 2554 "-" "Apache-HttpAsyncClient/4.1.2 (Java/1.8.0_101)" 1ms "IP_info: - , fp: - ,Start_Time: -"
    203.133.xxx.xxx - - [09/Mar/2017:17:02:09 +0900] "POST /xxx/xxx HTTP/1.1" 200 114 "-" "Apache-HttpAsyncClient/4.1.2 (Java/1.8.0_101)" 1ms "IP_info: - , fp: - ,Start_Time: -"
    203.133.xxx.xxx - - [09/Mar/2017:17:02:09 +0900] "POST /xxx/xxx HTTP/1.1" 200 3854 "-" "Apache-HttpAsyncClient/4.1.2 (Java/1.8.0_101)" 2ms "IP_info: - , fp: - ,Start_Time: -"
    203.133.xxx.xxx - - [09/Mar/2017:17:02:09 +0900] "POST /xxx/xxx HTTP/1.1" 200 114 "-" "Apache-HttpAsyncClient/4.1.2 (Java/1.8.0_101)" 1ms "IP_info: - , fp: - ,Start_Time: -"
    203.133.xxx.xxx - - [09/Mar/2017:17:02:09 +0900] "POST /xxx/xxx HTTP/1.1" 200 114 "-" "Apache-HttpAsyncClient/4.1.2 (Java/1.8.0_101)" 1ms "IP_info: - , fp: - ,Start_Time: -"
    203.133.xxx.xxx - - [09/Mar/2017:17:02:09 +0900] "POST /xxx/xxx HTTP/1.1" 200 114 "-" "Apache-HttpAsyncClient/4.1.2 (Java/1.8.0_101)" 1ms "IP_info: - , fp: - ,Start_Time: -"
    203.133.xxx.xxx - - [09/Mar/2017:17:02:09 +0900] "POST /xxx/xxx HTTP/1.1" 200 114 "-" "Apache-HttpAsyncClient/4.1.2 (Java/1.8.0_101)" 0ms "IP_info: - , fp: - ,Start_Time: -"
    203.133.xxx.xxx - - [09/Mar/2017:17:02:09 +0900] "POST /xxx/xxx HTTP/1.1" 200 114 "-" "Apache-HttpAsyncClient/4.1.2 (Java/1.8.0_101)" 0ms "IP_info: - , fp: - ,Start_Time: -"
    203.133.xxx.xxx - - [09/Mar/2017:17:02:09 +0900] "POST /xxx/xxx HTTP/1.1" 200 114 "-" "Apache-HttpAsyncClient/4.1.2 (Java/1.8.0_101)" 1ms "IP_info: - , fp: - ,Start_Time: -"
    203.133.xxx.xxx - - [09/Mar/2017:17:02:09 +0900] "POST /xxx/xxx HTTP/1.1" 200 114 "-" "Apache-HttpAsyncClient/4.1.2 (Java/1.8.0_101)" 1ms "IP_info: - , fp: - ,Start_Time: -"
    203.133.xxx.xxx - - [09/Mar/2017:17:02:09 +0900] "POST /xxx/xxx HTTP/1.1" 200 114 "-" "Apache-HttpAsyncClient/4.1.2 (Java/1.8.0_101)" 0ms "IP_info: - , fp: - ,Start_Time: -"
    203.133.xxx.xxx - - [09/Mar/2017:17:02:09 +0900] "POST /xxx/xxx HTTP/1.1" 200 114 "-" "Apache-HttpAsyncClient/4.1.2 (Java/1.8.0_101)" 1ms "IP_info: - , fp: - ,Start_Time: -"
    203.133.xxx.xxx - - [09/Mar/2017:17:02:09 +0900] "POST /xxx/xxx HTTP/1.1" 200 114 "-" "Apache-HttpAsyncClient/4.1.2 (Java/1.8.0_101)" 1ms "IP_info: - , fp: - ,Start_Time: -"
    203.133.xxx.xxx - - [09/Mar/2017:17:02:09 +0900] "POST /xxx/xxx HTTP/1.1" 200 2856 "-" "Apache-HttpAsyncClient/4.1.2 (Java/1.8.0_101)" 3ms "IP_info: - , fp: - ,Start_Time: -"
    203.133.xxx.xxx - - [09/Mar/2017:17:02:09 +0900] "POST /xxx/xxx HTTP/1.1" 200 114 "-" "Apache-HttpAsyncClient/4.1.2 (Java/1.8.0_101)" 0ms "IP_info: - , fp: - ,Start_Time: -"
    203.133.xxx.xxx - - [09/Mar/2017:17:02:09 +0900] "POST /xxx/xxx HTTP/1.1" 200 114 "-" "Apache-HttpAsyncClient/4.1.2 (Java/1.8.0_101)" 1ms "IP_info: - , fp: - ,Start_Time: -"
    
  3. L4에서 전부 처리될 수 있다고 가정하며, 망 분리나 트래픽에 대한 영향은 배제됩니다.

엑세스 로그로 측정하는 이유

scouter 에서 측정되는 데이터와 억세스 로그에서 측정하는 데이터의 차이는 없으며, 정확한 시간대의 유입을 체크하기 위해서는 억세스 로그가 더 편하기 때문입니다.

TPS 계산법

TPS ( Transaction per second )
= ActiveUsers / Res. Time= ConcurrentUsers/( Res. Time + Think Time )
= ActiveUser = ConcurrentUsers * ( ResTime / ( ResTime + Think Time ) )
= ResTime * TPS

여러가지 방법 중에 저는 ActiveUsers / Res. Time 를 사용했습니다. 실제로 해당 서버마다 고유의 API 처리에 대한 특성이 있어 정확한 TPS(Transaction Per Seconds)를 구하기는 힘드므로, 유입 request(트래픽)을 ActiveUser 로 계산하였고, 전체 서버의 api 의 평균응답시간을 계산하여 현재 시스템의 TPS 를 구했습니다.

17시 2분 9초의 request 의 count를 세어보니 1초동안 830건의 유입이 있었습니다. 해당 request 의 총 처리시간은 3600ms 로, request 하나당 처리시간은 4.35 ms, 1초로 환산하면 0.0043초의 처리시간이 걸렸습니다. 해당 request 는 하나의 ActiveUser 로 계산하며, Requset Interval 을 계산하면 190989 TPS 의 처리가 가능하다는 이야기가 됩니다. (서버 15대이므로 서버 한대당 12732 TPS 처리가능)

3월달 가장 유입이 많았던 날을 기준으로 전체 유입량을 1초로 계산할때, 45916505/(246060) 평균 유입은 641의 request 가 발생하였으며, 가장 유입이 많은 시간대의 17시(오후5시)의 평균 1초당 995건의 유입이 발생하였습니다.

추가 예상되는 트래픽이 현재의 10배라고 측정했을때, 6000 TPS 정도로 예상되며, 하루 5억2782만6500 TPS 로 예상되었습니다. 해당 서버는 15대의 서버가 한건에 대해 0.004초안에 처리되므로, 한서버에서 1만2천건의 처리가 가능한 것으로 측정되었기 때문에, 현재 서버의 유입으로 추가 트래픽의 10배를 더 버틸 수 있는 것으로 측정했습니다. 100배가 들어온다고 하여도, 서버 당 1만 2천건을 처리해야하므로 서버 2대 정도의 추가 증설이 필요한 것으로 결론내었습니다.

서버 증설의 경우, 결국 데이터를 비동기로 처리할 때 RDBMS 에 순간적인 row lock 이 발생하게 됩니다. 추가로 MYSQL(RDBMS)에 접속을 조금 더 줄일 수 있는 방안에 대한 추가 개발이 필요하여, 카프카 기술이 적용되게 되었습니다.