Tomcat 架构原理解析到架构设计借鉴

Tomcat 发展这么多年,已经比较成熟稳定。在如今『追新求快』的时代,Tomcat 作为 Java Web 开发必备的工具似乎变成了『熟悉的陌生人』,难道说如今就没有必要深入学习它了么?学习它我们又有什么收获呢?

静下心来,细细品味经典的开源作品 。提升我们的「内功」,具体来说就是学习大牛们如何设计、架构一个中间件系统,并且让这些经验为我所用。

美好的事物往往是整洁而优雅的。但这并不等于简单,而是要将复杂的系统分解成一个个小模块,并且各个模块的职责划分也要清晰合理。

与此相反的是凌乱无序,比如你看到城中村一堆互相纠缠在一起的电线,可能会感到不适。维护的代码一个类几千行、一个方法好几百行。方法之间相互耦合糅杂在一起,你可能会说 what the f*k!

学习目的 掌握 Tomcat 架构设计与原理提高内功

宏观上看

Tomcat 作为一个 「Http 服务器 + Servlet 容器」,对我们屏蔽了应用层协议和网络通信细节,给我们的是标准的 Request 和 Response 对象;对于具体的业务逻辑则作为变化点,交给我们来实现。我们使用了SpringMVC 之类的框架,可是却从来不需要考虑 TCP 连接、 Http 协议的数据处理与响应。就是因为 Tomcat 已经为我们做好了这些,我们只需要关注每个请求的具体业务逻辑。

微观上看

Tomcat 内部也隔离了变化点与不变点,使用了组件化设计,目的就是为了实现「俄罗斯套娃式」的高度定制化(组合模式),而每个组件的生命周期管理又有一些共性的东西,则被提取出来成为接口和抽象类,让具体子类实现变化点,也就是模板方法设计模式。

当今流行的微服务也是这个思路,按照功能将单体应用拆成「微服务」,拆分过程要将共性提取出来,而这些共性就会成为核心的基础服务或者通用库。「中台」思想亦是如此。

设计模式往往就是封装变化的一把利器,合理的运用设计模式能让我们的代码与系统设计变得优雅且整洁。

这就是学习优秀开源软件能获得的「内功」,从不会过时,其中的设计思想与哲学才是根本之道。从中借鉴设计经验,合理运用设计模式封装变与不变,更能从它们的源码中汲取经验,提升自己的系统设计能力。

宏观理解一个请求如何与 Spring 联系起来

在工作过程中,我们对 Java 语法已经很熟悉了,甚至「背」过一些设计模式,用过很多 Web 框架,但是很少有机会将他们用到实际项目中,让自己独立设计一个系统似乎也是根据需求一个个 Service 实现而已。脑子里似乎没有一张 Java Web 开发全景图,比如我并不知道浏览器的请求是怎么跟 Spring 中的代码联系起来的。

为了突破这个瓶颈,为何不站在巨人的肩膀上学习优秀的开源系统,看大牛们是如何思考这些问题。

学习 Tomcat 的原理,我发现 Servlet 技术是 Web 开发的原点,几乎所有的 Java Web 框架(比如 Spring)都是基于 Servlet 的封装,Spring 应用本身就是一个 Servlet(DispatchSevlet),而 Tomcat 和 Jetty 这样的 Web 容器,负责加载和运行 Servlet。如图所示:

提升自己的系统设计能力

学习 Tomcat ,我还发现用到不少 Java 高级技术,比如 Java 多线程并发编程、Socket 网络编程以及反射等。之前也只是了解这些技术,为了面试也背过一些题。但是总感觉「知道」与会用之间存在一道沟壑,通过对 Tomcat 源码学习,我学会了什么场景去使用这些技术。

还有就是系统设计能力,比如面向接口编程、组件化组合模式、骨架抽象类、一键式启停、对象池技术以及各种设计模式,比如模板方法、观察者模式、责任链模式等,之后我也开始模仿它们并把这些设计思想运用到实际的工作中。

整体架构设计

今天咱们就来一步一步分析 Tomcat 的设计思路,一方面我们可以学到 Tomcat 的总体架构,学会从宏观上怎么去设计一个复杂系统,怎么设计顶层模块,以及模块之间的关系;另一方面也为我们深入学习 Tomcat 的工作原理打下基础。

Tomcat 启动流程:startup.sh -> catalina.sh start ->java -jar org.apache.catalina.startup.Bootstrap.main()

Tomcat 实现的 2 个核心功能:

处理 Socket 连接,负责网络字节流与 Request 和 Response 对象的转化。

加载并管理 Servlet ,以及处理具体的 Request 请求。

所以 Tomcat 设计了两个核心组件连接器(Connector)和容器(Container)。连接器负责对外交流,容器负责内部 处理

Tomcat为了实现支持多种 I/O 模型和应用层协议,一个容器可能对接多个连接器,就好比一个房间有多个门。

Tomcat整体架构

Server 对应的就是一个 Tomcat 实例。

Service 默认只有一个,也就是一个 Tomcat 实例默认一个 Service。

Connector:一个 Service 可能多个 连接器,接受不同连接协议。

Container: 多个连接器对应一个容器,顶层容器其实就是 Engine。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjzfz.html