콘텐츠로 이동

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은?
      • 충돌 후 보고서를 분석하여 실패 후 어플리케이션의 동작 정의
      • 시스템이 민감한 데이터의 보안을 손상시키지 않도록 할 것
      • 모든 구성요소와 함께 정상으로 돌아옴
  • 테스트 환경
    1. 외부 인터페이스 Mock 처리
      • 외부 시스템은 항상 기대한 결과만을 반환하는 환경을 만들 것!
      • 내부 인터페이스/내부 객체 Mocking은 성능 테스트에서 하지 말 것!
      • 테스트 대상 시스템과 완벽히 분리된 Mock Server를 띄워야 함!
      • 병목이 되지 않는, 기대한 결과와 퍼포먼스를 반환하는 Mock Server 만들 것
    2. 사용한 도구들
      • nGrinder
      • pinpoint: Java로 작성된 대규모 분산 시스템용 APM 도구
        • APM: Application Performance Monitoring
        • Transaction의 추적을 제공하는 APM
        • 단일 Transaction의 stack trace를 기록하여 직접적인 병목이나 문제를 빠르게 추적

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을 변경
    • [Scala]

      • scala로 직접 시뮬레이션을 위한 테스트 코드 작성
      • 예시 스크립트 ```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) )

ifconfig