[Artillery] Node 환경 스트레스 테스트 (+ socket.io)

예니·2021년 3월 31일
2

배포 전, 서버가 얼마만큼의 부하를 견딜 수 있는지 부하 테스트를 진행해야했다.
친구들에게 배포해서 20명 정도 플레이를 했을 땐, 텍스트 길이 때문에 터졌기 때문에 서버 부하를 확인할 수가 없었다.
그래서 자동으로 부하 테스트를 할 수 있는 툴이 필요했고, 엄청난 서치 끝에 Artillery라는 갓갓갓 툴을 찾았다.

Node 환경에서의 부하 테스트 툴 중 가장 유명한 것 같았다. 게다가 socket.io 까지 지원한다. 바로 사용 가자
근데 문제는 socket.io 로 이용하는 레퍼런스가 많이 없었다. 물론 갓갓 Artillery 공식 문서에 socket.io를 사용하는 방법까지 나와있지만 우리 게임에서 로직을 수행하려면 어떻게 해야하는지 도저히 알 수 없었다.
장장 12시간정도의 삽질 끝에 더미 클라이언트들을 생성하여 룸에 입장시키고, 걔네들이 우리 게임 안에서 마구 매수, 매도를 할 수 있게 만들었다!

자 이제 정리를 해보자

1. 설치

npm install artillery

2. 간단 테스트

./node_modules/artillery/bin/artillery quick --duration 60 --rate 10 -n 20 http://localhost:8080
자신이 열어둔 localhost:포트 로 간단한 테스트를 진행할 수 있다.

(60초 동안, 초당 10번, 동시접속 20명으로 테스트를 진행)
(테스트를 진행하는 경로는 서버측 폴더)

3. 시나리오 작성 테스트

우리 프로젝트는 실시간으로 비트코인 데이터를 받아 차트를 그리고, 유저들의 자산을 업데이트 해주면서도 엄청난 양의 매수, 매도를 처리해야한다.
우선 유저들이 방에 입장해야하고, 게임을 시작하면 폭풍 매수, 매도를 진행하도록 시나리오를 기획했다. 하지만 역시나 뜻대로 안됐다.

우선, Artillery는 json 형식, yml 형식을 지원하는데, 공식문서와 많은 레퍼런스들이 yml 형식을 사용하고 있었다. yml은 이때 처음 봤다. xml, json보다 사람이 읽기 편한 형태로 indentation으로 구분한 형식이라하는데 이것부터 익숙하지 않았다.
많이 찾아봤지만 들여쓰기하는 기준도 알기 어려워서, 처음에 yml로 했다가 json으로 바꿨다가 다시 yml로 돌아왔다😂
yml의 들여쓰기 기준은 두칸! 이게 국룰인지는 모르겠지만 들여쓰기가 점점 많아지니까 두칸이 맞는 것 같다.

실행 명령어 : ./node_modules/artillery/bin/artillery run test.yml

config:
  target: "http://localhost:5000"
  socketio:
    query: "id=cUW7OXP624yUTJT"
  phases:
    - duration: 10
      arrivalRate: 4
scenarios:
  - name: "Connect and join Room"
    engine: "socketio"
    flow:
      - emit:
          channel: "joinRoom_Req"
          data:
            "playerID": "{{$randomString()}}"
            "roomID": "cUW7OXP624yUTJT"

      - think: 15
      - loop:
        - emit:
            channel: "buy_Req"
            data:
              "roomID": "cUW7OXP624yUTJT"
              "socketID": 0
              "currentBid": 10000
              "currentVolume": 10000
        - think: 1
        - emit:
            channel: "sell_Req"
            data:
                "roomID": "cUW7OXP624yUTJT"
                "socketID": 0
                "currentBid": 1000
                "currentVolume": 10000
        - think: 1
      - think: 45

내가 작성한 yml은 위와 같다.

  • query : socket 들이 들어오는 주소 끝에 roomID로 쿼리를 달고 있어서 쿼리 부분을 작성해줘야한다. 방 만들때마다 roomID가 매번 달라져서 테스트할때마다 이 부분을 바꿔주는게 번거로웠다. 이거 자동화하는 것도 시도해봐야지
  • phase
    - duration : 시나리오를 10초간 실행한다
    - arrivalRate : 1초당 실행할 횟수
    즉, 총 40명의 더미 클라이언트를 생성했다.
  • channel : 소켓들이 주고받는 프로토콜
    ex. socket.emit('hello', data)hello
  • data : js object 형태로 주고받는 데이터를 어떻게 yml로 표현할 수 있는지 의문이었는데, 그냥 저렇게 key : value 형태로 줄로 구분해주면 됐다.
  • think : 대기하는 초
    - 입장하고 15초간 대기
    - 매수, 매도하고 1초간 대기
    - 각 더미 클라이언트는 테스트 시간인 40초보다 먼저 끝나면 안되므로 45초간 대기

10초간 40명의 클라이언트들이 방에 입장하고, 방장(나)이 시작버튼을 누르면 다같이 게임을 시작한다. 이 부분까지 자동화시키기엔 시간이 부족해서 게임 시작버튼은 내가 눌렀다😁
(유저를 40명으로 제한한 이유는, 입장 테스트시 100~300명이 입장 가능했고, 게임 입장 시, 100명은 버벅임 현상이 발생해서 보수적으로 40명으로 잡았다. (aws ec2 t2.micro 기준))

게임을 시작하면 더미 클라이언트들이 1초 간격으로 매수, 매도를 반복한다. 40명이 1초마다 매수, 매도를 하니까 거의 초당 40번의 거래가 발생했다.
다행히 버벅임 전혀 없이 거래가 잘 진행되었다.

socket.io 로 간단한 예제는 있어도, 실제 프로젝트에 넣은 예제코드는 찾기 힘들어서 저 몇줄안되는 yml 파일을 작성하는 데에 굉장히 힘들었다. 아직도 완전히 이해했다고 말하기는 어렵지만, 그래도 순수 내 손으로 이해하고 짠 파일이라 정말 뿌듯하다. 훗날 node + socket.io + artillery 조합을 사용하시는 분들에게 도움이 됐으면 좋겠다.

4. 레포트 생성

./node_modules/artillery/bin/artillery run -o hax0r-report test.yml
위 명령어를 실행하면, 테스트가 끝나고 해당 디렉토리에 hax0r-report라는 이름의 레포트가 생성된다.

./node_modules/artillery/bin/artillery report hax0r-report Report generated: hax0r-report.html
위 명령어를 실행하면 html로 보여준다.



+


내가 만든 더미 클라이언트에게 밀렸다😅

3개의 댓글

comment-user-thumbnail
2021년 8월 27일

멋집니다~

답글 달기
comment-user-thumbnail
2021년 11월 27일

좋은 글 잘 보고 가요~~:)

답글 달기
comment-user-thumbnail
2021년 11월 30일

여기서 보네요~

답글 달기