当前位置:   article > 正文

Tomcat源码笔记(四)StandardService_standardservice.connector.startfailed

standardservice.connector.startfailed

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

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

initInternal() / startInternal()

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

  1. public class StandardService extends LifecycleMBeanBase implements Service {
  2. // 父组件Server的引用
  3. private Server server = null;
  4. // 多个Connector,每种连接一个Connector http,https,向相同协议不同端口的连接等
  5. protected Connector connectors[] = new Connector[0];
  6. // 用来synchronized
  7. private final Object connectorsLock = new Object();
  8. // Service下 和Connector和Engine同级别的组件Executor,StandardThreadExecutor
  9. // ThreadPoolExecutor的封装
  10. protected final ArrayList<Executor> executors = new ArrayList<>();
  11. // 子组件Engine
  12. private Engine engine = null;
  13. protected final Mapper mapper = new Mapper();
  14. protected final MapperListener mapperListener = new MapperListener(this);
  15. @Override
  16. protected void initInternal() throws LifecycleException {
  17. // 注册当前对象MBean
  18. super.initInternal();
  19. // 初始化engine
  20. if (engine != null) {
  21. engine.init();
  22. }
  23. // 初始化Executor
  24. for (Executor executor : findExecutors()) {
  25. if (executor instanceof JmxEnabled) {
  26. ((JmxEnabled) executor).setDomain(getDomain());
  27. }
  28. executor.init();
  29. }
  30. // 初始化mapperListener,只是注册JMX
  31. mapperListener.init();
  32. // 初始化Connector
  33. synchronized (connectorsLock) {
  34. for (Connector connector : connectors) {
  35. try {
  36. connector.init();
  37. } catch (Exception e) {
  38. String message = sm.getString(
  39. "standardService.connector.initFailed", connector);
  40. log.error(message, e);
  41. if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"))
  42. throw new LifecycleException(message);
  43. }
  44. }
  45. }
  46. }
  47. protected void startInternal() throws LifecycleException {
  48. // 设置Starting状态
  49. setState(LifecycleState.STARTING);
  50. // 启动Engine
  51. if (engine != null) {
  52. synchronized (engine) {
  53. engine.start();
  54. }
  55. }
  56. // 启动executor
  57. synchronized (executors) {
  58. for (Executor executor: executors) {
  59. executor.start();
  60. }
  61. }
  62. //mapperListener启动
  63. mapperListener.start();
  64. // Connector启动
  65. synchronized (connectorsLock) {
  66. for (Connector connector: connectors) {
  67. try {
  68. // If it has already failed, don't try and start it
  69. if (connector.getState() != LifecycleState.FAILED) {
  70. connector.start();
  71. }
  72. } catch (Exception e) {
  73. log.error(sm.getString(
  74. "standardService.connector.startFailed",
  75. connector), e);
  76. }
  77. }
  78. }
  79. }
  80. }

Connector和Engine下节看

Mapper

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

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

  1. public final class Mapper {
  2. volatile MappedHost[] hosts = new MappedHost[0];
  3. }

 

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

MapperListener

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

  1. public class MapperListener extends LifecycleMBeanBase
  2. implements ContainerListener, LifecycleListener {
  3. private final Mapper mapper;
  4. private final Service service;
  5. public MapperListener(Service service) {
  6. this.service = service;
  7. this.mapper = service.getMapper();
  8. }
  9. }

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

  1. public interface ContainerListener {
  2. public void containerEvent(ContainerEvent event);
  3. }

org.apache.catalina.mapper.MapperListener#startInternal

  1. @Override
  2. public void startInternal() throws LifecycleException {
  3. // 设置启动状态
  4. setState(LifecycleState.STARTING);
  5. Engine engine = service.getContainer();
  6. if (engine == null) {
  7. return;
  8. }
  9. // <Engine name="Catalina" defaultHost="localhost">
  10. // 获取defaultHost属性, 并检查是否存在对应的<Host >标签
  11. findDefaultHost();
  12. // 将Engine及其子容器都注册这个MapperListener对象
  13. addListeners(engine);
  14. // 获取engine的所有Host配置,注册到Mapper中
  15. // 注册host又会把其下所有context注册,接着往下注册所有wrapper
  16. Container[] conHosts = engine.findChildren();
  17. for (Container conHost : conHosts) {
  18. Host host = (Host) conHost;
  19. if (!LifecycleState.NEW.equals(host.getState())) {
  20. // Registering the host will register the context and wrappers
  21. registerHost(host);
  22. }
  23. }
  24. }
  1. private void registerHost(Host host) {
  2. String[] aliases = host.findAliases();
  3. // mapper中增加host
  4. mapper.addHost(host.getName(), aliases, host);
  5. // 注册context到mapper
  6. for (Container container : host.findChildren()) {
  7. if (container.getState().isAvailable()) {
  8. registerContext((Context) container);
  9. }
  10. }
  11. }

org.apache.catalina.mapper.MapperListener#containerEvent

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

 org.apache.catalina.mapper.MapperListener#lifecycleEvent

也是根据事件更新mapper

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/741610
推荐阅读
相关标签
  

闽ICP备14008679号