Jackson 네트워크와 MVA로 큐잉 시스템 성능 모델링하기

Jackson 네트워크, 개방형·폐쇄형 큐, Mean Value Analysis를 이용해 서비스 지연과 처리량, 병목을 모델링하는 방법을 정리한다.

2026-08-14 · 최초 발행 2024-04-29

서비스 경로를 큐로 모델링해야 하는 이유

용량 계획과 지연 시간 예측에서는 개별 서버의 성능만으로 충분하지 않다. 요청이 여러 서비스 스테이션을 거치고, 각 지점에서 다시 다른 노드로 이동하는 경로 전체를 봐야 병목과 SLO 위험을 함께 판단할 수 있다.

큐잉 네트워크는 서버와 큐로 이루어진 서비스 스테이션을 라우팅 확률로 연결한 대기·서비스 시스템의 집합이다. 스테이션별 도착률, 서비스 분포, 서버 수, 큐잉 규율을 입력으로 삼아 지연, 처리량, 대기열 길이 같은 지표를 구한다.

Jackson Network는 독립적인 M/M/m 스테이션과 마르코프 라우팅을 갖는 개방형 또는 폐쇄형 네트워크에서 곱형(product-form) 해를 제공한다. 트래픽 방정식으로 도착률 벡터를 구한 뒤, 스테이션별 M/M/m 해를 결합해 네트워크 성능을 계산하는 방식이다.

외부 요청이 들어오고 나가는 구조는 Open Network로, 고정된 고객 수가 시스템 안을 순환하는 구조는 Closed Network로 다룬다. Open Network는 외부 도착률 λ0를 전제로 안정 조건 아래 정상 상태를 분석한다. Closed Network에는 외부 유입과 유출이 없으며, 고정 고객 수 N의 순환을 Mean Value Analysis(MVA) 같은 반복 알고리즘으로 계산한다.

MVA는 고객 수 n=1..N을 순회하면서 스테이션 평균 체류시간 Rk(n), 시스템 응답시간 R(n), 처리량 X(n), 평균 큐 길이 Qk(n)를 갱신한다. 평균 체류시간과 처리량이 서로 영향을 주는 폐쇄형 시스템을 다루는 데 적합하다.

도착률, 방문율, 곱형 해의 역할

Open Jackson 네트워크의 도착률은 다음 트래픽 방정식에서 출발한다.

λ = γ + P^T λ → (I − P^T) λ = γ

γ는 외부 유입률이고 P는 라우팅 행렬이다. 이 선형계를 풀면 각 노드의 도착률을 얻을 수 있다. 방문율 Vk는 기준 노드에 대한 상대 방문 빈도이며, 병목을 식별하고 용량을 배분하는 근거가 된다.

곱형 해에서는 각 스테이션의 상태 분포가 독립적인 곱으로 표현된다. 따라서 단일 노드 해를 조합해 전체 네트워크 지표를 계산할 수 있다. 이 모델은 포아송 도착, 지수 서비스, 마르코프 라우팅, FCFS 등을 가정한다. BCMP 확장에서는 일부 비지수 분포와 우선순위도 허용한다.

Open Network는 API 게이트웨이나 공개 웹 요청처럼 외부 트래픽이 시스템을 주도하는 경우에 맞는다. 반대로 DB 커넥션 풀, 스레드풀, 배치 워크로드 순환처럼 사용자·세션·커넥션 수가 고정된 환경은 Closed Network로 보는 편이 자연스럽다.

MVA가 갱신하는 값과 안정성 조건

MVA의 입력은 고객 수 N, 서비스 시간 Sk, 방문율 Vk, 서버 수 mk다. 단순형에서는 mk=1로 둔다. 반복 과정에서는 다음 값을 갱신한다.

  • Rk(n)=Sk·(1+Qk(n−1)/mk)
  • R(n)=Σk VkRk(n)
  • X(n)=N/R(n)
  • Qk(n)=X(n)·Vk·Rk(n)
  • ρk = X(N)·Vk·Sk/mk

