Tomcat 튜닝 가이드
해당 게시물은 개인 메모용이다.
Tomcat 튜닝 가이드
Server.xml
Connector
protocol=”org.apache.coyote.http11.Http11NioProtocol”
- Tomcat은 네트워크 통신에 대해 3개의 옵션을 제공한다. BIO, NIO, APR 3가지이다.
- BIO vs NIO vs APR
- 디폴트 값은 BIO이다(HTTP/1.1).
acceptCount=”10”
- request Queue의 길이를 정의한다. 클라이언트가 HTTP Request를 요청했을 때 Idle Thread가 존재하지 않을 때, Idle Thread가 생길 때 까지의 대기 길이이다.
- 보통 큐에 메시지가 쌓여있다는 의미는 톰캣 인스턴스가 처리할 수 있는 쓰레드가 없다는 상황이며, 쓰레드를 사용해도 요청을 처리하지 못한다는 것은 이미 장애 상태일 가능성이 높다.
- 디폴트 값은 100이다.
enableLookups=”false”
- HttpServletRequest.getRemoteHost()는 DNS Lookup을 통해 클라이언트의 도메인을 반환하며, HttpServletRequest.getRemoteAddr()는 클라이언트의 IP 정보를 반환한다. enableLookups을 false로 지정할 경우, getRemoteHost()는 getRemoteAddr()과 같이 IP 정보를 반환한다. 즉, DNS Lookup 과정을 생략한다.
- 디폴트 값은 false이다.
compression=”off”
- 네트워크 대역폭을 절약하기 위해, HTTP Body를 GZIP 형태로 압축하여 response한다. 만약 HTTP Response Body의 크기가 클 경우, 해당 기능을 사용하는 것이 좋다.
- 해당 기능은 compressionMinSize(일정 사이즈 이상부터 압축), compressibleMimeType(압축하고자하는 마임 타입 지정)와 같은 부가 기능과 함께 사용한다.
- 해당 기능을 사용하여 Response할 때 Response Header는 Content-Encoding: gzip이라 표기한다.
- 디폴트 값은 off이다.
maxConnections
- 서버가 허용할 수 있는 최대 커넥션 수이다. 최대 커넥션 수가 도달하면 해당 메시지는 큐잉한다. 이때 큐 사이즈는 acceptCount가 결정한다. 해당 큐에서 처리를 대기한다.
- 디폴트-NIO: 10000, APR/BIO: 8192
maxKeepAliveRequests=”1” or maxKeepAliveRequests=$maxConnections_val
- HTTP 프로토콜(1.1)의 Keep Alive Connection을 사용할 때 최대 유지할 Connection의 수를 결정한다. Stateless REST API 서버의 경우, 1을 설정한다. Stateful한 웹페이지 서버의 경우, maxKeepAliveRequests는 maxConnection의 수치와 동일하게 설정한다.
- 디폴트는 100이다. 1은 비활성화, -1은 무제한이다.
- HTTP 프로토콜은 Stateless(Connection less) 프로토콜이다. 즉, 모든 요청은 1회성 요청이며, 커넥션은 재활용되지 않는다.
- Pros and cons
Pros
- 핸드 셰이킹 생략으로 인한 네트워크 레이턴시 감소
- 커넥션을 새로 만들지 않기 때문에 cpu 사용량 감소
- HTTP 파이프 라이닝 사용
Cons
- 리소스 낭비 우려
- (HTTP/1.1의 Default Connection 방식은 Keep-Alive이다. 그러나, 서버 측에서 해당 기능을 비활성화면 HTTP 프로토콜의 Keep Alive 기능을 사용하지 못한다.)
- (해당 기능을 비활성화 하면, HTTP Response Header에서 Connection:close 표기된다.)
- (TCP의 KeepAlive와 HTTP KeepAlive는 다르다.)
maxThread=”500~750”
- 톰캣 내의 쓰레드 수를 결정하는 옵션이다. 쓰레드의 수는 실제 Active User 수를 의미한다. 즉 순간 처리 가능한 트랜잭션의 수이다. 그러나, 너무 많은 수치는 쓰레드 문맥 교환으로 인해 되려 느려질 우려가 있다.
- 해당 설정은 성능 테스트를 통해 서버 환경에 절적할게 조절하는 것이 괜찮다.
- 디폴트는 200이다.
tcpNoDelay=”true”
- 톰켓은 패킷들을 모아서 버퍼 사이즈에 맞춰 보내는 로직을 사용한다. 보내고자 하는 패킷이 버퍼 사이즈에 못 미치면 일정시간 또는 버퍼가 찬 후 보낸다. 해당 설정 true를 통해 바로바로 보낼 수 있도록 한다.
- 디폴트는 true이다.
DB 커넥션 풀
DataSource 리소스 설정
- 보통 Tomcat을 사용할 때 Tomcat 설정 파일에 DataSoure 리소스를 설정한다.
- DataSource 리소스에 커넥션 풀을 운영 환경에 맞게 설정한다.
- maxActive / maxWait / maxIdle / minIdle
Tomcat JDBC Connection Pool 사용
- Common DBCP 보다 Tomcat JDBC를 사용한다.
- Commons DBCP vs Tomcat DBCP
- Commons DBCP, 단일 쓰레드(2.x 버전에서 해결됨)
- Commons DBCP, 느리다(2x 버전에서 해결).
- Commons DBCP, 업데이트 주기가 느리다.
- Tomcat DBCP의 새로운 기능 추가
- https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html
- http://vigilbose.blogspot.com/2009/03/apache-commons-dbcp-and-tomcat-jdbc.html
Tomcat 멀티 컨테이너 구성 관련
라이브러리 구성
- 하나의 톰캣에 여러 개의 WAR 파일을 동시에 배포할 때 같은 라이브러리가 각각 다른 클래스 로더로 배포되기 때문에 메모리 효율성이 떨어진다. 해당 라이브러리는 $tomcat/lib에 통합적으로 관리한다.
Tomcat 멀티 컨테이너 구성할 때 Executors의 사용
- Executor는 멀티 컨테이너 환경에서 쓰레드 풀을 공유한다. 공유를 통해 쓰레드의 낭비를 막을 수 있다.
- https://tomcat.apache.org/tomcat-8.0-doc/config/executor.html
Tomcat은 JVM위에서 돌아가고 JVM은 OS위에서 돌아간다. Tomcat의 퍼포먼스 향상은 JVM과 관계 있고, OS설정에 관계가 있다. 그 이상의 충분한 속도와 최적화는 JVM의 이해와 OS의 이해가 요구된다. 해당 게시물은 JVM/OS 설정 튜닝을 다루지 못했다. 해당 게시물을 작성하면서 한계점을 많이 느꼈다. 진짜 어플리케이션의 성능 튜닝은 OS의 이해까지 내려가야 한다는 점에 정말 한계를 느꼈다. 시간은 부족한데 배워야할 것은 너무 많다.
참고문헌
http://tomcat-configure.blogspot.com/2009/01/tomcat-maxthreads-configuration.html
https://www.eginnovations.com/blog/tomcat-performance-tuning/