Jetty架构分析

来源:互联网 发布:mmap文件阅读器 mac 编辑:程序博客网 时间:2024/06/03 19:04

最新的jetty版本是jetty 9,但下面这个jetty源码阅读系列都是基于jetty8进行的,所以可能有些地方和最新的源码对不上。
jetty服务器由一个或多个connector核心组件以及一系列handler组件和一个线程池组成。结构图如下:
这里写图片描述

三个组件的职责:connector负责接收客户端连接请求,而handler组件则负责处理请求并给予响应,前两个组件需要的线程资源都直接从线程池ThreadPool中获取。
Jetty Server可以同时配置多个不同connector在不同的端口进行监听,并可以根据不同的需求配置不同的connector,比如非阻塞的NioConnector,阻塞的SocketConnector等;对于处理请求的handler组件,也可以根据需要配置不同的handler,比如需要Servlet就配置一个ServletHandler,需要Session就配置一个SessionHandler,当然如果都不需要则不配置这些handler就可以了。
Jetty提供了一个Server类来协调和控制上线核心组件进行工作,Server是应用的起始点,它负责创建并初始化Connector Handler和ThreadPool,然后调用
start方法启动它们,让它们处于待命状态。值得注意的是Server类本身也是一个Handler。

1.组件的生命周期

Jetty中的关键组件,比如Connector、ThreadPool、Handler等都有生命周期的概念,这些组件的生命周期定义都是通过实现LifeCycle接口来进行控制。当然有些组件不是直接实现的LifeCycle而是通过继承LifeCycle的子类来定义的生命周期管理。下面是描述它们关系的类图:
这里写图片描述
上面说到Server本身也是一个Handler,同时它也是启动和协调其它组件工作的类,通过LifeCyle可以控制其它组件的生命周期,可以通过start()来启动Server,通过stop()来停止Server。
LifeCycle的定义如下,可以看到比较重要的关于生命周期的方法其实就是start()和stop()。其它还有一些判断组件运行状态和添加移除事件监听器的方法。

public interface LifeCycle{        public void start()        throws Exception;    public void stop()        throws Exception;    public boolean isStarted();    public boolean isStarting();    public boolean isStopping();    public boolean isStopped();    public boolean isFailed();    public void addLifeCycleListener(LifeCycle.Listener listener);    public void removeLifeCycleListener(LifeCycle.Listener listener);    public interface Listener extends EventListener    {        public void lifeCycleStarting(LifeCycle event);        public void lifeCycleStarted(LifeCycle event);        public void lifeCycleFailure(LifeCycle event,Throwable cause);        public void lifeCycleStopping(LifeCycle event);        public void lifeCycleStopped(LifeCycle event);    }

下面重点来分析下各个组件的start()方法,以对各类型组件的启动过程有个大致印象。AbstractLifeCycle是大多组件都继承的类,通过它的源码可以看到start()方法里面调用了三个方法:

public final void start() throws Exception    {        synchronized (_lock)        {            try            {                if (_state == __STARTED || _state == __STARTING)                    return;                setStarting();                doStart();                setStarted();            }            catch (Exception e)            {                setFailed(e);                throw e;            }            catch (Error e)            {                setFailed(e);                throw e;            }        }    }

而setStarting()和setStarted()只是设置下组件的状态和将当前的事件通知给在当前组件上注册了的监听者,如下所示:

 private void setStarting()    {        if (LOG.isDebugEnabled())            LOG.debug("starting {}",this);        _state = __STARTING;        for (Listener listener : _listeners)            listener.lifeCycleStarting(this);    }

所以本质上真正的启动逻辑是在doStart()方法里,而这个方法是由各个组件自己实现的。例如对Handler来说,他们都继承了AbstractHandler,而这个Handler继承了ContainerLifeCycle,在这里定义了核心启动逻辑:

 /**     * Starts the managed lifecycle beans in the order they were added.     */    @Override    protected void doStart() throws Exception    {        // indicate that we are started, so that addBean will start other beans added.        _doStarted = true;        // start our managed and auto beans        for (Bean b : _beans)        {            if (b._bean instanceof LifeCycle)            {                LifeCycle l = (LifeCycle)b._bean;                switch(b._managed)                {                    case MANAGED:                        if (!l.isRunning())                            start(l);                        break;                    case AUTO:                        if (l.isRunning())                            unmanage(b);                        else                        {                            manage(b);                            start(l);                        }                        break;                }            }        }        super.doStart();    }

可以看到这里将handler里管理的LifeCycle组件一次进行了启动,并将他们分成了managed和auto两种类型进行处理。Server也是handler,所以调用Server的start()会启动所有在Server里注册的组件。

Connector组件的抽象父类AbstractConnector也继承了ContainerLifeCycle,所以启动的形式也是和Handler类似的;不同的是调用ContainerLifeCycle的doStart()方法之后,又再往bean list中添加bean,也就是这些bean不会交给Container的生命周期方法进行管理。

@Override    protected void doStart() throws Exception    {        _defaultConnectionFactory = getConnectionFactory(_defaultProtocol);        if(_defaultConnectionFactory==null)            throw new IllegalStateException("No protocol factory for default protocol: "+_defaultProtocol);        super.doStart();        _stopping=new CountDownLatch(_acceptors.length);        for (int i = 0; i < _acceptors.length; i++)        {            Acceptor a = new Acceptor(i);            addBean(a);            getExecutor().execute(a);        }        LOG.info("Started {}", this);    }

QueuedThreadPool没有继承ContainerLifeCycle而是直接继承的AbstractLifeCycle,所以它的doStart()方法是在它自己的内部实现的:

@Override    protected void doStart() throws Exception    {        super.doStart();        _threadsStarted.set(0);        startThreads(_minThreads);    }

这里的super.doStart()调用的是AbstractLifeCycle的doStart()方法,其实什么都没做。所以将已启动的线程数设为0之后,主要的启动逻辑就由startThreads()来实现了,这里的逻辑主要是启动_minThreads个线程并将它们加入到线程中去:

private boolean startThreads(int threadsToStart)    {        while (threadsToStart > 0 && isRunning())        {            int threads = _threadsStarted.get();            if (threads >= _maxThreads)                return false;            if (!_threadsStarted.compareAndSet(threads, threads + 1))                continue;            boolean started = false;            try            {                Thread thread = newThread(_runnable);                thread.setDaemon(isDaemon());                thread.setPriority(getThreadsPriority());                thread.setName(_name + "-" + thread.getId());                _threads.add(thread);                thread.start();                started = true;                --threadsToStart;            }            finally            {                if (!started)                    _threadsStarted.decrementAndGet();            }        }        return true;    }

2.Connector 组件

Connector组件对应的类图如下:

这里写图片描述
从类图中可以看到Connector组件的实现方式分为NIO BIO两大类型。Connector的作用是从客户端接收连接,并将应用程序的数据传输给客户端。

3.Handler 组件
首先还是看下类图,了解各个类之间的关系:
这里写图片描述
所有的 handler 组件都实现了 Handler 接口。还可以看到, Handler 是可以以链表的形式相互组合的。Server 作为服务入口,本身也是 handler ,他继承了 HandlerWrapper 接口,我们看以看到他带了一个 handler 的引用变量,我们可以在配置文件中设置注入 ServletHandler 支持 servlet, 设置注入 WebAppContext 则支持我们的 webapp 应用。