TOMCAT 동작 방식 과 트래픽이 많아 서버가 감당하지 못하는 상황을
어떻게 예방 할 지에 대해 정리해본다.
🦐 WEB-SERVER 는 아파치 기준, WAS는 tomcat 기준으로 본다.
🤨 사용자의 요청이 Tomcat에 도달해 응답하기까지.
🥸 동작 순서 :
→ 사용자가 웹 브라우저 접근, 사용자의 요청 발생.
→ 80 포트로 web server 전달
→ web server에서 처리 할 정적인 컨텐츠가 아니라면 tomcat으로 요청 ( AJP 포트 통상 8009 )
→ Tomcat Connector에서 체크
→ Tomcat Servlet Container 에서 사용자의 요청 분석 및 HttpServletRequest , HttpServletResponse 생성
→ 어느 서블릿에 대한 요청인지 확인.
→ 인스턴스 생성 또는 기존 인스턴스 사용
→ Servlet service() 호출 POST / GET 등 요청 방식 확인
→ 실행된 메소드는 동적 페이지 생성
→ HttpServletResponse로 응답전송
→ HttpServletRequest / HttpServletResponse 객체 소멸.
😌 80번 포트로 Apache Web Server에 전달 →
* Apache Web Server는 HTML 파일 및 이미지 등
정적 컨텐츠는 WAS 로 보내지 않고 웹서버에서 처리 및 응답하는 선택을 할 수 있다.
그 외, 동적 처리가 필요하다면 TOMCAT의 AJP 포트 ( 통상 8009 포트) 로 요청을 톰캣에 전달한다.
AJP 포트
- 톰캣 - 아파치 연계 설정 ( AJP - Apache JServ Protocol )
톰캣의 server.xml 에 8080 Http 프로토콜을 사용하는 커넥터를 주석처리하고,
AJP 커넥터를 설정함으로써 쓸 수 있다. ( 아파치 서버의 설정도 필요하다 )
→ Tomcat Connector → Tomcat Server로 요청이 도달한다.
🤨 Tomcat 까지 요청이 왔다면, 응답을 받아야한다.
Tomcat은 서블릿 컨테이너를 통해 서블릿을 제공한다.
Servlet 은 사용자의 요청을 동적인 컨텐츠로 응답하기 위한 프로그램이자 Java EE의 표준 API 이다.
( javax.servlet.Servlet ) 특정 포트를 감지하거나, 클라이언트와 직접 연결을 맺지않는다.
Servlet Container ( Tomcat )에 의해 포트 , 연결 , 외부 리소스 접근 및 제한 기능이 관리된다.
→ 때문에 컨테이너 환경에서 servlet이 재활용 될 수 있고, 다른 개발 설정과 의존 관계가 분리된다.
따라서 Rest API의 EndPoint가 되거나 WebPage를 제공하는 프로그램이 될 수 있다.
• 클라이언트의 요청 > HTTP request > 서블릿 컨테이너에 전송
• 서블릿 컨테이너는 HttpServletRequest , HttpServletResponse 두 객체 생성하고,
사용자가 요청한 URL을 분석 → 어느 서블릿에 대한 요청인지 확인
• 해당 서블릿 요청한 적이 없거나, 현재 메모리에 생성된 인스턴스가 없다면 새로 생성
→ init() 메소드 실행 (초기화) → 스레드 생성 → 이미 인스턴스 있을 경우 스레드만 하나 생성
• 컨테이너는 서블릿 service() 호출 → POST , GET 여부에 따라 doGet() 또는 doPost() 호출
• 실행된 메소드는 동적인 페이지 생성 → HttpServletResponse 객체에 응답을 보냄.
• 응답 완료 시, HttpServletRequest, HttpServletResponse 두 객체를 소멸.
→ 서블릿 컨테이너 - 서블릿으로부터 받은 HttpServletRequest , HttpServletResponse
🤢 요청과 응답이 많은 경우.
사용자의 요청이 쏟아지고, 비즈니스 로직이 바쁘다면, 트래픽이 넘친다면. 더이상 수용 할 수 없는 양이라면,
터진다.
이러한 상황 예방을 위해서,
• Apache Web Server 설정으로 적절한 응답이 되도록 설정값을 미리 확인한다.
• MaxClient 및 ServerLimit 설정
* MaxClient : 동시 접속 가능한 클라이언트의 최대 수
* ServerLimit : 프로세스 수의 최대 수.
* 설정은 ServerLimit >= MaxClient로 설정해야하며, 기본값은 둘다 256이다.
• 설정이 무조건 크다고 좋진않다.
* 메모리 점유율이 커지며 OS단에서 문제가 되거나,
* CPU 100% 점유로 동작불능 상태가 되는 불상사가 일어날지도 모른다.
최적 설정값은 공식 사이트를 참고하는게 좋다.
web-server 와 마찬가지로 was에서도 설정이 가능하다.
Tomcat은 버전에 따라 커넥터가 다르다.
• Tomcat 커넥터의 버전별 동작 방식.
Connector는 특정 TCP port에서 request들을 listen하여 engine으로 보내준다.
* 앞서 말한 AJP 설정도 커넥터에 해당.
커넥터마다 동작 방식을 설정 할 수 있다.
protocol 을 지원하는 connector 선정 → 해당 커넥터 동작방식 선택하며,
설정 값들로 제어가 가능하다. ( 파라미터로 지정 )
- maxThreads :Connector 가 생성 가능한 최대 쓰레드 수
- maxConnections : 동시 처리 가능한 최대 Connection 수 BIO방식은 maxThreads 값과 동일함, NIO = 10,000, APR = 8,192
- maxSpareThreads : 최소 실행 유지할 쓰레드 수.
- acceptCount : 모든 쓰레드가 사용 중일 때, queue에 저장 가능한 최대 request 수. ( 대기로 넘길 개수 )
😢 서버가 바쁘다면, ( Thread pool 내에 Idle Thread가 없다면 )
사용자의 요청은 Queue로 대기상태가 된다.
대기중임에도 요청이 많아 aceptCount를 넘치게 하는 요청이 올 경우?
→ 응답 ( 오류 ) 로 나타난다.
- 보통 큐에 메시지가 쌓여있다는 의미는 톰캣 인스턴스가 처리할 수 있는 쓰레드가 없다는 상황이며, 쓰레드를 사용해도 요청을 처리하지 못한다는 것은 이미 장애 상태일 가능성이 높다.
따라서 오류, 즉 queue대기 보다는 빠른 응답을 원한다면 acceptCount 수를 적게 잡아서 처리 할 수도 있다.
😓 대기로 넣고 싶지 않아서, 요청에 즉각적으로 응답을 주고 싶으니까.
Connector가 생성 가능한 최대 쓰레드 ( MaxThread )를 늘릴 수 있다.
하지만 MaxThread를 무작정 늘린다고 응답을 전부 커버 할 수 있지는 않다.
- MaxThread는 순간 처리 가능한 트랜잭션이지만, 너무 많을 경우 쓰레드 문맥 교환으로 인해 되려 느려질 우려가 있다. 성능 테스트를 통해 서버 환경에 적절하게 조절하는 것이 좋다.
문맥 교환이란 현재까지의 작업 상태나 다음 작업에 필요한 각종 데이터를 저장하고 읽어오는 작업을 가리킨다. 이러한 문맥 교환에 걸리는 시간이 커지면 커질수록, 멀티 스레딩의 효율은 저하된다. 오히려 많은 양의 단순한 계산은 싱글 스레드로 동작하는 것이 더 효율적일 수 있다. 따라서 많은 수의 스레드를 실행하는 것이 언제나 좋은 성능을 보이는 것은 아니라는 점을 유의해야 한다. |
Tomcat은 jvm 위에서 동작하고 jvm 은 OS에서 돌아간다.
'WAS' 카테고리의 다른 글
톰캣 실행 시간 설정 (0) | 2022.02.02 |
---|