이용률 ρk는 안정성 판단의 기준이다. 병목 노드의 이용률이 높아질수록 대기와 응답시간이 커지므로, 파라미터와 서버 구성을 함께 재평가해야 한다.

n≤N아니오n N입력 수집N, S_k, V_k, m_k초기화Q_k(0)=0반복: n=1..N k에 대해R_k(n)=S_k*(1+Q_k(n-1)/m_k)R(n)=Σ V_k * R_k(n)X(n)=N / R(n)Q_k(n)=X(n)*V_k*R_k(n)안정성 검사ρ_k=X(n)*V_k*S_k/m_k < 1?모델/파라미터 조정S_k, m_k, V_k 재평가출력X(N), R(N), Q_k(N), ρ_k

유입형 시스템과 순환형 시스템의 차이

항목 Open Network Closed Network 트레이드오프
분석 용이성 트래픽 방정식으로 도착률 해석 용이 MVA 반복 필요, 민감도 높음 단순성 vs 정밀 순환 효과 반영
확장성 외부 트래픽 스케일에 선형 반응 N 증가 시 병목 급격 노출 수평 확장 vs 풀 크기/동시성 관리
안정성/수용도 ρ<1 유지 시 안정 N 고정으로 안정적이지만 병목 시 지연 급증 유입 제어 vs 풀 제어
모델링 목적 유입 기반 처리량/대기 예측 사용자/세션 순환 응답시간 예측 관문지표(X, W) vs 사용자 체감(R)
운영 편의 라우팅/유입률 제어 중심 풀 크기/서버 증설/쿼럼 조정 중심 트래픽 엔지니어링 vs 리소스 엔지니어링

전자상거래 요청 경로에서 Jackson 모델 적용

CDN→API Gateway→App→Cache→DB처럼 외부 요청이 유입되는 경로는 Open Jackson 모델로 분석할 수 있다.

라우팅 행렬 P는 APM이나 분산 트레이싱으로 전이 확률을 계산해 추정한다. 서비스 시간 Sk는 계측하며, p99/p95는 추가 검증 지표로 활용하되 모델의 기본값은 평균이다. 이후 (I−P^T)λ=γ를 풀어 각 노드의 도착률 λk와 이용률 ρk=λk·Sk/mk를 구한다.

ρk가 가장 큰 노드가 병목 후보가 된다. m을 증설하거나 Sk를 최적화하고, 캐시 적중률 개선으로 서비스 시간에 여유를 만들어 이용률을 낮춘다.

DB 커넥션 풀과 내부 워커 풀은 폐쇄형으로 본다

Web Thread Pool과 고정 연결 수의 DB Pool은 Closed Network에 해당한다. N은 스레드 수 또는 동시 세션 수로 두고, Vk와 Sk를 입력해 MVA로 X(N), R(N)을 계산한다. 이때 ρDB<1 제약을 확인해야 한다.

목표 R(SLO)을 달성하기 위한 조정안은 N, mDB, Sk에서 찾을 수 있다. 인덱스와 쿼리 최적화는 Sk를 바꾸고, DB 서버 구성은 mDB에 영향을 준다.

외부 Kafka 유입과 내부 워커 풀이 결합된 메시지 처리 파이프라인은 두 모델을 함께 쓸 수 있다. 외부 유입은 Jackson으로, 내부 워커 풀은 MVA로 분리 분석한 뒤 인터페이스 처리량이 일치하도록 합성한다.

계측부터 검증까지의 모델링 흐름

서비스 경로의 스테이션을 나열하고 외부 유입·유출 지점, 동시성 제약을 먼저 구분한다. 이후 X/λ, Sk(평균/표준편차), P 또는 V, mk를 수집하며 샘플링 기간과 부하 수준을 표준화한다.

