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