decadence

個人のメモ帳

Tomcatの起動からの云々を追う

ソース読む。

PDFでフローだけ追いたい人は以下の2つ

このタイミングのコード読んでる。

github.com

  • Bootstrap: public static void main

    • catalina.homeとcatalina.baseの設定
    • daemonnew Bootstrapしてinitしたもの入れる
      • init
        • initClassLoaders
          • commonLoader, catalinaLoader, sharedLoaderの3つのClassLoaderを作成
        • Thread.currentThread().setContextClassLoader(catalinaLoader)
        • SecurityClassLoad.securityClassLoad(catalinaLoader);
        • catalinaLoaderからorg.apache.catalina.startup.CatalinaをロードしてstartupClassに入れてstartupInstanceを作成
        • startupInstanceparentClassLoadersharedLoaderをセット
        • catalinaDaemonstartupInstanceとする
          • catalinaDaemon(Catalina)が実際のサーバ
      • 引数処理 (以下のdaemonメソッドでは、常にcatalinaDaemonの同名のメソッドを呼ぶ)
        • startd
          • daemon.load, daemon.start
        • start
          • daemon.setAwait(true), daemon.load, daemon.start
        • stopd
          • daemon.stop
        • stop
          • daemon.stopServer
        • configtest
          • daemon.load
  • Catalina

    • load
      • initDirs: java.io.tmpdirの存在確認
      • initNaming
        • "org.apache.naming""java.naming.factory.url.pkgs"へ入れる
        • "java.naming.factory.initial""org.apache.naming.java.javaURLContextFactory"を入れる
      • digesterの作成
        • server.xmlに記述されたxmlJavaクラスのマッピングを行っている
        • 各々でデフォルト実装などが指定されてたりもする(デフォルト実装が無い場合にはclassNameなどで指定する必要有り)
          • Server: StandardServerがデフォルト実装で、setServerへセットする
          • Server/GlobalNamingResources: NamingResourcesImplがデフォルト実装で、setGlobalNamingResourcesへセットする
          • Server/Listener: デフォルト実装無しで、Server/ListenerLifecycleListenerを取得し、addLifecycleListenerへセットする
          • Server/Service: StandardService
          • Server/Service/Listener: デフォルト実装無し
          • Server/Service/Executor: StandardThreadExecutor
          • ...
      • 設定ファイル(server.xml, etc)を探して読み込み
      • digesterに設定ファイルをparseさせる
      • serverにcatalinaHomeとcatalinaBaseをセット
      • 標準出力と、標準エラー出力をスレッドベースなキャプチャが出来るようなSystemLogHandlerでラップ
      • server.init()(実態はLifecycle.init)
    • start
      • server.start()(実態はLifecyce.start)
    • stop
      • server.stop(), server.destroy() (実態はry)
  • LifecycleBase: Lifecycleの状態の整合性を保持・比較しつつ、各internalなメソッドを呼び出す

    • リスナーを登録しておいて、各イベント発火時に各々に通知したり
    • init
      • initInternal
    • start
      • startInternal
  • NamingResourcesImpl

    • initInternal
      • ContextResource, ContextEnvironment, ContextResourceLinkのMBeanを作成
    • ...
  • StandardServer

    • Serverのデフォルト実装
    • initInternal
      • Stringのキャッシュ機構を提供
      • MBeanFactoryを作成
      • globalNamingResources.init()
      • 保持する全てのServiceに対し、service.init()
    • startInternal
      • CONFIGURE_START_EVENTというイベントをLifeCycleに投げる
      • LifecycleState.STARTING
      • globalNamingResources.start()
      • 保持する全てのServiceに対し、service.start()
  • StandardService

    • initInternal
      • Container(= Engine, Context, Host)がある場合、そのinit
      • 保持するExecutor全てのinit
      • mapperListener.init()
      • 保持するConnector全てのinit
    • startInternal
      • LifecycleState.STARTING
      • Container(= Engine, Context, Host)がある場合、container.start()
      • 保持するExecutor全てのstart
      • mapperListener.start()
      • 保持するConnector全てのstart
  • StandardThreadExecutor

    • Executorは与えられたコマンドを新しいスレッドで実行するためのもの
    • スレッドは基本的にプールされており、利用可能なスレッドが無い時は順次キューに入れられる
    • キューが一杯になると、RejectedExecutionExceptionが投げられるまで待つ
    • tomcat-exec-*(namePrefix)というスレッドはこいつが保持するスレッド
    • maxThreads, minSpareThreads, maxIdleTimeのデフォルト値などここにあり、全てThreadPoolExecutorのコンストラクタに渡されてる
    • startInternal
      • TaskQueue(maxQueueSize)の作成
      • ThreadPoolExecutorの作成
      • setState(LifecycleState.STARTING)
    • execute
      • 保持するThreadPoolExecutorのexecuteに投げる
  • Connector: Coyote connectorの実装

    • パラメータ(default)
      • asyncTimeout(30000ms)
      • port(-1)
      • redirectPort(443)
      • scheme("http")
      • secure(false)
      • maxParameterCount(10000)
      • maxPostSize(2*1024*1024 = 2MB)
      • parseBodyMethods("POST"): カンマ区切りで指定出来る
      • protocolHandlerClassName("org.apache.coyote.http11.Http11NioProtocol")
      • adapter
      • ...
    • コンストラクタ
      • protocolHandlerに、(protocol="HTTP/1.1"の時は)Http11AprProtocolインスタンスを入れる
    • initInternal
      • adapterにCoyoteAdapterをセット
      • protocolHandler.init()
    • startInternal
      • protocolHandler.start()
    • createRequest, createResponse
      • Adapterから呼ばれて、HttpServletRequest/Responseを継承した、自身に接続されたRequestとResponseを返す
    • resume: protocolHandler.resume()
    • pause: protocolHandler.pause()
  • Http11AprProtocol: extends ... AbstractProtocol: プロトコルの実装の1つ

    • コンストラクタ
      • endpoint = new AprEndpoint()
      • Http11ConnectionHandlerがendpointに対するHandlerとなる
    • init
      • endpoint.init()
    • start
      • endpoint.start()
    • Http11ConnectionHandler
      • process: ↓ のAprEndpointから返ってきた
        • なんか色々してる
        • processor.dispatch(nextDispatch.getSocketStatus())
        • processorはAbstractHttp11ConenctionHandler.createProcessorで作ったもの
    • Http11Processor.dispatch
      • getAdapter().asyncDispatch(requst, response, status): CoyoteAdapter.asyncDispatch
  • AprEndpoint

    • ソケットをaccept/pollするスレッド、sendfile用スレッド、ワーカースレッドプールを提供するサービス
    • startInternal
      • *-exec-ってワーカ用のスレッド作る
        • Connectorに渡されたmaxThreads, minSpareThreads, maxIdleTimeとかここのThreadPoolExecutorに渡す
      • *-Pollerってpollする用のスレッド作ってstartさせる
      • sendfileを利用する際には*-Sendfileってスレッド作ってstartさせる
      • startAcceptorThreads(): Acceptorってacceptする作って、*-Acceptor-$iって名前でスレッド
      • *-AsyncTimeoutって非同期タイムアウト用のスレッドもstartさせる
    • Acceptor.run
      • 無限ループしてacceptするやつ
      • connectionsってMapにソケットをkeyにAprSocketWrapperを入れる
      • socketを取得できたら、processSocketWIthOptionsでexecutorでSocketWithOptionsProcessorを渡して実行
    • SocketWithOptionsProcessor.run
      • pollerのpollersに、socketをkeyにしたものを追加する
    • Poller.run
      • 無限ループして、pollersから取り出したsocketのkeyを用いて、connectionsからArpSocketWrapperを取得
      • 取れたら(色々チェックして)processSocket
    • processScoket
      • executor.execute(new SocketProcessor(wrapper, status))
    • SocketProcessor.run
      • handler.process(socket, status) (handlerはHttp11AprProtocol.Http11ConnectionHandlerとか)
  • CoyoteAdapter

    • asyncDispatch
    • ...

続きは次回...

references

続き

は次回だったんだけど、以下の2つみたら大体分かったし終わり - http://telecastravinsky.blog.fc2.com/blog-entry-11.html - http://tomcat.apache.org/tomcat-8.0-doc/architecture/requestProcess/request-process.png

Servletを読み込んでるのは、StandarWrapperのallocateあたり

広告を非表示にする