前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Jetty启动过程

Jetty启动过程

作者头像
斯武丶风晴
发布2019-12-20 11:35:40
1.4K0
发布2019-12-20 11:35:40
举报
文章被收录于专栏:龙首琴剑庐龙首琴剑庐

启动过程总体流程

Server > ThreadPoolHandler > Connector

Server

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

  • 检查,如果 ErrorHandler 没有,则创建一个
  • 注册和启动关闭钩子
  • 启动除了 Connector 的其他所有组件 ThreadPoolHandler
  • 最后启动 Connector
代码语言:javascript
复制
// 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

代码语言:javascript
复制
         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, 并启动
代码语言:javascript
复制
// 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 本质是一个线程。

代码语言:javascript
复制
// 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 启动了。

代码语言:javascript
复制
// 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

代码语言:javascript
复制
// 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();
    }

by 斯武丶风晴 https://my.oschina.net/langxSpirit

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 启动过程总体流程
  • Server
  • Connector
    • SelectorManager
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档