인젝션 프로필(Injection) — 가상 사용자를 언제 얼마나 흘려보낼까

인젝션 프로필(Injection) — 가상 사용자를 언제 얼마나 흘려보낼까

부하 테스트에서 '얼마나 많은 가상 사용자가, 언제 들어오는지'를 정하는 게 인젝션(injection)이에요. 이걸 프로필(profile)이라고 하고, 시스템을 바라보는 관점에 따라 **열린 모델(open model)**과 **닫힌 모델(closed model)**로 나눠요.

인젝션 프로필은 injectOpen·injectClosed 메서드(Scala에서는 그냥 inject)로 정의해요. 이 메서드는 순차적으로 처리될 인젝션 단계(injection step)의 시퀀스를 인자로 받아요.

출처: Gatling injection scripting reference

본문

열린 모델(Open model) — 핵심 구성 요소

열린 모델은 '초당 얼마나 많은 사용자가 도착하는가(도착률)'를 기준으로 부하를 흘려보내는 모델이에요.

setUp(
  scn.inject(
    nothingFor(4),                          // 1
    atOnceUsers(10),                         // 2
    rampUsers(10).during(5),                 // 3
    constantUsersPerSec(20).during(15),      // 4
    constantUsersPerSec(20).during(15).randomized, // 5
    rampUsersPerSec(10).to(20).during(10.minutes), // 6
    rampUsersPerSec(10).to(20).during(10.minutes).randomized, // 7
    stressPeakUsers(1000).during(20)         // 8
  ).protocols(httpProtocol)
)
  1. nothingFor(duration): 주어진 시간 동안 멈춰 있어요.
  2. atOnceUsers(nbUsers): 주어진 수의 사용자를 한 번에 주입해요.
  3. rampUsers(nbUsers).during(duration): 주어진 수의 사용자를 일정 시간 창에 고르게 분산해 주입해요.
  4. constantUsersPerSec(rate).during(duration): 초당 일정 비율로 사용자를 규칙적인 간격으로 주입해요.
  5. constantUsersPerSec(rate).during(duration).randomized: 같은 비율이지만 무작위 간격으로 주입해요.
  6. rampUsersPerSec(rate1).to(rate2).during(duration): 시작 비율에서 목표 비율로 규칙적인 간격으로 주입해요.
  7. rampUsersPerSec(rate1).to(rate2).during(duration).randomized: 시작에서 목표 비율로 무작위 간격으로 주입해요.
  8. stressPeakUsers(nbUsers).during(duration): heaviside 계단 함수를 주어진 시간으로 스무스하게 근사한 곡선을 따라 사용자를 주입해요.

계단식(Stairs) 부하

용량 테스트를 만들다 보면 램프와 플랫 구간을 이어서 부하를 점진적으로 올리고 싶을 때가 많아요. 수동으로 블록을 이어 붙일 수도 있지만, Gatling은 내장 헬퍼 incrementUsersPerSec를 제공해요.

setUp(
  // 초당 10, 15, 20, 25, 30명 도착하는 레벨을 만들고
  // 각 레벨은 10초, 레벨 사이는 10초짜리 선형 램프로 분리
  scn.inject(
    incrementUsersPerSec(5.0)
      .times(5)
      .eachLevelLasting(10)
      .separatedByRampsLasting(10)
      .startingFrom(10)   // Double
  )
)

separatedByRampsLastingstartingFrom은 둘 다 선택이에요. 램프를 지정하지 않으면 한 레벨이 끝나자마자 다음 레벨로 점프하고, 시작 사용자 수를 지정하지 않으면 초당 0명부터 시작해 바로 다음 단계로 갑니다.

닫힌 모델(Closed model) — 핵심 구성 요소

닫힌 모델은 '동시에 시스템에 머무는 사용자 수(동시 사용자 수)'를 기준으로 부하를 유지하는 모델이에요.

setUp(
  scn.inject(
    constantConcurrentUsers(10).during(10), // 1
    rampConcurrentUsers(10).to(20).during(10) // 2
  )
)

닫힌 모델 인젝션 프로필의 빌딩 블록은 두 가지예요.

  1. constantConcurrentUsers(nbUsers).during(duration): 시스템의 동시 사용자 수가 일정하게 유지되도록 주입해요.
  2. rampConcurrentUsers(fromNbUsers).to(toNbUsers).during(duration): 동시 사용자 수가 한 값에서 다른 값으로 선형으로 램프되도록 주입해요.

계단식(Stairs) 부하

닫힌 모델도 incrementConcurrentUsers 헬퍼로 계단식 부하를 만들 수 있어요.

setUp(
  scn.inject(
    incrementConcurrentUsers(5)
      .times(5)
      .eachLevelLasting(10)
      .separatedByRampsLasting(10)
      .startingFrom(10)   // Int
  )
)

인젝션 단계 체이닝

한 시나리오에 인젝션 단계들을 시퀀스로 넘길 수 있어요. 단, 단계들은 모두 같은 모델 종류여야 해요. 다음 인젝션 단계는 현재 단계가 정의한 모든 가상 사용자가 시작되고 나서 시작돼요.

// open model
setUp(
  scn.inject(
    // 먼저 도착률을 1분 동안 0→100 users/s로 램프
    rampUsersPerSec(0.0).to(100.0).during(1.minute),
    // 그다음 10분 동안 100 users/s 유지
    constantUsersPerSec(100.0).during(10.minutes)
  )
)
// closed model
setUp(
  scn.inject(
    // 먼저 동시 사용자 수를 1분 동안 0→100으로 램프
    rampConcurrentUsers(0).to(100).during(1.minute),
    // 그다음 10분 동안 100명 동시 유지
    constantConcurrentUsers(100).during(10.minutes)
  )
)

순차 시나리오(Sequential scenarios)

andThen으로 시나리오를 순차 실행할 수 있어요. andThen을 체이닝하면 Gatling은 이전 자식의 모든 사용자(후손 포함)가 종료돼야만 새 자식을 시작하도록 정의해요.

setUp(
  parent.inject(injectionProfile)
    // parent의 마지막 사용자가 종료되면 child1·child2가 동시에 시작
    .andThen(
      child1.inject(injectionProfile)
        // child1의 마지막 사용자가 종료되면 grandChild가 시작
        .andThen(grandChild.injectClosed(injectionProfile)),
      child2.injectClosed(injectionProfile)
    )
    // 마지막 grandChild와 child2 사용자가 종료되면 child3 시작
    .andThen(child3.injectClosed(injectionProfile))
)

더 알아보기