톰캣 기본 및 운영

기본 아키텍처

Tomcat 그것은 두 개의 모듈 공동으로 구성

  • connector
  • container

connector 구문 분석에 대한 책임  HTTP , 예를 들어, 요청을  请求头 ,  查询字符串 ,   등이있다. 세대   와 나중에 넘겨   적절한를 호출 할 책임이있다,   .请求参数HttpRequestHttpResponse 
containerServlet

커넥터

Tomcat 기본값은  Connector 입니다  HttpConnector . 마찬가지로  Connector 우리가 구현해야하는  Connector 이 인터페이스를.

Tomcat 그것은 나중에 열려면 시작 스레드 에 의해 무한 루프를 수행  ServerSocket 요청을 기다리고. 요청이 생성되면  Socket ,이 점에 유의  HttpConnector 자신을 처리하지 않습니다  Socket ,하지만 그것을 줄  HttpProcessor . 자세한 사항은 아래를 참조 코드 여기 난 단지 키 코드를 유지.

공공 무효 실행 () { 
        우리가 shutdown 명령을받을 때까지 // 루프 
        {(! 정지) 동안 
            소켓 소켓 = NULL을; 
            {시도 
                ) (소켓 = serverSocket.accept을; //等待链接
            } 캐치 (AccessControlException가 에이스) { 
                ( "소켓 보안 예외를 허용"에이스) 로그; 
                잇다; 
            } 
            // 적절한 핸드 오프 프로세서 소켓 
            HttpProcessor 프로세서 createProcessor = (); 
            processor.assign (소켓); //这里是立刻返回的
            가 완료되면, 프로세서는 그 자체를 재활용한다 // 
        } 
    }

 

 

위의가 있습니다  processor.assign(socket); 즉시 반환해야하며, 대기가 차단되지 않습니다. Tomcat이 하나 개의 요청을 처리 할 수 없기 때문에, 각, 비동기  processor 프로세스는 별도의 스레드입니다.

HttpProcessor

위의 코드는 쇼 호출하지 않습니다   이 방법은 그것을 호출하는 방법이다, 방법은? 이제 살펴 보자   방법.HttpProcessorprocessHttpProcessorrun

공공 무효 실행 () { 
        // 우리가 종료 신호를받을 때까지 프로세스 요청 
        (! 정지) 동안 { 
            // 다음 소켓 기다립니다 할당 할 
            소켓 소켓 =) (기다리고 있습니다; 
            (소켓 == NULL을)의 경우 
                계속; 
            // 프로세스이 소켓의 요청 
            시도 { 
                과정 (소켓); 
            } 캐치 (의 Throwable t) { 
                로그 ( "process.invoke", t); 
            } 
            이 요청까지 완료 // 
            connector.recycle (이); 
        } 
    }

 

 

우리는 전화 그를 발견  await 얻기 위해 기다리고 차단하는 방법을  socket 방법을. 전에 그리고  Connector 부르심  assign 할당, 그 이유는 무엇인가?

자세히 살펴 다음  await 과  assign 접근 방식. 이 두 가지 방법의 협력,  assign 인수  socket 통지 할 때  await 다음 반환  socket .

 

동기화 무효 할당 (소켓 소켓) { 
    // 이전 소켓을 얻을 수있는 프로세서 기다립니다 
    {(가능) 동안 
        {하려고 
            대기를 (); 
        } 캐치 (예외 : InterruptedException 전자) { 
        } 
    } 
    // 스토어 새로 가능한 소켓과 우리의 스레드에 통지 
    this.socket = 소켓을; 
    가능 = TRUE; 
    의 notifyAll (); 
} 
개인 동기화 소켓을 기다리고 () { 
    // 커넥터가 새로운 소켓을 제공하기 위해 기다립니다 
    {동안 (가능!) 
        {하려고 
            대기를 (); 
        } 캐치 (예외 : InterruptedException 전자) { 
        } 
    }
    // 우리가받은 커넥터를 통지이 소켓 
    소켓 소켓 = this.socket; 
    가능 = 거짓; 
    의 notifyAll (); 
    (소켓) 반환; 
}

 

 

기본값은  available 입니다  false .

그런 다음 충전 요청을 해결 할 일은이 남아  HttpRequest 와  HttpResponse 객체, 다음에  container 책임.

저는 여기에 세부 사항으로 이동하지만, 구문 분석하는 방법을 더

 

