1. 首页
  2. tomcat源码分析

02-二、Tomcat源码分析-tomcat框架设计

作者:黄小厮 | 出处 https://blog.csdn.net/dwade_mia/article/category/7527362

总体架构

tomcat的总体架构如下图所示(摘自http://blog.csdn.net/jiaomingliang/article/details/47393141
img_0907_01__1.png

如上图所示,tomcatServerServiceEngine、Connerctor、Host、Context组件组成,其中带有s的代表在一个tomcat实例上可以存在多个组件,比如Context(s)tomcat允许我们部署多个应用,每个应用对应一个Context。这些组件在 tomcatconf/server.xml文件中可以找到,对tomcat的调优需要改动该文件


server.xml <Service name="Catalina"> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> <Engine name="Catalina" defaultHost="localhost"> <Realm className="org.apache.catalina.realm.LockOutRealm"> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> </Realm> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> </Engine>

Server

img_0907_01__2.png

Server 组件对应org.apache.catalina.Server接口,类图如上所示。


\- Server继承至LifeCycle,LifeCycle是一个非常重要的接口,各大组件都继承了这个接口,用于管理tomcat的生命周期,比如init、start、stop、destory; 另外,它使用了观察者模式,LifeCycle是一个监听者,它会向注册的LifecycleListener观察者发出各种事件 \- Server提供了findService、getCatalina、getCatalinaHome、getCatalinaBase等接口,支持查找、遍历Service组件,这里似乎看到了和Serivce组件的些许联系

public interface Server extends Lifecycle { public NamingResourcesImpl getGlobalNamingResources(); public void setGlobalNamingResources(NamingResourcesImpl globalNamingResources); public javax.naming.Context getGlobalNamingContext(); public int getPort(); public void setPort(int port); public String getAddress(); public void setAddress(String address); public String getShutdown(); public void setShutdown(String shutdown); public ClassLoader getParentClassLoader(); public void setParentClassLoader(ClassLoader parent); public Catalina getCatalina(); public void setCatalina(Catalina catalina); public File getCatalinaBase(); public void setCatalinaBase(File catalinaBase); public File getCatalinaHome(); public void setCatalinaHome(File catalinaHome); public void await(); public Service findService(String name); public Service[] findServices(); public void removeService(Service service); public Object getNamingToken();

Service

Service 的默认实现类是 StardardService,类结构和 StardardServer 很相似,也是继承至 LifecycleMBeanBase,实现了 Service 接口

Service 接口不难发现 Service 组件的内部结构


\- 持有Engine实例 \- 持有Server实例 \- 可以管理多个Connector实例 \- 持有Executor引用

public class StandardService extends LifecycleMBeanBase implements Service { // 省略若干代码 } public interface Service extends Lifecycle { public Engine getContainer(); public void setContainer(Engine engine); public String getName(); public void setName(String name); public Server getServer(); public void setServer(Server server); public ClassLoader getParentClassLoader(); public void setParentClassLoader(ClassLoader parent); public String getDomain(); public void addConnector(Connector connector); public Connector[] findConnectors(); public void removeConnector(Connector connector); public void addExecutor(Executor ex); public Executor[] findExecutors(); public Executor getExecutor(String name); public void removeExecutor(Executor ex); Mapper getMapper();

Connector

Connectortomcat 中监听 TCP 端口的组件,server.xml 默认定义了两个 Connector,分别用于监听 httpajp 端口。对应的代码是org.apache.catalina.connector.Connector,它是一个实现类,并且实现了Lifecycle接口

http


<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000"

http对应的Connector配置如上所示,其中protocol用于指定http协议的版本,还可以支持2.0connectionTimeout定义了连接超时时间,单位是毫秒;redirectPortSSL的重定向端口,它会把请求重定向到8443这个端口

AJP

“`java


`Apache` `jserver` 协议(`AJP`)是一种二进制协议,它可以将来自 `web` 服务器的入站请求发送到位于 `web` 服务器后的应用服务器。 如果我们希望把 `Tomcat` 集成到现有的(或新的)`Apache http server`中,并且希望 `Apache` 能够处理web应用程序中包含的静态内容,或者使用 `Apache` 的SSL处理,我们便可以使用该协议。但是,在实际的项目应用中,`AJP` 协议并不常用,大多数应用场景会使用 `nginx+tomcat` 实现负载。 ## Container `org.apache.catalina.Container`接口定义了容器的api,它是一个处理用户 `servlet` 请求并返回对象给 `web` 用户的模块,它有四种不同的容器: ```java \- Engine,表示整个Catalina的servlet引擎 \- Host,表示一个拥有若干个Context的虚拟主机 \- Context,表示一个Web应用,一个context包含一个或多个wrapper \- Wrapper,表示一个独立的servlet

img_0907_01__3.png

EngineHostContextWrapper 都有一个默认的实现类 StandardXXX,均继承至 ContainerBase。此外,一个容器还包含一系列的 LodderLoggerManagerRealmResources

一个容器可以有一个或多个低层次上的子容器,并且一个 Catalina 功能部署并不一定需要全部四种容器。一个 Context 有一个或多个 wrapper,而 wrapper 作为容器层次中的最底层,不能包含子容器。从一个容器添加到另一容器中可以使用在 Container 接口中定义的 addChild() 方法义:

删除一个容器可以使用 Container 接口中定义的 removeChild() 方法:

另外容器接口支持子接口查找和获得所有子接口集合的方法 findChildfindChildren 方法:


public Container findChild(String name);

Engine

img_0907_01__4.png

Engine 表示 CatalinaServlet 引擎,如果使用了 Engine 的话,则它是 Catalina 的顶层容器,因此在StardardCataline的setParent()方法中直接抛出的异常


public interface Engine extends Container { public String getDefaultHost(); public void setDefaultHost(String defaultHost); public String getJvmRoute(); public void setJvmRoute(String jvmRouteId); public Service getService(); public void setService(Service service); } public class StandardEngine extends ContainerBase implements Engine { // other code... public void setParent(Container container) { throw new IllegalArgumentException(sm.getString("standardEngine.notParent")); }

server.xml


<Engine name="Catalina" defaultHost="localhost"> <Realm className="org.apache.catalina.realm.LockOutRealm"> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> </Realm> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host>

Host

Host 定义了一个虚拟主机,正所谓虚拟主机,当然是可以用来部署应用程序的,TomcatHost 也是如此。它在 server.xml 中定义了一个 localhostHost,应用根目录在 webapps下面,默认是支持解压重新部署的。

Context

img_0907_01__5.png

Context 代表一个独立的 web 应用,针对每个 Contexttomcat 都是使用不同的 Classloader 避免类冲突。如果我们希望使用一个自定义的目录作为部署路径的话,可以在 server.xml 中新增Context即可

代码模块简介

catalina包

Tomcat 的核心模块,包括了 HttpServletHttpSession 的实现,以及各大组件的实现,这块的代码量是最多的,也是最复杂的一部分

coyote包

这块主要用于支持各种协议,比如http1.1、http2.0、ajp等,代码量较少

tomcat包

tomcat的基础包,包括了数据库连接池、websocket 实现、tomcatejni、工具类。org.apache.tomcat.util包的代码量也不少,其中还包括了对 jdk 源码的扩展,比如线程池。

下图罗列各个模块的大致用途以及代码量
img_0907_01__6.png

参考资料

http://blog.csdn.net/jiaomingliang/article/details/47393141

写完了如果写得有什么问题,希望读者能够给小编留言,也可以点击[此处扫下面二维码关注微信公众号](https://www.ycbbs.vip/?p=28 "此处扫下面二维码关注微信公众号")

看完两件小事

如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:

  1. 关注我们的 GitHub 博客,让我们成为长期关系
  2. 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
  3. 关注公众号 「方志朋」,公众号后台回复「666」 免费领取我精心整理的进阶资源教程
  4. JS中文网,Javascriptc中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,是给开发者用的 Hacker News,技术文章由为你筛选出最优质的干货,其中包括:Android、iOS、前端、后端等方面的内容。目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。

    本文著作权归作者所有,如若转载,请注明出处

    转载请注明:文章转载自「 Java极客技术学习 」https://www.javajike.com

    标题:02-二、Tomcat源码分析-tomcat框架设计

    链接:https://www.javajike.com/article/2020.html

« 死磕Tomcat系列(2)——EndPoint源码解析
死磕Tomcat系列(1)——整体架构»

相关推荐

QR code