SpringBoot 응용 프로그램 시작 내 장 된 Tomcat 프로 세 스 소스 분석

커 넥 터 시작 과정
커 넥 터 는 Tomcat 에서 제공 하 는 클래스 입 니 다.

//     Connector       
@Override
protected void startInternal() throws LifecycleException {

    // Validate settings before starting
    if (getPortWithOffset() < 0) {
        throw new LifecycleException(sm.getString(
                "coyoteConnector.invalidPort", Integer.valueOf(getPortWithOffset())));
    }

    setState(LifecycleState.STARTING);

    try {
    	//     
        protocolHandler.start();
    } catch (Exception e) {
        throw new LifecycleException(
                sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);
    }
}
springboot 은 기본적으로 8080 포트 에서 HTTP 서 비 스 를 제공 하기 때문에 HTTP 프로 토 콜 요청 을 처리 하 는 Http11NioProtocol 인 스 턴 스 입 니 다.NIO 방식 으로 HTTP 프로 토 콜 을 처리 합 니 다.
Connector 가 HTTP 요청 에 대한 수신 과 처 리 는 직접 완 료 된 것 이 아니 라 이 Http11NioProtocol protocol Handler 에 의뢰 한 것 입 니 다.

프로 토 콜 핸들 러 는 NioEndpoint 에 요청 처 리 를 맡 겼 다.
AbstractProtocol

@Override
public void start() throws Exception {
    if (getLog().isInfoEnabled()) {
        getLog().info(sm.getString("abstractProtocolHandler.start", getName()));
        logPortOffset();
    }

    endpoint.start();
    monitorFuture = getUtilityExecutor().scheduleWithFixedDelay(
            new Runnable() {
                @Override
                public void run() {
                    if (!isPaused()) {
                        startAsyncTimeout();
                    }
                }
            }, 0, 60, TimeUnit.SECONDS);
}
호출 체인:
  • Connector.start()
  • startInternal()
  • Http11NioProtocol protocolHandler.start();
  • Http11NioProtocol 의 start 방법 은 기본 클래스 AbstractProtocol 에서 제공 합 니 다.그것들 은 모두 tomcat 가 제공 하 는 클래스 입 니 다
  • NioEndpoint endpoint.start()
  • start 구성원 변수 endpoint,NioEndpoint 인 스 턴 스 입 니 다.Http 11 NioProtocol 류 인 스 턴 스 도 최종 처리 요청 이 아 닙 니 다.구체 적 으로 이러한 요청 의 처 리 는 NioEndpint endpoint 에 의뢰 되 었 습 니 다.

    AbstractEndpoint
    
    public final void start() throws Exception {
        if (bindState == BindState.UNBOUND) {
            bindWithCleanup();
            bindState = BindState.BOUND_ON_START;
        }
        startInternal();
    }
    tomcat 의 세 가지 모드 를 볼 수 있 습 니 다.기본적으로 NIO 모드 를 사용 합 니 다.
    
    @Override
    public void bind() throws Exception {
        initServerSocket();
    
        setStopLatch(new CountDownLatch(1));
    
        // Initialize SSL if needed
        initialiseSsl();
    
        selectorPool.open(getName());
    }
    
    protected void initServerSocket() throws Exception {
        if (!getUseInheritedChannel()) {
        	//        
            serverSock = ServerSocketChannel.open();
            socketProperties.setProperties(serverSock.socket());
            InetSocketAddress addr = new InetSocketAddress(getAddress(), getPortWithOffset());
            //        
            serverSock.socket().bind(addr,getAcceptCount());
        } else {
            // Retrieve the channel provided by the OS
            Channel ic = System.inheritedChannel();
            if (ic instanceof ServerSocketChannel) {
                serverSock = (ServerSocketChannel) ic;
            }
            if (serverSock == null) {
                throw new IllegalArgumentException(sm.getString("endpoint.init.bind.inherited"));
            }
        }
        //    serverSock      
        serverSock.configureBlocking(true); //mimic APR behavior
    }
    server Socket 은 차단 모드 를 설정 합 니 다.기본적으로 NIO 모드 를 사용 하 는데 왜 차단 모드 를 설정 합 니까?
    왜 NIO 를 사용 합 니까?BIO 의 accept 는 차단 방법 이기 때문에 write 와 read 도 모두 차단 되 어 있 습 니 다.새 연결 이 왔 을 때 만 새 스 레 드 를 만들어 서 이 연결 을 처리 할 수 있 습 니 다.이렇게 해서 가장 큰 문 제 는 대량의 연결 을 동시에 처리 할 수 없다 는 것 이다.대량의 연결 이 가 져 온 것 은 많은 스 레 드 를 만 드 는 것 이기 때문에 대량의 스 레 드 는 운영 체제 가 무 너 지기 쉽다.또한 병발 도가 높 지만 많은 스 레 드 가 공전 하고 많은 시간 을 스 레 드 의 헛걸음 과 스 레 드 전환 에 낭비 하 며 효율 도 떨어진다.
    그래서 니 오 가 탄생 했다.
    사실 연결 을 처리 하 는 작업 은 백 스테이지 스 레 드 에 두 지 않 아 도 됩 니 다.백 스테이지 스 레 드 는 연결 이 제때에 이 루어 지지 않 을 수 있 기 때문에 이 를 메 인 스 레 드 에 두 고 병발 도 를 증가 하 는 것 이 좋 습 니 다(장점 이 뚜렷 하 지 는 않 지만).
    중요 한 관심 사 는 연결 이 만들어 진 후에 클 라 이언 트 와 상호작용 을 하 는 socket 입 니 다.이 동작 은 반드시 차단 되 어야 합 니 다.이것 은 분명 합 니 다.긴 연결 을 처리 할 때,우리 가 관심 을 가 지 는 것 은 이번 연결 안의 데이터 읽 기와 쓰기 이기 때문이다.
    NioEndpoint 는 차단 모드 의 ServerSocketChannel 을 사용 하여 연결 이 들 어 오 기 를 막 고 기다 리 고 있 으 며,accept 후에 만 이 들 어 오 는 socket channel 을 비 차단 방식 으로 처리 하고 있 습 니 다(setSocketOptions 방법 참조).
    저자 가 지적 한 바 와 같이 ServerSocketChannel 을 비 차단 으로 만 들 면 읽 기 가 바 쁠 것 입 니 다.즉,하나의 스 레 드 는 들 어 오 는 연결 이 있 는 지 계속 문의 할 것 입 니 다.비 차단 모드 에서 accept()가 null 로 돌아 갈 수 있 기 때 문 입 니 다.
    APR 은 Apache Portable Runtime 을 대표 합 니 다.
    Tomcat 는 socket 을 받 았 을 때 다음 과 같은 동작 을 했 습 니 다.


    레 퍼 런 스
    https://blog.csdn.net/andy_zhang2007/article/details/78641974
    https://stackoverflow.com/questions/23168910/why-tomcats-non-blocking-connector-is-using-a-blocking-socket
    여기 서 SpringBoot 애플 리 케 이 션 이 내 장 된 Tomcat 를 시작 하 는 과정 에 대한 분석 에 관 한 글 을 소개 합 니 다.더 많은 SpringBoot 내 장 된 Tomcat 시작 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 부 탁 드 리 겠 습 니 다!

    좋은 웹페이지 즐겨찾기