`
Donald_Draper
  • 浏览: 950948 次
社区版块
存档分类
最新评论

Tomcat的Engine初始化,启动过程

阅读更多
Tomcat的Server初始化及启动过程:http://donald-draper.iteye.com/blog/2327060
Realm域管理:http://www.cnblogs.com/xing901022/p/4552843.html
通过分析Server初始化及启动过程,我们可以看到关键只在Engine的init和start方法
public class StandardService extends LifecycleMBeanBase implements Service {
    private static final String info =
        "org.apache.catalina.core.StandardService/1.0";
    private String name = null;
    private static final StringManager sm =
        StringManager.getManager(Constants.Package);
    private Server server = null;
    protected Connector connectors[] = new Connector[0];
    private final Object connectorsLock = new Object();
    protected ArrayList<Executor> executors = new ArrayList<Executor>();
    protected Container container = null;
    private ClassLoader parentClassLoader = null;
    @Override
    protected void initInternal() throws LifecycleException {
        //注册Service到JMX
        super.initInternal();
	//初始化Container
        if (container != null) {
            container.init();
        }
    }
    @Override
    protected void startInternal() throws LifecycleException {
        if(log.isInfoEnabled())
            log.info(sm.getString("standardService.start.name", this.name));
	//设置Service状态
        setState(LifecycleState.STARTING);
        if (container != null) {
            synchronized (container) {
	        //启动container
                container.start();
            }
        }
    }
    //Container处理所有请求
    public void setContainer(Container container) {
        Container oldContainer = this.container;
        if ((oldContainer != null) && (oldContainer instanceof Engine))
            ((Engine) oldContainer).setService(null);
        this.container = container;
        if ((this.container != null) && (this.container instanceof Engine))
            ((Engine) this.container).setService(this);
        if (getState().isAvailable() && (this.container != null)) {
            try {
	        //启动Engine
                this.container.start();
            } 
        }
    }
}

Server中Engine的配置:
<Engine name="Catalina" defaultHost="localhost">
      <!--
      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
      -->
      <!-- Use the LockOutRealm to prevent attempts to guess user passwords
           via a brute-force attack -->
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
             resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <!-- SingleSignOn valve, share authentication between web applications
             Documentation at: /docs/config/valve.html -->
        <!--
        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
        -->
        <!-- Access log processes all example.
             Documentation at: /docs/config/valve.html
             Note: The pattern used is equivalent to using pattern="common" -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />
      </Host>
    </Engine>

下面来看StandardEngine的initInternal和startInternal方法
public class StandardEngine extends ContainerBase implements Engine {

    public StandardEngine() {
        super();
	//设置Http请求Valve
        pipeline.setBasic(new StandardEngineValve());
        /* Set the jmvRoute using the system property jvmRoute */
        try {
            setJvmRoute(System.getProperty("jvmRoute"));
        } catch(Exception ex) {
            log.warn(sm.getString("standardEngine.jvmRouteFail"));
        }
        // By default, the engine will hold the reloading thread
        backgroundProcessorDelay = 10;

    }
    //默认主机名
    private String defaultHost = null;
    /**
     * The descriptive information string for this implementation.
     */
    private static final String info = "org.apache.catalina.core.StandardEngine/1.0";
    //Engine关联的Service
    private Service service = null;
    /** Allow the base dir to be specified explicitly for
     * each engine. In time we should stop using catalina.base property -
     * otherwise we loose some flexibility.
     */
    private String baseDir = null;
    /**
     * The JVM Route ID for this Tomcat instance. All Route ID's must be unique across the cluster.
     */
    private String jvmRouteId;

    /**
     * Default access log to use for request/response pairs where we can't ID the intended host and context.
     */
    private final AtomicReference<AccessLog> defaultAccessLog =
        new AtomicReference<AccessLog>();
    //初始化
    protected void initInternal() throws LifecycleException {
        //获取角色权限
        getRealm();
        super.initInternal();
    }
     //获取角色权限
     public Realm getRealm() {
        Realm configured = super.getRealm();
        // If no set realm has been called - default to NullRealm
        // This can be overridden at engine, context and host level  
        if (configured == null) {
            configured = new NullRealm();
            this.setRealm(configured);
        }
        return configured;
    }
   //启动
    protected synchronized void startInternal() throws LifecycleException {
        
        // Log our server identification information
        if(log.isInfoEnabled())
            log.info( "Starting Servlet Engine: " + ServerInfo.getServerInfo());
        // 启动Standard container 
        super.startInternal();
    }
    //添加子容器<Host>
    public void addChild(Container child) {
        if (!(child instanceof Host))
            throw new IllegalArgumentException
                (sm.getString("standardEngine.notHost"));
        super.addChild(child);

    }
}

从上可以看出StandardEngine的initInternal和startInternal方法,实际调用的,
为其父类的initInternal和startInternal,我们来看ContainerBase
public abstract class ContainerBase extends LifecycleMBeanBase
        implements Container {

   //子容器Map
  protected HashMap<String, Container> children =
        new HashMap<String, Container>();
	 protected int backgroundProcessorDelay = -1;
    /**
     * The container event listeners for this Container. Implemented as a
     * CopyOnWriteArrayList since listeners may invoke methods to add/remove
     * themselves or other listeners and with a ReadWriteLock that would trigger
     * a deadlock.
     */
    //线程安全的容器监听器List
    protected List<ContainerListener> listeners = 
            new CopyOnWriteArrayList<ContainerListener>();
    /** The Loader implementation with which this Container is associated.*/
    protected Loader loader = null;
    /** The Logger implementation with which this Container is associated.*/
    protected Log logger = null;
    /** Associated logger name.*/
    protected String logName = null;
    /** The Manager implementation with which this Container is associated.*/
    protected Manager manager = null;
    /** The cluster with which this Container is associated.*/
    protected Cluster cluster = null;
    //容器名
    protected String name = null;
    /** The parent Container to which this Container is a child.*/
    protected Container parent = null;
    /** The parent class loader to be configured when we install a Loader.*/
    protected ClassLoader parentClassLoader = null;
    /** The Pipeline object with which this Container is associated.*/
    protected Pipeline pipeline = new StandardPipeline(this);
    /** The Realm with which this Container is associated.*/
    private volatile Realm realm = null;
    /** Lock used to control access to the Realm. */
    private final ReadWriteLock realmLock = new ReentrantReadWriteLock();
    // javax.naming.Context
    /** The resources DirContext object with which this Container is associated.*/
    protected DirContext resources = null;
    /** The string manager for this package.*/
    protected static final StringManager sm =
        StringManager.getManager(Constants.Package);

    //当添加子容器时,是否自动启动
    protected boolean startChildren = true;
  
    /**The property change support for this component.
     */
    protected PropertyChangeSupport support = new PropertyChangeSupport(this);
    //后台线程
    private Thread thread = null;
    //后台线程完成信号量
    private volatile boolean threadDone = false;
    /**
     * The access log to use for requests normally handled by this container
     * that have been handled earlier in the processing chain.
     */
    protected volatile AccessLog accessLog = null;
    private volatile boolean accessLogScanComplete = false;
    //处理Container事件线程数
    private int startStopThreads = 1;
    protected ThreadPoolExecutor startStopExecutor;
    //初始化
     protected void initInternal() throws LifecycleException {
       //LinkedBlockingQueue,线程安全的阻塞队列
        BlockingQueue<Runnable> startStopQueue =
            new LinkedBlockingQueue<Runnable>();
       //新建容器事件,线程池执行器
        startStopExecutor = new ThreadPoolExecutor(
                getStartStopThreadsInternal(),
                getStartStopThreadsInternal(), 10, TimeUnit.SECONDS,
                startStopQueue,
                new StartStopThreadFactory(getName() + "-startStop-"));
        startStopExecutor.allowCoreThreadTimeOut(true);
	//注册Engine到JMX
        super.initInternal();
    }
    //启动
    protected synchronized void startInternal() throws LifecycleException {
       //启动loader
        if ((loader != null) && (loader instanceof Lifecycle))
            ((Lifecycle) loader).start();
        logger = null;
        getLogger();
	//启动manager
        if ((manager != null) && (manager instanceof Lifecycle))
            ((Lifecycle) manager).start();
	//启动cluster
        if ((cluster != null) && (cluster instanceof Lifecycle))
            ((Lifecycle) cluster).start();
	//配置Realm
        Realm realm = getRealmInternal();
        if ((realm != null) && (realm instanceof Lifecycle))
            ((Lifecycle) realm).start();
	//加载resources
        if ((resources != null) && (resources instanceof Lifecycle))
            ((Lifecycle) resources).start();
        //获取子容器
        Container children[] = findChildren();
        List<Future<Void>> results = new ArrayList<Future<Void>>();
        for (int i = 0; i < children.length; i++) {
	    //后台线程执行器,执行子容器
            results.add(startStopExecutor.submit(new StartChild(children[i])));
        }
        boolean fail = false;
        for (Future<Void> result : results) {
            try {
                result.get();
            } catch (Exception e) {
                log.error(sm.getString("containerBase.threadedStartFailed"), e);
                fail = true;
            }

        }
        if (fail) {
            throw new LifecycleException(
                    sm.getString("containerBase.threadedStartFailed"));
        }
        // Start the Valves in our pipeline (including the basic), if any
	//启动请求处理Valves包括basic(StandardEngineValve),这个在Engine构造方法中
        if (pipeline instanceof Lifecycle)
            ((Lifecycle) pipeline).start();
        setState(LifecycleState.STARTING);
        // Start our thread
        threadStart();
    }
     protected void threadStart() {
        if (thread != null)
            return;
        if (backgroundProcessorDelay <= 0)
            return;
        threadDone = false;
        String threadName = "ContainerBackgroundProcessor[" + toString() + "]";
	//新建后台更新上线问线程
        thread = new Thread(new ContainerBackgroundProcessor(), threadName);
        thread.setDaemon(true);
        thread.start();
    }
    //子容器启动Callable
     private static class StartChild implements Callable<Void> {
        private Container child;
        public StartChild(Container child) {
            this.child = child;
        }
        @Override
        public Void call() throws LifecycleException {
	    //启动子容器
            child.start();
            return null;
        }
    }
     /**
     * Private thread class to invoke the backgroundProcess method 
     * of this container and its children after a fixed delay.
     */
    //后台更新上下文线程
    protected class ContainerBackgroundProcessor implements Runnable {

        @Override
        public void run() {
            Throwable t = null;
            String unexpectedDeathMessage = sm.getString(
                    "containerBase.backgroundProcess.unexpectedThreadDeath",
                    Thread.currentThread().getName());
            try {
                while (!threadDone) {
                    try {
                        Thread.sleep(backgroundProcessorDelay * 1000L);
                    }
                    if (!threadDone) {
		        //获取父容器
                        Container parent = (Container) getMappingObject();
			//获取当前线程ClassLoader
                        ClassLoader cl = 
                            Thread.currentThread().getContextClassLoader();
                        if (parent.getLoader() != null) {
                            cl = parent.getLoader().getClassLoader();
                        }
                        processChildren(parent, cl);
                    }
                }
            } 
        }
        protected void processChildren(Container container, ClassLoader cl) {
            try {
                if (container.getLoader() != null) {
                    Thread.currentThread().setContextClassLoader
                        (container.getLoader().getClassLoader());
                }
                container.backgroundProcess();
            } finally {
                Thread.currentThread().setContextClassLoader(cl);
            }
            Container[] children = container.findChildren();
            for (int i = 0; i < children.length; i++) {
                if (children[i].getBackgroundProcessorDelay() <= 0) {
                    processChildren(children[i], cl);
                }
            }
        }
    }
    /**
     * Execute a periodic task, such as reloading, etc. This method will be
     * invoked inside the classloading context of this container. Unexpected
     * throwables will be caught and logged.
     */
     //当上下文改变时,重新加载时,上下文,更新到Container
    @Override
    public void backgroundProcess() {
        
        if (!getState().isAvailable())
            return;

        if (cluster != null) {
            try {
                cluster.backgroundProcess();
            } 
        }
        if (loader != null) {
            try {
                loader.backgroundProcess();
            } 
        }
        if (manager != null) {
            try {
                manager.backgroundProcess();
            } 
        }
        Realm realm = getRealmInternal();
        if (realm != null) {
            try {
                realm.backgroundProcess();
            } 
        }
        Valve current = pipeline.getFirst();
        while (current != null) {
            try {
                current.backgroundProcess();
            }                
            }
            current = current.getNext();
        }
        fireLifecycleEvent(Lifecycle.PERIODIC_EVENT, null);
    }
    //启动停止,子容器线程工厂类
     private static class StartStopThreadFactory implements ThreadFactory {
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        public StartStopThreadFactory(String namePrefix) {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
            this.namePrefix = namePrefix;
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(group, r, namePrefix + threadNumber.getAndIncrement());
            thread.setDaemon(true);
            return thread;
        }
    }
    /**
     * Process the specified Request, to produce the corresponding Response,
     * by invoking the first Valve in our pipeline (if any), or the basic
     * Valve otherwise.
     */
     //处理HTTP请求
    @Override
    public void invoke(Request request, Response response)
        throws IOException, ServletException {

        pipeline.getFirst().invoke(request, response);

    }
    //添加子容器权限
     @Override
    public void addChild(Container child) {
        if (Globals.IS_SECURITY_ENABLED) {
            PrivilegedAction<Void> dp =
                new PrivilegedAddChild(child);
            AccessController.doPrivileged(dp);
        } else {
            addChildInternal(child);
        }
    }
    //添加子容器
    private void addChildInternal(Container child) {
        synchronized(children) {
            if (children.get(child.getName()) != null)
                throw new IllegalArgumentException("addChild:  Child name '" +
                                                   child.getName() +
                                                   "' is not unique");
            child.setParent(this);  // May throw IAE
            children.put(child.getName(), child);
        }

        // Start child
        // Don't do this inside sync block - start can be a slow process and
        // locking the children object can cause problems elsewhere
        try {
            if ((getState().isAvailable() ||
                    LifecycleState.STARTING_PREP.equals(getState())) &&
                    startChildren) {
		 //启动自容器
                child.start();
            }
        } 
	   //产生ADD_CHILD_EVENT事件
            fireContainerEvent(ADD_CHILD_EVENT, child);
        }
    }
    /**
     * Perform addChild with the permissions of this class.
     * addChild can be called with the XML parser on the stack,
     * this allows the XML parser to have fewer privileges than
     * Tomcat.
     */
    protected class PrivilegedAddChild
        implements PrivilegedAction<Void> {

        private Container child;

        PrivilegedAddChild(Container child) {
            this.child = child;
        }

        @Override
        public Void run() {
            addChildInternal(child);
            return null;
        }
    }
    //添加addValve
    public synchronized void addValve(Valve valve) {
        pipeline.addValve(valve);
    }
}

从分析ContainerBase,可以得出ContainerBase主要做的工作是,创建后台子容器线程
执行器,执行子容器的启动任务,启动context更新守候线程。
在ContainerBase的startInternal中有这么一句
if (pipeline instanceof Lifecycle)
            ((Lifecycle) pipeline).start();

查看StandardPipeline
public class StandardPipeline extends LifecycleBase
        implements Pipeline, Contained {
    //待子类扩展
    protected void initInternal() {
        // NOOP
    }
    //如果Valve实现了LifecycleBase,则启动Valve的startInternal方法
    protected synchronized void startInternal() throws LifecycleException {
        // Start the Valves in our pipeline (including the basic), if any
        Valve current = first;
        if (current == null) {
            current = basic;
        }
        while (current != null) {
            if (current instanceof Lifecycle)
                ((Lifecycle) current).start();
            current = current.getNext();
        }
        setState(LifecycleState.STARTING);
    }
}

在StandardEngine中有构造方法种,初始化
 public StandardEngine() {
        super();
        pipeline.setBasic(new StandardEngineValve());
        /* Set the jmvRoute using the system property jvmRoute */
        try {
            setJvmRoute(System.getProperty("jvmRoute"));
        } 
        backgroundProcessorDelay = 10;
}

而pipeline是在ContainerBase定义
/**
  * The Pipeline object with which this Container is associated.
  */
 protected Pipeline pipeline = new StandardPipeline(this);

查看StandardPipeline,处理HTTP请求的Pipeline
public class StandardPipeline extends LifecycleBase
        implements Pipeline, Contained {

    /** The basic Valve (if any) associated with this Pipeline.*/
    //处理HTTP请求的Basic Valve
    protected Valve basic = null;
    /** The Container with which this Pipeline is associated.*/
    //关联容器
    protected Container container = null;
    /** Descriptive information about this implementation.*/
    protected static final String info = "org.apache.catalina.core.StandardPipeline/1.0";
    /** The first valve associated with this Pipeline.*/
    //第一个Valve
    protected Valve first = null;
    //设置basic-Valve
    public void setBasic(Valve valve) {

        // Change components if necessary
        Valve oldBasic = this.basic;
        if (oldBasic == valve)
            return;
        // Stop the old component if necessary
        if (oldBasic != null) {
            if (getState().isAvailable() && (oldBasic instanceof Lifecycle)) {
                try {
                    ((Lifecycle) oldBasic).stop();
                } 
            }
            if (oldBasic instanceof Contained) {
                try {
                    ((Contained) oldBasic).setContainer(null);
                } 
            }
        }
        // Start the new component if necessary
        if (valve == null)
            return;
        if (valve instanceof Contained) {
            ((Contained) valve).setContainer(this.container);
        }
        if (getState().isAvailable() && valve instanceof Lifecycle) {
            try {
                ((Lifecycle) valve).start();
            } 
        }
        //更新pipeline
        Valve current = first;
        while (current != null) {
            if (current.getNext() == oldBasic) {
                current.setNext(valve);
                break;
            }
            current = current.getNext();
        }
        
        this.basic = valve;
    }
    //添加Valve
     @Override
    public void addValve(Valve valve) {
        // Validate that we can add this Valve
        if (valve instanceof Contained)
            //如果valve是Contained,则设置valve的关联容器
            ((Contained) valve).setContainer(this.container);
        // Start the new component if necessary
        if (getState().isAvailable()) {
            if (valve instanceof Lifecycle) {
                try {
		    //启动valve
                    ((Lifecycle) valve).start();
                }
            }
        }
        // Add this Valve to the set associated with this Pipeline
	//将Valve与PipeLine关联,如果first为null,则Valve关联到first
        if (first == null) {
            first = valve;
            valve.setNext(basic);
        } else {
            Valve current = first;
            while (current != null) {
                if (current.getNext() == basic) {
                    current.setNext(valve);
                    valve.setNext(basic);
                    break;
                }
                current = current.getNext();
            }
        }
        container.fireContainerEvent(Container.ADD_VALVE_EVENT, valve);
    }
    //返回first Valve
    public Valve getFirst() {
        if (first != null) {
            return first;
        }
        return basic;
    }
}

//StandardEngineValve,处理请求Valve
final class StandardEngineValve
    extends ValveBase {
    public StandardEngineValve() {
        super(true);
    }
    //类信息
    private static final String info =
        "org.apache.catalina.core.StandardEngineValve/1.0";
    private static final StringManager sm =
        StringManager.getManager(Constants.Package);
    //获取类信息
    public String getInfo() {

        return (info);

    }
    //处理HTTP请求
    public final void invoke(Request request, Response response)
        throws IOException, ServletException {

	//获取Host信息,处理请求
        Host host = request.getHost();
        if (host == null) {
            response.sendError
                (HttpServletResponse.SC_BAD_REQUEST,
                 sm.getString("standardEngine.noHost", 
                              request.getServerName()));
            return;
        }
        if (request.isAsyncSupported()) {
            request.setAsyncSupported(host.getPipeline().isAsyncSupported());
        }
        host.getPipeline().getFirst().invoke(request, response);
    }
     //事件推送
    public final void event(Request request, Response response, CometEvent event)
        throws IOException, ServletException {

        // Ask this Host to process this request
        request.getHost().getPipeline().getFirst().event(request, response, event);
    }
}

//Valve,实际上一个链表,只有后继,没有前驱
public interface Valve {

    //-------------------------------------------------------------- Properties
    /**
     * Return descriptive information about this Valve implementation.
     */
    public String getInfo();

    /**
     * Return the next Valve in the pipeline containing this Valve, if any.
     */
    public Valve getNext();
    /**
     * Set the next Valve in the pipeline containing this Valve.
     *
     * @param valve The new next valve, or <code>null</code> if none
     */
    public void setNext(Valve valve);
    //---------------------------------------------------------- Public Methods
    /**
     * Execute a periodic task, such as reloading, etc. This method will be
     * invoked inside the classloading context of this container. Unexpected
     * throwables will be caught and logged.
     */
    public void backgroundProcess();
    /**
     * Perform request processing as required by this Valve.

     *
     * An individual Valve <b>MAY</b> perform the following actions, in
     * the specified order:

     * [list]
     * <li>Examine and/or modify the properties of the specified Request and
     *     Response.
     * <li>Examine the properties of the specified Request, completely generate
     *     the corresponding Response, and return control to the caller.
     * <li>Examine the properties of the specified Request and Response, wrap
     *     either or both of these objects to supplement their functionality,
     *     and pass them on.
     * <li>If the corresponding Response was not generated (and control was not
     *     returned, call the next Valve in the pipeline (if there is one) by
     *     executing <code>getNext().invoke()</code>.
     * <li>Examine, but not modify, the properties of the resulting Response
     *     (which was created by a subsequently invoked Valve or Container).
     * [/list]
     *
     * A Valve <b>MUST NOT</b> do any of the following things:

     * [list]
     * <li>Change request properties that have already been used to direct
     *     the flow of processing control for this request (for instance,
     *     trying to change the virtual host to which a Request should be
     *     sent from a pipeline attached to a Host or Context in the
     *     standard implementation).
     * <li>Create a completed Response [b]AND[/b] pass this
     *     Request and Response on to the next Valve in the pipeline.
     * <li>Consume bytes from the input stream associated with the Request,
     *     unless it is completely generating the response, or wrapping the
     *     request before passing it on.
     * <li>Modify the HTTP headers included with the Response after the
     *     <code>getNext().invoke()</code> method has returned.
     * <li>Perform any actions on the output stream associated with the
     *     specified Response after the <code>getNext().invoke()</code> method has
     *     returned.
     * [/list]
     * @exception IOException if an input/output error occurs, or is thrown
     *  by a subsequently invoked Valve, Filter, or Servlet
     * @exception ServletException if a servlet error occurs, or is thrown
     *  by a subsequently invoked Valve, Filter, or Servlet
     */
    public void invoke(Request request, Response response)
        throws IOException, ServletException;
    //推送事件
    public void event(Request request, Response response, CometEvent event)
        throws IOException, ServletException;
    public boolean isAsyncSupported();
}

总结:
以上分析可以得出,Engine的初始化与启动实际上是委托给ContainerBase,而ContainerBase初始化与启动,主要做的工作是,创建后台子容器线程执行器,执行子容器的启动任务,启动context更新守候线程。ContainerBase拥有一个StandardPipeline,StandardPipeline是处理HTTP请求的管道,在管道内部有很多Valve( Valve, Filter, or Servlet),这些Value是一个只有后继的链,当请求进来的时候,调用invoke(Request request, Response response)处理请求。
0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics