Tomcat启动流程分析

发布时间:2023年12月28日

通过前面的学习,相信已经对Tomcat这个容器已经有了自己的一些认知,接下来的话我们将会一起来进行探讨Tomcat的架构设计和目录解析。

一、Tomcat目录解析

  • /bin 启动、关闭和其他脚本
  • /conf 配置文件和相关DTD。比较重要的是server.xml,这里面书写了tomcat的相关配置,可以配置最大线程数,连接器的类型等等。
  • /logs 默认的配置文件存放的地址
  • /webapps 这是网络应用程序所在的位置

二、名词解释

2.1 Server

在 Tomcat 的世界里,服务器代表了整个容器。Tomcat 提供了服务器接口的默认实现,用户很少对其进行自定义。Server元素代表整个 Catalina servlet 容器。因此,它必须是配置文件中的单个最外层元素conf/server.xml。它的属性代表了servlet容器整体的特征。

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 int getPortOffset();

    public void setPortOffset(int portOffset);

    public int getPortWithOffset();

    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 int getUtilityThreads();

    public void setUtilityThreads(int utilityThreads);

    public void addService(Service service);

    public void await();

    public Service findService(String name);

    public Service[] findServices();

    public void removeService(Service service);

    public Object getNamingToken();

    public ScheduledExecutorService getUtilityExecutor();
}

2.2 Service

服务是一种中间组件,位于服务器内部,并将一个或多个连接器绑定到一个引擎。Service 元素很少由用户自定义,它的默认实现已经很丰富了。Service元素表示一个或多个连接器组件的组合,这些连接器组件共享单个 引擎组件来处理传入请求。一个或多个Service元素可以嵌套在Server元素内。唯一可以嵌套在Service 元素内的组件是一个或多个Connector元素,后跟一个Engine元素。

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();
}

2.3 Engine

引擎 代表特定服务的请求处理管道。由于服务可能有多个连接器,引擎接收并处理来自这些连接器的所有请求,将响应返回到适当的连接器以传输给客户端。 可以实现引擎接口来提供定制引擎。
Engine元素代表与特定 Catalina服务关联的整个请求处理机制 。它接收并处理 来自一个或多个Connector 的所有请求,并将完成的响应返回给 Connector,以便最终传输回客户端。

恰好有一个Engine元素必须嵌套在Service元素内,位于与该 Service 关联的所有相应 Connector 元素之后。

2.4 Host

主机是网络名称与 Tomcat 服务器的关联。一个引擎可以包含多个主机,Host 元素还支持网络别名。
一个或多个Host元素嵌套在 Engine元素内。在 Host 元素内,您可以为与该虚拟主机关联的 Web 应用程序嵌套Context元素。与每个引擎关联的主机之一必须具有与 defaultHost该引擎的属性匹配的名称。

客户端通常使用主机名来标识他们希望连接的服务器。此主机名也包含在 HTTP 请求标头中。Tomcat 从 HTTP 标头中提取主机名并查找 具有匹配名称的主机。如果未找到匹配项,则请求将路由到默认主机。默认主机的名称不必与 DNS 名称匹配(尽管可以),因为任何 DNS 名称与 Host元素的名称不匹配的请求都将被路由到默认主机。

2.5 Connector

连接器处理与客户端的通信。Tomcat 有多个连接器。其中包括 HTTP 连接器和 AJP 连接器,前者用于处理大多数 HTTP 流量,尤其是在将 Tomcat 作为独立服务器运行时;后者用于实现将 Tomcat 连接到 Apache HTTPD 服务器等网络服务器时使用的 AJP 协议。

2.6 Context

一个上下文代表一个网络应用程序。一个主机可能包含多个上下文,每个上下文都有唯一的路径。可以通过实现 Context 接口来创建自定义 Context。

三、结构图

这里我们需要明白一点,Tomcat为了更好的划分职责,将内部架构主要分为了两个连接器和容器,连接器只负责接收网络请求,通过指定的解析器然后将请求解析,转化为容器可以识别ServletRequest,而容器和连接器通信也是通过ServletResponse来进行实现。
在这里插入图片描述

3.1 容器层次

容器里面则是负责ServerResponse的具体处理,比如通过路径映射到对应的Servlet,执行过滤器链,执行具体的业务逻辑等都是在容器这里,下面我们在一起来观察下容器的结构图。
在这里插入图片描述
通过上面的两张图我们可以了解到在Tomcat的架构中,连接器是可以有多个的,通过Service绑定到一个具体的引擎上,这其中的关系可以是多对一的关系。而引擎里面也可以有多个Host,用于区分不同的站点。就相当于一个独立的web程序,通过虚拟的域名分隔开。再者就是Context,它是一个应用的上下文,保存着一些运行时的必要数据,一个应用可以有多个上下文信息,最后便是Wrapper包装的Servlet,在这里通过路径匹配,将URL资源路径名映射到对应的Servlet实现类,这便是Tomcat的一个基本的架构。

3.2 Jetty结构

相较于Tomcat的架构来说,Jetty的架构就显得比较小巧清晰,主要是由Connector,Handler和ThreadPool组成,在这里是不是有点熟悉,其实这个有点像Netty的架构,也有点像Redis的架构。
Redis的结构是单独的开了一个连接器用来接收连接,之后判断到来的请求是读请求还是写请求,然后通过分发给对应的任务处理器,处理后再进行返回。而Netty则是通过Selector,Channel,Buffer这几个组件实现,当连接到达时进行接受,然后绑定channel,将channel注册到Selector,之后的通信都通过channel进行处理,之后的任务处理内部也维护的有自己的处理线程池。如果出现瓶颈的话会考虑拓展多个Selector等等一系列的优化手段。

四、测试环境运行

我们之前只是搭建好了我们自己的Tomcat的测试环境,但是我们还没有进行编写我们自己的Servlet,下来的话我们就要来进行测试一下我们搭建的平台是否可用,然后来进行注册我们自己的Servlet。

4.1 编码

@WebServlet("/myservlet")
public class MyServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(1111);
    }
}
文章来源:https://blog.csdn.net/weixin_49919104/article/details/135219071
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。