14. 서버를 어떻게 세팅해야 할까?

웹 서버의 Keep Alive

웹 서버와 웹 브라우저가 연결 되었을때 KeepAlive 기능이 켜져 있지 않으면, 매번 HTTP 연결을 맺었다 끊었다 하는 작업을 반복한다. KeepAlive 기능이 켜져 있으면 두 개 정도의 연결을 열어서 끊지 않고, 연결을 계속 재사용할 수 있다. KeepAlive 설정을 할 때는 반드시 KeepAlive-Timeout 설정도 같이 해야 한다. 이 설정은 초 단위로 KeepAlive가 끊기는 시간을 설정하기 위한 부분이다. 마지막 연결이 끝난 이후에 다음 연결이 될 때까지 얼마나 기다릴지를 지정한다.

KeepAliveTimeout 15

사용자가 너무 많아 접속이 잘 안될 경우, 이 설정을 5초 정도로 짧게 주는 것도 서버의 리소스를 보다 효율적으로 사용할 수 있는 방법이다.

DB Connection Pool 및 스레드 개수 설정

DB Connection Pool은 보통 40~50개로 지정하며, 스레드 개수는 이보다 10개 정도 더 지정한다. 가장 좋은 방법은 성능 테스트를 통해서 가장 적절한 값을 구하는 것이다.

DB의 CPU 사용량이 100%에 도달했다면 CPU를 점유하는 쿼리를 찾아서 튜닝해야 한다. 인덱스가 없거나 테이블을 풀 스캔하는 쿼리가 있는건 아닌지 쿼리의 플랜을 떠서 확인해 봐야 한다.

DB의 CPU 사용량이 50%도 되지 않는 상황에서 WAS의 CPU 사용량이 100%에 도달했다면 WAS의 애플리케이션을 튜닝해야 한다. 이미 튜닝된 상태라면 서버의 DB Connection Pool의 개수는 약간 여유를 두기 위해서 25~30개 정도로 지정하는 것이 좋다(서버를 늘리는 것은 가장 마지막에 해야 한다).

Connection Pool의 개수만큼 중요한 값이 대기 시간(wait time)과 관련된 값이다. DB Connection Pool의 개수를 넘어 섰을 때 애플리케이션에서는 ‘어디 남는 Connection 없나?’ 하고 두리번거리면서 기다린다. 대기 시간이 20초라면 DB 연결을 못해 기다리는 사용자들이 적어도 20초는 대기해야 한다는 말이다.

대기 시간을 100ms 정도로 줄 경우에는 문제가 없을까? 필자가 경험한바로는 메모리를 1GB로 할당한 WAS에서 300ms 이하의 Full GC 시간을 만들기는 매우 어렵다. 만약 DB 연결을 하려고 대기하는 순간 Full GC가 발생하면 그 순간에 대기하고 있는 모든 스레드는 DB와 연결을 못했다고 Timeout을 내뿜을 수도 있다.

WAS 인스턴스 개수 설정

예를 들어 CPU core 개수가 모두 36개인 장비가 있다. 인스턴스가 1개 일때 500 TPS가 나오고, 인스턴스가 2개 일때 700 TPS, 인스턴스가 3개 일때 720 TPS, 4개 일때 730 TPS가 나온다고 가정하다. 필자라면 이 상황에서 인스턴스를 2~3개 정도만 띄울 것이다. 인스턴스를 더 늘린다고 해서 TPS가 증가하지 않는 상황에서는 오히려 유지보수성만 떨어지기 때문이다.

만약 WAS 장비에 4GB의 여유 메모리가 있다고 하더라도 하나의 인스턴스에 4GB의 메모리를 지정하여 사용하는 것은 굉장히 좋지 않은 방법이다. 왜냐하면 Full GC가 발생할 때마다 많은 시간이 소요될 확률이 커지기 때문이다. 가급적이면 512MB~2GB 사이에서 메모리를 지정하는 것이 좋다. 예를 들어 1GB로 메모리를 지정하여 2개의 인스턴스를 사용하는 것이 좋은 방법일 것이다.

Session Timeout 시간 설정

WAS에서 따로 설정한 바가 없거나 세션 객체의 invalidate() 함수가 수행되지 않으면 세션은 삭제되지 않으므로 유의하자.