Open Network에서는 트래픽 방정식을 푼 뒤 각 노드의 대기·응답시간 Wk를 계산한다. M/M/1에서는 Wk = Sk/(1−ρk)다. Closed Network에서는 MVA 반복으로 X(N), R(N), Qk(N)을 산출한다.

예측값과 관측값의 차이는 비지수 분포, 서비스 타임 변동계수, 버스트와 코호트 효과에서 생길 수 있다. 필요하면 BCMP 근사, CoV^2 반영, 시뮬레이션을 병행한다. 설계에 반영할 때는 병목 노드에서 m 증설, Sk 최적화, 라우팅 확률 조정, 캐시 또는 큐잉 규율 변경 순으로 검토한다.

Open Jackson과 Closed MVA 코드 예시

전제조건: Python 3.10+, numpy 1.26+, 단일 서버(M/M/1) 가정.

import numpy as np

def jackson_open_lambda(P, gamma):
    """
    Open Jackson network arrival rates.
    Solve (I - P^T) * lam = gamma
    P: routing matrix (KxK), gamma: external arrival vector (K,)
    """
    I = np.eye(P.shape[0])
    lam = np.linalg.solve(I - P.T, gamma)
    return lam

def mva_closed(S, V, N, m=None):
    """
    Mean Value Analysis for closed network (simple M/M/m, default m=1).
    S: service times (K,), V: visit ratios (K,), N: population (int)
    m: servers per node (K,) or None -> 1
    Returns: X, R, Q (per-node)
    """
    K = len(S)
    V = np.array(V, dtype=float)
    S = np.array(S, dtype=float)
    m = np.ones(K) if m is None else np.array(m, dtype=float)

    Q = np.zeros(K)
    X = 0.0
    for n in range(1, N+1):
        Rk = S * (1.0 + Q / m)  # approximate for M/M/m with m servers
        R = float(np.sum(V * Rk))
        X = n / R
        Q = X * V * Rk
        rho = X * V * S / m
        if np.any(rho >= 1.0):
            raise RuntimeError(f"Unstable at n={n}, rho={rho}")
    return X, R, Q

# Example
P = np.array([[0.0, 0.3],
              [0.1, 0.0]])
gamma = np.array([100.0, 0.0]) / 1000.0  # 100 req/s to node 0
lam = jackson_open_lambda(P, gamma)
S = np.array([3e-3, 5e-3])  # 3ms, 5ms
rho = lam * S
print("Open λ:", lam, "Utilization ρ:", rho)

V = np.array([1.0, 0.5])  # visits per cycle
X, R, Q = mva_closed(S, V, N=50, m=[2,1])
print("Closed X:", X, "R:", R, "Q:", Q)

코드는 ρ≥1이면 RuntimeError를 발생시키므로, 해당 상황에서는 파라미터를 재평가하거나 서버 증설을 검토해야 한다. M/M/1과 지수 분포를 가정하며, 고분산 서비스 시간(CoV^2>1) 환경에서는 보수적 근사 또는 시뮬레이션이 필요하다.

병목을 앞당겨 발견했을 때의 효과

병목 노드 사전 식별 정확도는 내부 실측 기반 사례값으로 +1530%p 향상될 수 있다. 과프로비저닝은 2040% 절감하고, 동일 SLO 달성 기준에서 서버 수를 최소화할 수 있다.

큐잉 지연을 낮추면 p95 응답시간 초과 빈도를 25% 이상 줄일 수 있다. 대규모 부하 테스트를 대체하거나 축소하고, 시뮬레이션 대비 모델 계산 시간을 단축해 실시간 What-if 분석도 가능하다.

정확한 파라미터 계측, ρ<1과 적정 N의 유지, 병목 우선 해소, 검증과 교정의 반복이 모델을 운영 판단에 쓸 수 있게 만든다.

큐잉 네트워크Jackson 네트워크MVA성능 모델링용량 계획