Jetty源码导读一:启动过程

启动过程总体流程

Server > ThreadPoolHandler > Connector

Server

启动过程,主要做了以下的事情:

  • 检查,如果 ErrorHandler 没有,则创建一个

  • 注册和启动关闭钩子

  • 启动除了 Connector 的其他所有组件 ThreadPoolHandler

  • 最后启动 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

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

RAC环境单实例启动数据库收到ORA

     在RAC环境中,如果你在没有启动节点的集群服务的情况下单实例启动数据库,将收到类似如下的报错:\oracle@rhel1u01\$sqlSQL\Plus:Release10.2.0.5.0ProductiononTueApr215:00:272013Copyright(