Tomcat 是一款轻量级的web容器
window 可以 下载 win支持的exe 二进制 运行文件 或者 zip压缩文件。
区别是:win直接可以 生成 window下的服务,而 zip 需要手动运行 service.bat install
Tomcat 支持 远程debug
tomcat 支持远程debug项目,意味着可以直接debug线上环境的项目,默认端口是8000.
catalina jpda start
突然好奇Servlet 到底是Tomcat定义的规范还是 Java 定义的规范,发现是在:javax.servlet 包下的Servlet 最终被实现
Tomcat 总体设计思路
一个Java应用如果想运行起来,就必须要 有一个 main入口,而一般的Java项目实现了servlet怎么去让外界可以访问呢?自身没办法,只能通过tomcat去访问,把tomcat作为访问的入口,进入我们写的servlet中,处理完毕之后返回给客户端,这是大体思路。
只需要一个简单的 开始,停止。 没有任何业务功能。
这样处理耦合就很高,服务的启动之后,协议的连接还有业务处理都写在一起,并且对于多协议的处理不好扩展,业务代码也是,所以产生了connector和container --> 连接器和容器。
连接器负责对外的协议连接监听请求,容器作为存放项目,实现servlet规范的业务处理类。
每一个组件都拥有自己的start() 和 stop() 来负责管理自己的 资源的 开始和释放。
一个Service 包含多组 Connector 和 Container,而一个Server 又包含多个Service,每一个Service之间是独立的,(每一个Service都有一个自己的 JVM),Connector 收到请求,只会把业务处理转发给当前 Connector 同一 Service 下的 Container 处理。
Container 这个 命名 过于通用,所以在tomcat中将改为 Engine。
需要注意的是,在Tomcat 中 Engine 并不是 Servlet 容器,整体Server是一款Servlet容器,Engine 并不关心请求的链接、协议等的处理,Engine(引擎)只负责处理经过链接、协议之后的请求业务。
Container (Engine) 的设计
当Connector 接收到请求之后,需要找到合适的Engine 来处理,但是Container(Engine) 容器 需要管理多个 Web 应用,所以Engine 下面又有多个 Web应用。
可以发现,每一个组件都有一个start() 和 stop() 方法,意味着每一个组件都可以独立的启动和停止,让组件之间充分解耦,之后的组件也会有同样的方法,提高扩展性和可维护性。
然后就有一个问题,一个容器直接与 多个 web项目建立了绑定关系,我们可以设置多个请求路径为不同的项目,但是明现不符合预期的项目独立的特征。那也可以一个Server我就跑一个项目,跑多个项目实例,如果我就想一个实例跑多个呢?然后用不同的Host去建立与项目之间的关系?
而在一个Web 项目中,可以存在多个Servlet 处理类,需要一个组件概念来单独存放这些Servlet。在Tomcat 中 Servlet被命名为 Wrapper。
其实Tomcat 的架构整体可以 理解为 两类,一个是对外的连接器(Connector),一个是实际的处理请求之后返回响应的 容器/引擎 (Engine),而一个容器中,可以部署多个项目Context,但是又希望可以不同的域名访问不同的 项目组,就加了一层Host,一个Host可以存放多个Context,而一个Engine又可以存放多个Host,一个Service只有一个Engine和多个Connector,Servlet规范中,一个web项目不可能只有一个业务处理的Servlet,所以Context下面又有多个Wrapper(Tomcat中的Servlet命名),Tomcat架构是以 组件 对 组件的关系,每一个组件都可以单独的开启关闭来达到可扩展性,可维护性,个人见解,还达到了可单独控制的效果。
Tomcat 的 Container 还有一个重要的功能,就是后台处理。在很多情况下,我们的Container 需要执行一些异步处理,而且是定期执行的,如每隔30秒执行一次,Tomcat 对于 Web 应用文件变更的扫描就是通过该机制实现的。Tomcat针对后台处理,在Container 上定义了backgroundProcess() 方法,并且其基础抽象类(ContainerBase) 确保在启动组件的同时,异步启动后台处理。因此,在绝大多数情况下, 各个容器组件仅需要实现Container的backgroundProcess() 方法际可,不必考虑创建异步线程。
Lifecycle (生命周期)
在Tomcat 设计概念中,每一个组件都拥有start()、stop() 生命周期的管理特性,所以为这些组件抽象出一个 统一的管理生命周期的 接口。
有以下方法:
- Init():初始化组件
- start(): 启动组件
- stop(): 停止组件
- destroy(): 销毁组件
看不懂UML图,看源码验证。。。
确实每一个组件都 继承了 Lifecycle。
这个图,还没怎么看懂,不过感觉有用,先放上= =源码里面的。
同时,该接口支持组件状态以及状态之间的转换,支持添加时间监听器(LifecycleListener)用于监听组件的状态变化。如此,我们可以采用一致的机制来初始化、启动、停止以及销毁各个组件。如Tomcat核心组件的默认实现继承自LifecycleMBeanBase抽象类,该类不但负责组件各个状态的转换和事件的处理,还将组件自身注册为MBean,以便通过Tomcat的管理工具进行动态维护。
继承关系先展示了Engine,StandardEngine 是 Engine的实现类
每一个生命周期方法可能对应数个状态的转换,以start() 为例,分为 启动前、启动中、已启动,这三个状态自动转换 (所有标识为auto的转换路径都是在生命周期方法中自动转换的,不再需要额外的方法调用)
原来上面源码中的图。。。就是这个每一个生命周期的状态转换的流程图,auto不需要关注额外的方法调用。ps:英文不好不行,连源码注释都看不懂
2021-05-27,未完待续