웹 개발
VPS 운영하면서 메모리 문제 진단하는 법
메모리 부족으로 서버가 느려지거나 프로세스가 죽을 때 어디서부터 봐야 할까.
메모리 부족 증상과 원인
서버가 갑자기 느려지거나 특정 시간대에만 느려진다면, 메모리 부족을 의심해봐야 한다. 내 경우엔 매일 밤 11시쯤 MySQL 쿼리가 시간초과되는데, 알고 보니 메모리가 거의 없어서 스왑 디스크를 사용하고 있었다.
메모리 문제는 데이터베이스 쿼리가 크거나, 캐시를 너무 많이 저장했거나, 메모리 누수가 있는 애플리케이션이 원인일 수 있다.
현재 메모리 상태 확인하기
먼저 전체 메모리 사용량을 본다.
free -h
출력 예:
total used free shared buff/cache available
Mem: 62Gi 45Gi 2.3Gi 1.2Gi 14Gi 16Gi
Swap: 31Gi 8.5Gi 22Gi
available 값이 중요하다. 이게 1GB 미만이면 시스템이 스왑을 많이 쓸 가능성이 높다.
어떤 프로세스가 메모리를 많이 쓰는지 본다.
ps aux --sort=-%mem | head -20
프로세스별로 메모리 사용량을 볼 수 있다. Docker를 쓰는 경우 컨테이너별로도 확인할 수 있다.
docker stats
메모리 누수 찾기
같은 프로세스가 계속 메모리를 더 쓰고 있다면 메모리 누수를 의심해야 한다. 몇 시간 동안 메모리 사용량을 모니터링해본다.
# 특정 프로세스의 메모리만 계속 모니터링
watch -n 5 'ps aux | grep process_name'
메모리가 계속 증가한다면 애플리케이션 코드를 봐야 한다. Node.js라면 힙 스냅샷을 떠볼 수 있고, Python이라면 memory_profiler를 써볼 수 있다.
캐시와 버퍼 정리
때로는 OS 캐시가 너무 커져서 가용 메모리가 적어 보이기도 한다. 하지만 이 캐시는 필요시 자동으로 해제되므로, 보통은 정리할 필요가 없다.
# 캐시 정리 (필요시에만)
sync
echo 3 > /proc/sys/vm/drop_caches
더 중요한 건 불필요한 프로세스를 종료하는 것이다. 테스트용 서버가 계속 떠있거나, 예전 버전의 애플리케이션이 백그라운드에서 도는 경우가 있다.
메모리 설정 최적화
MySQL의 경우 메모리 설정을 너무 크게 잡으면 안 된다.
# /etc/mysql/mysql.conf.d/mysqld.cnf
innodb_buffer_pool_size=8G
innodb_log_file_size=512M
전체 메모리의 75% 정도를 넘지 않도록 하자. 다른 프로세스가 실행될 공간도 필요하다.