게임 렉 백서 › L9 서버 게임 프로세스
데드락 Deadlock
원인 ID sp-deadlock · 주 담당 게임개발팀·서버 개발
그림과 실험이 있는 원본 카드로 열기 →
두 스레드가 서로 상대가 잡은 락을 기다리면 영원히 멈춥니다.
왜 스레드 A는 락1을 잡고 락2를, B는 락2를 잡고 락1을 기다림 → 그러면 둘 다 영원히 멈추고 관련 스레드도 줄줄이 멈춤 → 화면에서는 서버 전체 정지, 워치독이 재시작하며 전원 접속 끊김
- 증상
- 멈춤, 접속 끊김
- 요인
- 정체
- 누가 겪나
- 서버 전체, 특정 기능만
- 언제
- 가끔 무작위로, 사람이 몰릴 때
- 담당
- 주 담당 게임개발팀·서버 개발
- 게임개발팀 할 일
- 락 순서 규칙, 타임아웃 있는 락, 워치독과 멈춘 순간의 스레드 덤프 남기기.
- 그래프에서는
- 연결이 한꺼번에 끊김 · 접속 수, 서버 송신량
- 확인할 곳
- 멈춘 동안 모든 스레드의 호출 스택을 뜸. JVM은 jstack(데드락을 자동으로 찾아 표시), .NET은 dotnet-stack, 네이티브 서버는 gdb의 thread apply all bt, 또는 gcore로 코어 파일을 떠 두고 재시작한 뒤 분석
- 이러면 맞음
- 두 개 이상의 스레드가 서로 상대가 잡은 락을 기다리는 스택으로 멈춰 있고, 그동안 프로세스 CPU 사용률이 0에 가까움
- 이러면 아님
- 멈춘 동안 스레드 하나가 CPU 100%로 돌고 있으면 무한 루프. 스레드들이 DB·외부 응답을 기다리고 있으면 동기 호출이나 스레드 풀 고갈 쪽
- 확인 수단
- 인프라 도구로 확인(게임 코드 불필요)
출처
- Runtime locking correctness validator Linux kernel
두 락을 서로 반대 순서로 잡으면 순환 대기로 데드락(lock inversion deadlock), 리눅스 커널은 락 순서를 검사해 미리 경고 - Liveness, Readiness, and Startup Probes Kubernetes
실행 중이지만 진행하지 못하는 데드락 상태를 라이브니스 검사로 잡아 컨테이너를 재시작 - Diagnostic Tools (Java SE 21 Troubleshooting Guide) Oracle
jstack은 실행 중인 JVM의 모든 스레드 스택을 출력하고 데드락도 찾아 표시(Found one Java-level deadlock) - dotnet-stack diagnostic tool - .NET CLI Microsoft
.NET 프로세스의 모든 스레드의 관리 스택을 캡처해 출력 - Threads (Debugging with GDB) GNU Project
thread apply all로 모든 스레드에 같은 명령(bt: 호출 스택 출력)을 실행 - gcore(1) — Linux manual page gdb
실행 중인 프로그램의 코어 파일을 만들고 만든 뒤에도 프로그램은 그대로 계속 실행
함께 보면 좋은 원인
같은 층: L9 서버 게임 프로세스
같은 증상(멈춤)의 다른 층 원인
그림과 실험이 있는 원본 카드 보기