<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Tomcat源碼學(xué)習(xí)第3篇 - Bootstrap的啟動(dòng)過(guò)程

          共 18168字,需瀏覽 37分鐘

           ·

          2021-03-31 20:14

          上一篇我們看了Tomcat中各個(gè)組件的init過(guò)程,初始化賦值好了,那么接下來(lái)就該輪到start了,話(huà)不多說(shuō),馬上進(jìn)入主題~

          1. Bootstrap.start()

          通過(guò)start方法我們可以看到他是通過(guò)反射調(diào)用了 Catalina.start()方法,按F7跳到這個(gè)類(lèi)里面看一下。

          public void start() throws Exception {
              if (catalinaDaemon == null) {
                  init();
              }
              // 通過(guò)反射調(diào)用 Catalina.start() 方法
              Method method = catalinaDaemon.getClass().getMethod("start", (Class [])null);
              method.invoke(catalinaDaemon, (Object [])null);
          }
          image

          2. Catalina.start()

          進(jìn)來(lái)一看,又是熟悉的套娃風(fēng)格,還得繼續(xù)往里面跳轉(zhuǎn)

          image

          3. LifecycleBase.start()

          還是這個(gè)熟悉的組件生命周期類(lèi),看到這里就仿佛看到了結(jié)局,肯定是跟initInternal這個(gè)方法一樣一層層嵌套進(jìn)去,讓我們走起~

          image

          4. StandardServer.startInternal()

          之前我們有說(shuō)過(guò)在一個(gè)Tomcat中是可以有多個(gè)service的,所以這里需要遍歷所有的service分別讓各自啟動(dòng)起來(lái)

          image

          server.xml文件中再給他配置一個(gè)<Service>標(biāo)簽即可,如圖所示:

          image

          5. StandardService.startInternal()

          開(kāi)始進(jìn)入正題了,在這個(gè)方法中我們可以看到它分別做了以下操作:

          1. 容器的啟動(dòng):engine.start()
          2. 連接器的啟動(dòng):connector.start()
          protected void startInternal() throws LifecycleException {
              if(log.isInfoEnabled())
                  log.info(sm.getString("standardService.start.name"this.name));
              setState(LifecycleState.STARTING);

              // 這里首先啟動(dòng)我們定義的容器 engine
              if (engine != null) {
                  synchronized (engine) {
                      // 啟動(dòng) engine 子容器
                      engine.start();
                  }
              }

              synchronized (executors) {
                  for (Executor executor: executors) {
                      executor.start();
                  }
              }

              mapperListener.start();

              // Start our defined Connectors second
              synchronized (connectorsLock) {
                  for (Connector connector: connectors) {
                      try {
                          // If it has already failed, don't try and start it
                          if (connector.getState() != LifecycleState.FAILED) {
                              // 啟動(dòng)連接器
                              connector.start();
                          }
                      } catch (Exception e) {
                          log.error(sm.getString(
                              "standardService.connector.startFailed",
                              connector), e);
                      }
                  }
              }
          }

          6. StandardEngine.startInternal()

          這里直接調(diào)用的ContainerBase.startInternal方法實(shí)現(xiàn)下屬組件的啟動(dòng)

          protected synchronized void startInternal() throws LifecycleException {
              // Log our server identification information
              if(log.isInfoEnabled())
                  log.info( "Starting Servlet Engine: " + ServerInfo.getServerInfo());
              // Standard container startup
              super.startInternal();
          }

          7. ContainerBase.startInternal()

          這里使用的是線(xiàn)程池的方式,如果有多個(gè)Host,那么就可以多個(gè)線(xiàn)程并行實(shí)例化Host,加快Tomcat啟動(dòng)速度

          protected synchronized void startInternal() throws LifecycleException {
              // 啟動(dòng)下屬容器
              logger = null;
              getLogger();
              Cluster cluster = getClusterInternal();
              if (cluster instanceof Lifecycle) {
                  ((Lifecycle) cluster).start();
              }
              Realm realm = getRealmInternal();
              if (realm instanceof Lifecycle) {
                  ((Lifecycle) realm).start();
              }

              // 查找并啟動(dòng)子容器,Host 在初始化階段后還是不完整的,需要繼續(xù)封裝,把容器關(guān)系維護(hù)完整
              Container children[] = findChildren();
              List<Future<Void>> results = new ArrayList<>();
              for (Container child : children) {
                  results.add(startStopExecutor.submit(new StartChild(child)));
              }

              MultiThrowable multiThrowable = null;

              for (Future<Void> result : results) {
                  try {
                      result.get();
                  } catch (Throwable e) {
                      log.error(sm.getString("containerBase.threadedStartFailed"), e);
                      if (multiThrowable == null) {
                          multiThrowable = new MultiThrowable();
                      }
                      multiThrowable.add(e);
                  }

              }
              if (multiThrowable != null) {
                  throw new LifecycleException(sm.getString("containerBase.threadedStartFailed"),
                                               multiThrowable.getThrowable());
              }

              // Start the Valves in our pipeline (including the basic), if any
              if (pipeline instanceof Lifecycle) {
                  ((Lifecycle) pipeline).start();
              }

              // 設(shè)置容器生命周期狀態(tài)
              setState(LifecycleState.STARTING);

              // Start our thread
              threadStart();
          }
          image

          8. StandardHost.startInternal()

          protected synchronized void startInternal() throws LifecycleException {

              // Set error report valve
              String errorValve = getErrorReportValveClass();
              if ((errorValve != null) && (!errorValve.equals(""))) {
                  try {
                      boolean found = false;
                      Valve[] valves = getPipeline().getValves();
                      for (Valve valve : valves) {
                          if (errorValve.equals(valve.getClass().getName())) {
                              found = true;
                              break;
                          }
                      }
                      if(!found) {
                          Valve valve =
                              (Valve) Class.forName(errorValve).getConstructor().newInstance();
                          getPipeline().addValve(valve);
                      }
                  } catch (Throwable t) {
                      ExceptionUtils.handleThrowable(t);
                      log.error(sm.getString(
                              "standardHost.invalidErrorReportValveClass",
                              errorValve), t);
                  }
              }
              super.startInternal();
          }

          Host的實(shí)例化,是通過(guò)設(shè)置生命周期狀態(tài)來(lái)進(jìn)行促發(fā)生命周期事件fireLifecycleEvent來(lái)執(zhí)行后續(xù)工作的。

          1. deployApps:處理 host下多個(gè)應(yīng)用
          2. deployDirectories:處理host下面以目錄方式部署的(results.add(),這里也是以多線(xiàn)程的方式并行執(zhí)行的)
          3. host.addChild():這時(shí)才觸發(fā)context實(shí)例核心內(nèi)容
          4. context:具體讀取web.xml封裝wrapper過(guò)程使用事件驅(qū)動(dòng)交給ContextConfig(它也是一個(gè)事件監(jiān)聽(tīng)器)
          image
          image
          image
          image
          image

          9. MapperListener.startInternal()

          public void startInternal() throws LifecycleException {

                  setState(LifecycleState.STARTING);
            // 得到 engine 容器
                  Engine engine = service.getContainer();
                  if (engine == null) {
                      return;
                  }
            // 找到默認(rèn)主機(jī)
                  findDefaultHost();
            // 為當(dāng)前容器以及子容器添加監(jiān)聽(tīng)器
                  addListeners(engine);
            // 注冊(cè)engine下所有的host
                  Container[] conHosts = engine.findChildren();
                  for (Container conHost : conHosts) {
                      Host host = (Host) conHost;
                      if (!LifecycleState.NEW.equals(host.getState())) {
                          // 注冊(cè)上下文和包裝器
                          registerHost(host);
                      }
                  }
              }

          10. Connector.startInternal()

          截至到這里,容器的注冊(cè)與啟動(dòng)已經(jīng)完成了,接下來(lái)到連接器的啟動(dòng)了

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

              setState(LifecycleState.STARTING);

              try {
                  protocolHandler.start();
              } catch (Exception e) {
                  throw new LifecycleException(
                      sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);
              }
          }

          11. AbstractProtocol.start()

          這里對(duì) EndPoint進(jìn)行初始化

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

              endpoint.start();

              // Start timeout thread
              asyncTimeout = new AsyncTimeout();
              Thread timeoutThread = new Thread(asyncTimeout, getNameInternal() + "-AsyncTimeout");
              int priority = endpoint.getThreadPriority();
              if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
                  priority = Thread.NORM_PRIORITY;
              }
              timeoutThread.setPriority(priority);
              timeoutThread.setDaemon(true);
              timeoutThread.start();
          }
          image

          12. AbstractEndpoint.start()

          public final void start() throws Exception {
              if (bindState == BindState.UNBOUND) {
                  bind();
                  bindState = BindState.BOUND_ON_START;
              }
              startInternal();
          }

          13. NioEndpoint.bind()

          public void bind() throws Exception {
              if (!getUseInheritedChannel()) {
                  // 獲取 nio 通道 channel
                  serverSock = ServerSocketChannel.open();
                  socketProperties.setProperties(serverSock.socket());
                  InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));
                  // 綁定端口,但尚未使用 accept 獲取客戶(hù)端連接
                  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.configureBlocking(true); //mimic APR behavior

              // Initialize thread count defaults for acceptor, poller
              if (acceptorThreadCount == 0) {
                  // FIXME: Doesn't seem to work that well with multiple accept threads
                  acceptorThreadCount = 1;
              }
              if (pollerThreadCount <= 0) {
                  //minimum one poller thread
                  pollerThreadCount = 1;
              }
              setStopLatch(new CountDownLatch(pollerThreadCount));

              // Initialize SSL if needed
              initialiseSsl();

              selectorPool.open();
          }

          14. NioEndpoint.startInternal()

          這里通過(guò)startAcceptorThreads啟動(dòng)Accepter線(xiàn)程,該線(xiàn)程用于接收新的Socket連接

          image
          image

          總結(jié)

          image
          - END -


          瀏覽 58
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲第一黄色 | 聚色自拍偷拍 | 国产综合在线视频 | av京东热 | 天天夜夜肏 |