Tomcat源码笔记(四)StandardService

58 篇文章 0 订阅
8 篇文章 1 订阅

上节看了容器的初始化和启动,知道了Tomcat初始化和启动都是由Server.init(),Server.start(),层层向下依次触发各个组件的initInternal(),startInternal()方法进行初始化和启动,从本片开始,就从各组件的初始化和启动开始读源码(本文Tomcat8.5)

本文的Service实现类是StandardService,内部从配置文件中看到,内部是多个Connector和一个Engine组成,来看代码

initInternal() / startInternal()

就是调用各子组件(Engine\Connector\Mapper\Executor)的初始化和启动方法

public class StandardService extends LifecycleMBeanBase implements Service {
    // 父组件Server的引用
    private Server server = null;

    // 多个Connector,每种连接一个Connector  http,https,向相同协议不同端口的连接等
    protected Connector connectors[] = new Connector[0];
    
    // 用来synchronized
    private final Object connectorsLock = new Object();

    // Service下 和Connector和Engine同级别的组件Executor,StandardThreadExecutor
    // ThreadPoolExecutor的封装
    protected final ArrayList<Executor> executors = new ArrayList<>();

    // 子组件Engine
    private Engine engine = null;

    protected final Mapper mapper = new Mapper();

    protected final MapperListener mapperListener = new MapperListener(this);

    @Override
    protected void initInternal() throws LifecycleException {
        // 注册当前对象MBean
        super.initInternal();

        // 初始化engine
        if (engine != null) {
            engine.init();
        }

        // 初始化Executor
        for (Executor executor : findExecutors()) {
            if (executor instanceof JmxEnabled) {
                ((JmxEnabled) executor).setDomain(getDomain());
            }
            executor.init();
        }

        // 初始化mapperListener,只是注册JMX
        mapperListener.init();

        // 初始化Connector
        synchronized (connectorsLock) {
            for (Connector connector : connectors) {
                try {
                    connector.init();
                } catch (Exception e) {
                    String message = sm.getString(
                            "standardService.connector.initFailed", connector);
                    log.error(message, e);

                    if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"))
                        throw new LifecycleException(message);
                }
            }
        }
    }

   protected void startInternal() throws LifecycleException {

        // 设置Starting状态
        setState(LifecycleState.STARTING);

        // 启动Engine
        if (engine != null) {
            synchronized (engine) {
                engine.start();
            }
        }

        // 启动executor
        synchronized (executors) {
            for (Executor executor: executors) {
                executor.start();
            }
        }

        //mapperListener启动
        mapperListener.start();

        // Connector启动
        synchronized (connectorsLock) {
            for (Connector connector: connectors) {
                try {
                    // If it has already failed, don't try and start it
                    if (connector.getState() != LifecycleState.FAILED) {
                        connector.start();
                    }
                } catch (Exception e) {
                    log.error(sm.getString(
                            "standardService.connector.startFailed",
                            connector), e);
                }
            }
        }
    }
}

Connector和Engine下节看

Mapper

对请求进行路由, Mapper中有MappedHost数组,Mapper内部类有MappedHost\MappedContext\MappedWrapper 几种,和Container容器有四个子接口Engine,Host,Context,Wrapper一一对应

目的是请求来时快速查找匹配的具体的wrapper(Servlet)

public final class Mapper {
   volatile MappedHost[] hosts = new MappedHost[0];
}

 

在tomcat服务器中,有多个service,每个service有一个engine,而一个engine可以部署多个host,一个host又可以部署多个context,一个context多个wrapper,Mapper类中也符合这个层次。

MapperListener

查询当前Engine所部署的相关应用更新到mapper中,并监听Engine下容器动态更新mapper

public class MapperListener extends LifecycleMBeanBase
        implements ContainerListener, LifecycleListener {
    private final Mapper mapper;

    private final Service service;

    public MapperListener(Service service) {
        this.service = service;
        this.mapper = service.getMapper();
    }
}

首先MapperListener继承 LifecycleMBeanBase,说明对象的启动会被注册到jmx上面去,其次实现了两个Listener,LifecycleListener之前见过,监听顶层的生命周期变更事件触发lifecycleEvent()方法,ContainerListener监听容器Container的变更事件触发containerEvent()方法

public interface ContainerListener {
    public void containerEvent(ContainerEvent event);
}

org.apache.catalina.mapper.MapperListener#startInternal

   @Override
    public void startInternal() throws LifecycleException {
        // 设置启动状态
        setState(LifecycleState.STARTING);

        Engine engine = service.getContainer();
        if (engine == null) {
            return;
        }

        //  <Engine name="Catalina" defaultHost="localhost">
        //  获取defaultHost属性, 并检查是否存在对应的<Host >标签
        findDefaultHost();

        // 将Engine及其子容器都注册这个MapperListener对象
        addListeners(engine);

        // 获取engine的所有Host配置,注册到Mapper中
        // 注册host又会把其下所有context注册,接着往下注册所有wrapper
        Container[] conHosts = engine.findChildren();
        for (Container conHost : conHosts) {
            Host host = (Host) conHost;
            if (!LifecycleState.NEW.equals(host.getState())) {
                // Registering the host will register the context and wrappers
                registerHost(host);
            }
        }
    }
  private void registerHost(Host host) {

        String[] aliases = host.findAliases();

        // mapper中增加host
        mapper.addHost(host.getName(), aliases, host);

        // 注册context到mapper
        for (Container container : host.findChildren()) {
            if (container.getState().isAvailable()) {
                registerContext((Context) container);
            }
        }
    }

org.apache.catalina.mapper.MapperListener#containerEvent

监听器回调方法,根据事件注册或移除监听器,更新mapper

 org.apache.catalina.mapper.MapperListener#lifecycleEvent

也是根据事件更新mapper

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值