개인 무효 처리 (소켓 socket) { 
    // 파싱 
    .... 
    connector.getContainer () (요청, 응답)를 호출한다.; 
    .... 
}

 

 

컨테이너

컨테이너는로부터받은 요청을 실행할 수있는 객체입니다  클라이언트를 , 그 요청에 따라 응답을 반환

 

Container 그것은이 클래스가 구현하는 인터페이스 인터페이스 인스턴스 처리 요구, 해당 통화를 수신 할 수있다  Servlet .

이 네 가지 범주 있습니다  Container , 네  Container 하지 사이에 평행하게,하지만 아버지와 아들의 관계는

  • Engine - 최상위 컨테이너는 복수를 포함 할 수있다 Host
  • Host - 가상 나타내는 호스트가 여러 개 포함 할 수 있습니다 Context
  • Context - 대신  web应用 , 즉  ServletContext , 그것은 여러 포함 할 수 있습니다 Wrappers
  • Wrapper - 대표가  Servlet 가장 낮은 레벨이 다른 컨테이너를 포함 할 수 없습니다

컨테이너 통화

컨테이너 가공 공장, 가공 수용 같다  request , 처리 및 파이프 라이닝은 매우 비슷하지만 조금 다르다. 여기라고 사용됩니다  , 일을 중국어 번역 이다   ,   위해 파이프 라인 처리, 가공 도구를 호출을 넣어   메스처럼되고,   당신이 더 추가 할 수있는   도구를 마무리라고 Pipeline管道requestValvePipelineValveBaseValve

위의 목록은 더 추상적 인 말의 코드를 살펴 보자 수 있습니다. Engine 상부 용기는, 상기 있도록  invoke 의해 수행되는  Engine 방법. StandardEngine 그것은이  Engine 기본 구현, 또한 구현하고 있습니다  Pipeline 인터페이스를, 그리고 포함  Pipeline .

그 건설 방법도 지정되어  baseValve 파이프 라인의 마지막 호출입니다, Valve

공공 StandardEngine () { 
    슈퍼 (); 
    pipeline.setBasic (새 StandardEngineValve ()); 
}

 

 

그럼 우리는 볼  invoke 이 방법에서 상속됩니다  ContainerBase . 사이 만에 하나 개의 라인,  pipeline 처리.

공개 공극 호출 (요청 요청, 응답 응답) 
        IOException이, {ServletException이 발생 
        pipeline.invoke (요청, 응답); 
}

 

 

다음은   기본입니다 실현,   구현.StandardPipelineinvokepipeline

공공 무효의 호출 (요청 요청, 응답 응답) 
        IOException이, ServletException이가 {던졌습니다 
        // 요청이 파이프 라인의 첫 번째 밸브를 호출 
        (새 StandardPipelineValveContext ()) invokeNext (요청, 응답).; 
}

 

 

하나 개의 라인! 전화   입니다 방법,   내부 클래스를. 우리가 살펴 보자StandardPipelineValveContextinvokeNextpipeline

특정 코드

 

공공 무효 invokeNext (요청 요청, 응답 응답) 
            IOException이, ServletException이 발생을 { 
            INT 첨자 = 단계; 
            단 스테이지 = + 1; 
            // 현재 요청 스레드 요청 밸브를 호출 
            하는 경우 (첨자 <valves.length) { 
                밸브 [첨자] .invoke (요청, 응답이); //加工
            } 다른 경우 ((첨자 == valves.length) && (기본 = NULL)!) { 
                basic.invoke (요청, 응답이); 
            } 다른 { 
                새로운 ServletException을 던질 
                    (sm.getString ( "standardPipeline.noValve을")); 
            } 
}

 

 

그것은 통화를  pipeline 사용  Valve 하기 위해  request 처리를 수행 밸브가 실행될 때 호출  BaseValve 위의 인 StandardEngineValve ,

우리는 보는  invoke 방법

 

