1.连接器
Tomcat 的整体架构包含了两个核心组件连接器和容器。连接器负责对外交流,容器负责内部处理。连接器用 ProtocolHandler 接口来封装通信协议和 I/O 模型的差异,ProtocolHandler 内部又分为 EndPoint 和 Processor 模块,EndPoint 负责底层 Socket通信,Proccesor 负责应用层协议解析。连接器通过适配器 Adapter 调用容器。
2.容器
Tomcat 设计了多层容器是为了灵活性的考虑,灵活性具体体现在一个Tomcat 实例(Server)可以有多个 Service,每个 Service 通过多个连接器监听不同的端口,而一个 Service 又可以支持多个虚拟主机。一个 URL 网址可以用不同的主机名、不同的端口和不同的路径来访问特定的 Servlet 实例。
2.1.怎么体现多层容器的灵活性
这些容器具有父子关系,形成了树形结构,用到了组合模式。
Tomcat用组合模式管理容器,所有容器组件都实现了 Container 接口,因此组合模式可以使得用户对单容器对象和组合容器对象的使用具有一致性。这里单容器对象指的是最底层的 Wrapper,组合容器对象指的是上面的 Context、Host 或者 Engine;
2.2.容器层级之间通过责任链模式来进行处理数据
请求的链式调用是基于 Pipeline-Valve 责任链来完成的,这样的设计使得系统具有良好的可扩展性,如果需要扩展容器本身的功能,只需要增加相应的 Valve 即可。
3.复杂系统设计思路
分析需求,根据高内聚低耦合的原则确定子模块。
找出子模块中的变化点和不变点,用接口和抽象基类去封装不变点,在抽象基类中定义模板方法,让子类自行实现抽象方法,也就是具体子类去实现变化点。
高内聚是指相关度比较高的功能要尽可能集中,不要分散。
低耦合是指两个相关的模块要尽可能减少依赖的部分和降低依赖的程度,不要让两个模块产生强依赖。
4.Tomcat如何实现一键启停
一键式启停:LifeCycle 接口,在父组件的 init() 方法里需要创建子组件并调用子组件的 init() 方法。同样,在父组件的 start() 方法里也需要调用子组件的 start() 方法,这就是组合模式的使用,并且只要调用最顶层组件,也就是 Server 组件的 init() 和 start() 方法,整个 Tomcat 就被启动起来了。
系统扩展:各个组件 init() 和 start() 方法的具体实现是复杂多变的,我们可以自己通过添加监听器来监听父节点的变化,监听器实现自己的逻辑,这是典型的观察者模式,具体来说就是在 LifeCycle 接口里加入两个方法:添加监听器和删除监听器。
重用性:LifeCycleBase抽象基类,模板方法模式。
5.Tomcat的高层组件都负责做什么
设计这样的组件时,需要考虑两个方面:
1.合适的数据结构来保存子组件
2.根据子组件依赖关系来决定它们的启动和停止顺序,以及如何优雅的停止,防止异常情况下的资源泄漏;