2023 08 29
2023-08-29¶
성능 테스트¶
참고: https://jins-dev.tistory.com/entry/load-testing-%EA%B3%BC-stress-testing-performance-testing-%EC%97%90-%EB%8C%80%ED%95%9C-%EB%B9%84%EA%B5%90 참고: https://loosie.tistory.com/821 참고: https://techblog.woowahan.com/2572/
- 개요
- 성공적인 성능 테스트는 데이터베이스, 네트워크, 소프트웨어, 하드웨어 등과 관련될 수 있는 대부분의 성능 문제를 예측해야 함
- 왜 필요한가?
- 내가 만든 이 시스템이 실제 장비에서...
- 어느 정도의 부하를 견딜 수 있는가?
- 시스템(DB, 서버), 자원(cpu, disk, memory)에서 병목이 생기지 않는가?
- 자원을 효율적으로 사용하는가? => (Akka Actor?)
- 메모리 누수, 오류, 오버플로우는 발생하지 않는가?
- 최악의 상황에선 어떤 동작을 하는가?
- 장애 조치와 복구가 잘 동작을 하는가?
- 내가 만든 이 시스템이 실제 장비에서...
-
종류
- [부하 테스트 - Load Testing] : 얼마만큼의 부하를 견디는가
- Ramp up
- 임계치 한계에 도달할 때까지 시스템의 부하를 지속적으로 증가
- 낮은 수준의 부하 -> 높은 수준의 부하 예상 트래픽을 꾸준히 증가시키며 진행
- 한계점 측정이 관건
- 임계치를 높이는 목적
- 동시 접속자수 & 해당 부하에 대한 Response Time 측정
- ex) 1분 동안 10만명의 동시접속을 처리할 수 있는 시스템을 만들 수 있는가?
- 부하테스트 목표
- 버퍼 오버플로, 메모리 누수 및 메모리 관리 오류와 관련된 어플리케이션의 결함 확인
- 로드 밸런싱 문제, 대역폭 문제, 기존 시스템의 용량 확인
- 어플리케이션이 향후 예상되는 로드를 관리할 수 있도록 DB, 하드웨어, 네트워크 등 어플레케이션 구성 요소 상한 결정
- [스트레스 테스트 - Stress Testing] : 스트레스 받는 상황에서 시스템의 안정성
- 최대 부하치에 해당하는 만큼의 많은 동시 접속자수가 포함된 상황에서 시스템이 얼마나 안정적으로 돌아가는가?
- 시스템 모니터링, 로깅, 보안상의 이슈, 데이터 결함 등 서비스에 영향이 가서는 안됨
- 부하가 심한 상황, 시스템의 복구가 어려운 상황에서 얼마나 크래시를 견디며 서비스가 운영되는가 + 빠르게 복구되는가 + Response Time은?
- 충돌 후 보고서를 분석하여 실패 후 어플리케이션의 동작 정의
- 시스템이 민감한 데이터의 보안을 손상시키지 않도록 할 것
- 모든 구성요소와 함께 정상으로 돌아옴
- [부하 테스트 - Load Testing] : 얼마만큼의 부하를 견디는가
- 테스트 환경
- 외부 인터페이스 Mock 처리
- 외부 시스템은 항상 기대한 결과만을 반환하는 환경을 만들 것!
- 내부 인터페이스/내부 객체 Mocking은 성능 테스트에서 하지 말 것!
- 테스트 대상 시스템과 완벽히 분리된 Mock Server를 띄워야 함!
- 병목이 되지 않는, 기대한 결과와 퍼포먼스를 반환하는 Mock Server 만들 것
- 사용한 도구들
- nGrinder
- pinpoint: Java로 작성된 대규모 분산 시스템용 APM 도구
- APM: Application Performance Monitoring
- Transaction의 추적을 제공하는 APM
- 단일
Transaction의 stack trace를 기록하여 직접적인 병목이나 문제를 빠르게 추적
- 외부 인터페이스 Mock 처리
Gatling¶
참고: https://www.daddyprogrammer.org/post/9115/gatling-api-load-test-setup-environment/ 참고: https://gatling.io/docs/gatling/reference/current/http/request/
- 개요
- 실제 서비스 환경과 유사하게 요청을 시뮬레이션 하며 테스트
- 서비스 투입 전 성능상 문제가 없는지 확인하고 개선하기 위해 사용
- Gatling을 이용해 유저가 정해진 시나리오대로 동작하는 것처럼 시뮬레이션 할 수 있음
-
Gatling 테스트 환경 구성
- 시뮬레이션을 위한 테스트코드 작성
- [recorder]
- 웹브라우저에서 요청한 http call을 캡쳐해 테스트 코드 작성
- recorder를 사용해 테스터의 액션을 캡쳐 -> 테스트 코드(scala)를 자동으로 생성
- 웹 프론트의 동작 방식을 테스트로 기록해 테스트 하기 좋음
- 브라우저의 요청을 gatling recorder에서 캡쳐할 수 있도록 브라우저의 proxy setting을 변경
- https://chrome.google.com/webstore/detail/proxy-switchyomega/padekgcemlokbadohgkifijomclgjgif
- 이렇게 켜놓고 브라우저 뚝딱뚝딱 왔다갔다 하면 스칼라 코드 확인 가능 (알아서 recorder가 Scala로 써줌)
-
[Scala]
- scala로 직접 시뮬레이션을 위한 테스트 코드 작성
- 백엔드 API를 직접 호출하는 경우 (https://gatling.io/docs/gatling/reference/current/http/request/ 참고하여 작성)
- 예시 스크립트
```scala
class FirstSimulation extends Simulation {
val httpProtocol = http.baseUrl("http://localhost:8080")
.acceptHeader("application/json")
.acceptEncodingHeader("gzip, deflate")
.acceptLanguageHeader("ko-KR, ko;q=0.9,en-US;q=0.8")
.userAgentHeader("Mozilla/5.0")
val authHeaders = Map( "X-AUTH-TOKEN" -> "eyJsdfjisdofj.sfu098fsn.x1jkfjd" )
val formParam = Map( "author" -> "joel", "title" -> "jo", "content" -> "joel.jo" )
val postId = 0
val scn = scenario("FirstSimulation") .exec(http("게시판 보기").get("/v1/board/freeboard/posts")) .pause(2) .exec(http("게시판에 글 작성").post("/v1/board/freeboard/post").headers(authHeaders).formParamMap(formParam).check(status.is(200))) .exec(http("작성한 글 확인").get(s"/v1/board/post/${postId}"))
setUp(scn.inject(atOnceUsers(1))).protocols(httpProtocol) } ```
- 다음과 같이 setup하여 부하를 늘릴 수 있음 => 시나리오 만들고, 이를 어떻게 몇명이나 부하보낼지는 setUp에서 결정
scala setUp( scn.inject( nothingFor(4 seconds), // 일정시간 대기 atOnceUsers(10), // 지정된 수의 사용자를 한번에 주입 rampUsers(10) during (5 seconds), // 주어진 지속시간에 걸쳐 주어진 수의 사용자를 선형적으로 늘려가며 주입 constantUsersPerSec(20) during (15 seconds), // 주어진 지속시간에 걸쳐 사용자를 일정한 비율로 증가시키며 주입. 일정한 간격 주입. constantUsersPerSec(20) during (15 seconds) randomized, // 주어진 지속시간에 걸쳐 사용자를 일정한 비유로 증가시키며 주입. 랜덤한 간격 주입. rampUsersPerSec(10) to 20 during (10 minutes), // 주어진 지속시간 동안 사용자를 시작 비율 -> 목표 비율까지 증가시키며 주입. 일정한 간격 주입 rampUsersPerSec(10) to 20 during (10 minutes) randomized, // 주어진 지속시간 동안 사용자를 시작 비율 -> 목표 비율까지 증가시키며 주입. 랜덤한 간격 주입 heavisideUser(1000) during (20 seconds) // 단위 계단 함수로 주어진 지속시간 동안 사용자를 주입. ).protocols(httpProtocol) )
- scala로 직접 시뮬레이션을 위한 테스트 코드 작성