들어가며
지금까지 시리즈에서는
- GC와 멀티스레딩의 관계
- GC 로그 분석 방법
- GC 로그 한 줄 해석
- GC 튜닝 전/후 비교
까지 살펴봤습니다. 이번 편에서는 한 단계 더 실무로 들어가,
ASP.NET 서버에서 실제로 가장 자주 발생하는 GC 장애 패턴
을 정리합니다.
이 글의 목표는 단순합니다.
- 장애를 "겪고 나서" 분석하는 것이 아니라
- 미리 로그만 보고 위험을 감지할 수 있게 만드는 것
입니다.
패턴 1. 요청당 대형 객체 생성 (LOH 폭발)
증상
- 일정 시간마다 서버 멈춤
- 응답 지연이 계단식으로 증가
GC 로그 특징
GC(2) Pause 700ms
LOH Size: 1.8GB
원인 코드
public IActionResult Download()
{
return File(new byte[500_000], "application/octet-stream");
}
해결 방법
- ArrayPool 사용
- 스트리밍 응답
var buffer = ArrayPool<byte>.Shared.Rent(500_000);
패턴 2. 캐시 객체 누적으로 인한 Gen2 압박
증상
- 메모리 사용량이 천천히 계속 증가
- 재시작 전까지 회복되지 않음
GC 로그 특징
GC(2) Pause 400ms
Heap Size: 2800MB -> 2700MB
원인 코드
static Dictionary<string, object> Cache = new();
해결 방법
- 만료 정책 도입
- WeakReference 사용 고려
패턴 3. 비동기 코드에서의 암묵적 할당 폭증
증상
- CPU 여유 있음
- TPS가 기대보다 낮음
GC 로그 특징
GC(0) Pause 5ms (빈번)
원인 코드
await httpClient.GetAsync(url);
- 클로저
- 상태 머신 객체 생성
해결 방법
- ValueTask 사용
- 불필요한 async 제거
패턴 4. ThreadPool Starvation + GC 결합
증상
- 요청 대기열 급증
- GC Pause가 짧아도 장애 발생
GC 로그 특징
GC Pause 50ms
ThreadPool Queue Length: 증가
원인 코드
Task.Run(() => HeavyWork());
해결 방법
- 비동기 I/O 전환
- Task.Run 남용 금지
패턴 5. Background GC에 대한 오해
증상
- "Background GC니까 안전"이라고 판단
- 실시간 서비스에서 간헐적 끊김
GC 로그 특징
Background GC finished
Final Pause: 120ms
핵심 포인트
- Background GC도 마지막엔 STW 존재
- 짧지만 트래픽 피크와 겹치면 치명적
장애 패턴 빠른 진단 표
증상가장 먼저 볼 것
| 주기적 멈춤 | Gen2 Pause |
| 메모리 증가 | Heap 감소폭 |
| TPS 저하 | Gen0 빈도 |
| 간헐적 끊김 | Background Final Pause |
마무리
GC 장애는 대부분 패턴화되어 있습니다.
같은 문제는 다른 서버에서도 같은 형태로 나타납니다.
이 다섯 가지 패턴만 익혀도,
- 장애 원인 파악 속도가 빨라지고
- 로그를 보는 시선이 완전히 달라지며
- 사전 대응이 가능해집니다.
반응형
'ASP.NET' 카테고리의 다른 글
| 웹에서 클라이언트 브라우져 정보를 취득 (0) | 2013.01.28 |
|---|---|
| ASP.NET MVC 4 を使った Mobile Web ソリューション実装 (0) | 2013.01.28 |