25. 수용 제어·부하 차단 부재로 인한 메타안정 장애 (C#)

난이도 상 해설 보기 →

결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커 (A)(B) 는 주목 위치 힌트다.

결함 코드 · C#
// 시나리오: 게임 백엔드의 인벤토리/매치메이킹 API 서버 한 대.
//   - 프런트에서 들어온 요청을 무제한 작업 큐에 넣고, 고정 크기 워커 풀이 순서대로 처리한다.
//   - 각 요청에는 클라이언트가 정한 데드라인(DeadlineUtc)이 있고, 데드라인이 지나면
//     클라이언트는 응답을 버리고 재시도한다(같은 작업을 다시 제출).
//   - 평상시엔 여유가 있지만, 이벤트 오픈/점검 직후 순간 부하가 스파이크로 몰린다.
//
// 요구사항:
//   1) 순간 부하가 처리 용량을 초과하면, 서버는 초과분을 빠르게 거절해
//      큐가 무한히 자라지 않게 해야 한다.
//   2) 이미 데드라인이 지난(클라가 포기한) 요청은 처리하지 않고 버려, 헛일을 막아야 한다.
//   3) 스파이크가 끝나면 시스템은 스스로 정상 지연으로 회복해야 한다.
//
// 과제: 아래 RequestServer 를 검토하여, 부하 스파이크 시 큐가 폭증하고 재시도가
//       증폭되어 스파이크가 끝난 뒤에도 과부하가 지속되는 지점을
//       (A)(B) 마커로 진단하고, 정확한 수정안과 더 나은 설계를 제시하라.

using System;
using System.Collections.Concurrent;
using System.Threading;

public sealed class Request
{
    public long Id;
    public DateTime DeadlineUtc;   // 이 시각 이후엔 클라가 응답을 버리고 재시도
    public Action Work;            // 실제 처리
}

public sealed class RequestServer
{
    private readonly ConcurrentQueue<Request> _queue = new();
    private readonly SemaphoreSlim _signal = new(0);
    private readonly int _workers;

    public RequestServer(int workers)
    {
        _workers = workers;
        for (int i = 0; i < workers; i++)
            new Thread(WorkerLoop) { IsBackground = true }.Start();
    }

    // 프런트가 요청을 제출한다.
    public void Submit(Request req)
    {
        _queue.Enqueue(req);       // (A) 들어오는 대로 큐에 넣는다
        _signal.Release();
    }

    private void WorkerLoop()
    {
        while (true)
        {
            _signal.Wait();
            if (!_queue.TryDequeue(out var req))
                continue;

            req.Work();            // (B) 데큐한 요청을 실행한다
        }
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

작성 후 위 해설 보기에서 모범 해설과 대조하세요.