启动过程总体流程
Server > ThreadPool 、Handler > Connector
Server
启动过程,主要做了以下的事情:
-
检查,如果
ErrorHandler没有,则创建一个 -
注册和启动关闭钩子
-
启动除了 Connector 的其他所有组件
ThreadPool、Handler -
最后启动
Connector// Server.java @Override protected void doStart() throws Exception { // 1.如果 ErrorHandler 没有,则创建一个 if (_errorHandler == null) _errorHandler = getBean(ErrorHandler.class); if (_errorHandler == null) setErrorHandler(new ErrorHandler()); if (_errorHandler instanceof ErrorHandler.ErrorPageMapper) LOG.warn("ErrorPageMapper not supported for Server level Error Handling"); _errorHandler.setServer(this);
1 //2.If the Server should be stopped when the jvm exits, register 2 //with the shutdown handler thread. 3 if (getStopAtShutdown()) 4 ShutdownThread.register(this); 5 6 //3. Register the Server with the handler thread for receiving 7 //remote stop commands 8 ShutdownMonitor.register(this); 9 //Start a thread waiting to receive "stop" commands. 10 ShutdownMonitor.getInstance().start(); // initialize 11 12 // 4.启动 Server, 将会启动除了 Connector 的其他所有组件 13 MultiException mex = new MultiException(); 14 try 15 { 16 super.doStart(); 17 } 18 catch (Throwable e) 19 { 20 mex.add(e); 21 } 22 23 // 5.最后启动 Connector 24 if (mex.size() == 0) 25 { 26 for (Connector connector : _connectors) 27 { 28 try 29 { 30 connector.start(); 31 } 32 catch (Throwable e) 33 { 34 mex.add(e); 35 } 36 } 37 } 38 39 if (isDumpAfterStart()) 40 dumpStdErr(); 41 42 mex.ifExceptionThrow(); 43 44 LOG.info(String.format("Started @%dms", Uptime.getUptime())); 45}
比如 embedded-jetty-jsp
1 server = new Server(); 2 3 // Define ServerConnector 4 ServerConnector connector = new ServerConnector(server); 5 connector.setPort(port); 6 server.addConnector(connector); 7 8 // Create Servlet context 9 ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS); 10 servletContextHandler.setContextPath("/"); 11 servletContextHandler.setResourceBase(baseUri.toASCIIString()); 12 13 // Since this is a ServletContextHandler we must manually configure JSP support. 14 enableEmbeddedJspSupport(servletContextHandler); 15 16 // Add Application Servlets 17 servletContextHandler.addServlet(DateServlet.class, "/date/"); 18 // Create Example of mapping jsp to path spec 19 ServletHolder holderAltMapping = new ServletHolder(); 20 holderAltMapping.setName("foo.jsp"); 21 holderAltMapping.setForcedPath("/test/foo/foo.jsp"); 22 servletContextHandler.addServlet(holderAltMapping, "/test/foo/"); 23 24 // Default Servlet (always last, always named "default") 25 ServletHolder holderDefault = new ServletHolder("default", DefaultServlet.class); 26 holderDefault.setInitParameter("resourceBase", baseUri.toASCIIString()); 27 holderDefault.setInitParameter("dirAllowed", "true"); 28 servletContextHandler.addServlet(holderDefault, "/"); 29 server.setHandler(servletContextHandler); 30 31 // Start Server 32 server.start(); 33 34 35
Connector
Connector 的实现类 ServerConnector 中,有一个_acceptors的数组,在 Connector 启动的时候, 会根据_acceptors数组的长度创建对应数量的 Acceptor,而 Acceptor 的个数可以配置。
-
启动
HttpConnectionFactory,SelectorManager等 -
根据_acceptors数组的长度创建对应数量的
Acceptor, 并启动// AbstractConnector.java @Override protected void doStart() throws Exception { ... // 启动 HttpConnectionFactory, SelectorManager 等 super.doStart(); ...
1 for (int i = 0; i < _acceptors.length; i++) 2 { 3 Acceptor a = new Acceptor(i); 4 addBean(a); 5 getExecutor().execute(a); 6 } 7}
Acceptor 本质是一个线程。
1// ServerConnector.java 2 @Override 3 public void accept(int acceptorID) throws IOException 4 { 5 ServerSocketChannel serverChannel = _acceptChannel; 6 if (serverChannel != null && serverChannel.isOpen()) 7 { 8 // 阻塞等待客户端的连接 9 SocketChannel channel = serverChannel.accept(); 10 // 连接成功 11 accepted(channel); 12 } 13 } 14 15 // 这里已经连接成功 16 private void accepted(SocketChannel channel) throws IOException 17 { 18 channel.configureBlocking(false); 19 Socket socket = channel.socket(); 20 configure(socket); 21 // _manager 是 SelectorManager 实例,里面管理了所有的 Selector 实例 22 _manager.accept(channel); 23 } 24 25 26
SelectorManager
SelectorManager 启动的时候,会把所有的 ManagedSelector 启动了。
1// SelectorManager.java 2 @Override 3 protected void doStart() throws Exception 4 { 5 _lease = ThreadPoolBudget.leaseFrom(getExecutor(), this, _selectors.length); 6 for (int i = 0; i < _selectors.length; i++) 7 { 8 ManagedSelector selector = newSelector(i); 9 _selectors[i] = selector; 10 addBean(selector); 11 } 12 super.doStart(); 13 } 14 15 16
ManagedSelector 启动的时候,会启动 SelectorProducer (使用策略 EatWhatYouKill )
1// ManagedSelector.java 2 public ManagedSelector(SelectorManager selectorManager, int id) 3 { 4 _selectorManager = selectorManager; 5 _id = id; 6 SelectorProducer producer = new SelectorProducer(); 7 Executor executor = selectorManager.getExecutor(); 8 _strategy = new EatWhatYouKill(producer, executor); 9 addBean(_strategy, true); 10 setStopTimeout(5000); 11 } 12 13 @Override 14 protected void doStart() throws Exception 15 { 16 super.doStart(); 17 _selector = _selectorManager.newSelector(); 18 19 // The producer used by the strategies will never 20 // be idle (either produces a task or blocks). 21 22 // The normal strategy obtains the produced task, schedules 23 // a new thread to produce more, runs the task and then exits. 24 _selectorManager.execute(_strategy::produce); 25 26 // Set started only if we really are started 27 Start start = new Start(); 28 submit(start); 29 start._started.await(); 30 } 31 32 33
相关
Jetty源码导读二:接受请求过程 https://my.oschina.net/langxSpirit/blog/3144657
by 斯武丶风晴 https://my.oschina.net/langxSpirit