// 선택 호스트이 요청에 사용되는 
) (StandardEngine 엔진 = (StandardEngine) getContainer에; 
호스트 = (호스트) 엔진 호스트. 지도 (요청, TRUE); 
만약 (호스트 == NULL) { 
    ((HttpServletResponse를) response.getResponse ()) 대해 sendError. 
        (HttpServletResponse.SC_BAD_REQUEST, 
            sm.getString ( "standardEngine.noHost" 
                        request.getRequest () getServerName ()).); 
    반환; 
} 
//이 요청 처리하기 위해이 호스트를 물어 
host.invoke (요청, 응답);

 

 

그것은 통해  (Host) engine.map(request, true); 취득 대응  Host 하고 계속해서 용기를 다음 계층으로 진행한다. 나중에 실행 순서

그리고  Engine 같은, 그러나 많은 내가 갈

 

요약 실행 순서

긴 뛴 후  invoke 완성 된 용기의 제 1 층의 최종 실행 순서. 난 당신이 내가 여기서 무엇을 조금 현기증, 요약을 볼 것 같아요.

커넥터 -> HttpProcessor.process () -> StandardEngine.invoke () -> StandardPipeline.invoke () ->

StandardPipelineValveContext.invokeNext () -> valves.invoke () -> StandardEngineValve.invoke () ->

StandardHost.invoke ()

 

 

여기에 위치하는  Engine 이 층의 끝. 다음이었다  Host 정확히 같은 단계는,

StandardHost.invoke () -> StandardPipeline.invoke () ->

StandardPipelineValveContext.invokeNext () -> valves.invoke () -> StandardHostValve.invoke () ->

StandardContext.invoke ()

 

 

그 다음에  Context 이 층의 처리는 마지막에 대응하는 선택  Wrapping 실행된다.

싸개

Wrapper (A)에 상응하는  Servlet 예를 들면,  StandardContext 더 따른 것  request 선택에 대응하는  Wrapper 통화. 우리는 직접 살펴

Wrapper 중  basevalve 전화 할 경우는   방법. 다음은   내가 많이 생략 방법은,ServletserviceStandardWrapperValveinvoke

키 봐.

 

공공 무효의 호출 (요청 요청, 응답 응답 
                       ValveContext valveContext)는 
        IOException가, ServletException이가 {던졌습니다 
        // 할당 서블릿 이 요청을 처리하기 위해 인스턴스를 
        경우를 {(사용할 수 없음!) 
            서블릿 = wrapper.allocate (); 
        } 
        이 요청에 대한 필터 체인 생성 // 애플리케이션 licationFilterChain filterChain = 
            createFilterChain (요청, 서블릿); 
        //이 요청에 대한 필터 체인 전화 
        // 참고 :이 또한 방법 서블릿의 service ()를 호출 
        문자열 JS 
        경우 (! jspFile = NULL)
         PFILE = wrapper.getJspFile (); //是否是JSP 
            sreq.setAttribute (Globals.JSP_FILE_ATTR, jspFile); 
        다른 
            sreq.removeAttribute (Globals.JSP_FILE_ATTR); 
        경우 ((서블릿 = NULL) && (filterChain = NULL)!) { 
            filterChain.doFilter (SREQ, SRES); 
        } 
        sreq.removeAttribute (Globals.JSP_FILE_ATTR); 
    }

 

 

먼저 호출이  wrapper.allocate() ,이 방법은 매우 중요하다, 그것은 통과 할 것이다  反射 (가) 해당 찾을   우리에게 반환의 예의 파일 구조를. 그런 다음 생성   에 익숙한   당신이 낯선 없어야한다? 이것은 우리가 무엇에 개발  시간의 사용   . 다음의 구현   이 호출 및 방법,   우리는이 방법을보고servletclassFilterChainj2ee web appfilterdoFilterinternalDoFilter

개인 무효 internalDoFilter (ServletRequest를 요청 ServletResponse를 응답) 
        IOException가이 {ServletException이 발생 
        존재하는 경우 다음 // 필터 전화 
        (this.iterator.hasNext ()) {경우 
            ApplicationFilterConfig filterConfig = 
              (ApplicationFilterConfig) iterator.next (); 
            필터 filter = NULL; 
            
            필터 = filterConfig.getFilter (); 
            filter.doFilter (요청, 응답이); 
            반환; 
        } 
        서블릿 인스턴스를 호출 - // 우리는 체인의 끝에 떨어졌다 
        경우 HttpServletRequest의 instanceof를 ((요청) &&  
            HttpServletResponse를 instanceof를 (응답)) {
            ,의 Servlet.service ((HttpServletRequest의) 요청을
                            (HttpServletResponse를) 반응); 
        사용한다} else { 
            의 Servlet.service (요청, 응답); 
        } 
}

 

 

마지막으로,이 방법은 본  service 지금 당신의 사용을 알고, 방법을  filter 수행하지 않으면 시간  doFilter ,  service 이유는 핸들에 의해 실행되지 않습니다.

추천

출처blog.csdn.net/anwarkanji/article/details/90528238