Tomcat架构及源码学习笔记

一,Tomcat介绍

1,Tomcat官网:https://tomcat.apache.org

The Apache Tomcat® software is an open source implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies.

Tomcat可以称为Web容器或Servlet容器。


计算机网络模型

2,怎么让Tomcat具有Servlet容器的功能呢?
tomcat的lib包中有servlet-api.jar包,对servlet规范进行了了实现。进而封装一个个的Servlet,实现方式如下:

public interface Servlet { 
      void init(ServletConfig config) throws ServletException; 
      ServletConfig getServletConfig(); 
      void service(ServletRequest req, ServletResponse res)throws ServletException, IOException; 
      String getServletInfo(); void destroy(); 
}

自定义servlet举例:

class LoginServlet extends HttpServlet{ 
      doGet(request,response){};
      doPost(request,response){}; 
}

web.xml中的配置

 
        LoginServlet 
        com.xxx.web.servlet.LoginServlet 
 
 
        LoginServlet 
        /login 

3,Tomcat的代码原理:

class MyTomcat{ 
        List list=new ArrayList(); 
        //监听端口
        ServerSocket server=new ServerSocket(8080); 
        //接收请求
        Socket socket=server.accept(); 
        // 把请求和响应都封装在业务代码中的servlet 
        // 只要把业务代码中一个个servlets添加到tomcat中即可 
        list.add(servlets); 
}
tomcat容器

二,Tomcat源码

1,源码下载:https://archive.apache.org/dist/tomcat/tomcat-8/v8.0.11/src/
2,产品目录文件含义

  • bin:主要用来存放命令,.bat是windows下,.sh是Linux下
  • conf:用来存放tomcat的一些配置文件
  • lib:存放tomcat依赖的一些jar包
  • log:存放tomcat在运行时产生的日志文件
  • temp:存放运行时产生的临时文件
  • webapps:存放应用程序
  • work:存放tomcat运行时编译后的文件,比如JSP编译后的文件
    3,源码导入与调试
    (1) 根据上面的链接下载对应的tomcat源码
    (2) 创建pom.xml文件
 

    4.0.0 
    org.apache.tomcat 
    Tomcat8.0 
    Tomcat8.0 
    8.0
    
        Tomcat8.0
        java 
        test 
         
             
                java 
             
         
         
             
                test 
             
        
         
             
                org.apache.maven.plugins 
                maven-compiler-plugin 
                2.3 
                 
                    UTF-8 
                    1.8 
                    1.8 
                 
             
        
    
     
         
            junit 
            junit 
            4.12 
            test 
         
        
            org.easymock 
            easymock 
            3.4
        
         
            ant 
            ant 
            1.7.0 
         
         
            wsdl4j 
            wsdl4j 
            1.6.2 
         
         
            javax.xml 
            jaxrpc 
            1.1 
        
         
            org.eclipse.jdt.core.compiler 
            ecj 
            4.5.1 
         
    

(3) 将源码导入到idea中
(4) 创建application,并填写name, Main class,VM options信息:


创建application

(5) 在当前源码目录创建apache-tomcat-8.0.11文件夹,并将一些文件拷贝到该目录下,如bin、conf、lib、logs、temp、webapps、work
(6) 启动,发现报错,找不到CookieFileter,直接删除
(7) 打开浏览器访问:localhost:8080

4,web端口监听验证
org.apache.catalina.connector.Connector#initInternal()--- org.apache.coyote.ProtocolHandler#init---org.apache.coyote.AbstractProtocol#init---org.apache.tomcat.util.net.AbstractEndpoint#init
--- org.apache.tomcat.util.net.JIoEndpoint#bind
--- org.apache.tomcat.util.net.DefaultServerSocketFactory#createSocket(int)

 @Override
    public ServerSocket createSocket (int port, int backlog)
            throws IOException {
        //Java IO | Socket
        return new ServerSocket (port, backlog);
    }

5,servlets容器验证
Context标签就是代表一个web项目。http://tomcat.apache.org/tomcat-8.0-doc/architecture/overview.html

A Context represents a web application.

所以web项目的加载是从Context开始的。
org.apache.catalina.core.StandardContext#loadOnStartup

读取配置:org.apache.catalina.startup.ContextConfig#configureContext

 for (ServletDef servlet : webxml.getServlets().values()) {
            Wrapper wrapper = context.createWrapper();
            // Description is ignored
            // Display name is ignored
            // Icons are ignored
            if (servlet.getLoadOnStartup() != null) {
                wrapper.setLoadOnStartup(servlet.getLoadOnStartup().intValue());
            }
            .....
            context.addChild(wrapper);
        }

读取web.xml:
org.apache.catalina.startup.ContextConfig#createWebXml

private static final StringManager sm =
        StringManager.getManager(Constants.PACKAGE_NAME);
public class Constants {
    public static final String PACKAGE_NAME =
            Constants.class.getPackage().getName();
    public static final String WEB_XML_LOCATION = "/WEB-INF/web.xml";
}

三,Tomcat架构分析

1,tomcat核心架构图:

tomcat核心架构图

架构图----源码----server.xml 一一对应的关系:
http://tomcat.apache.org/tomcat-8.0-doc/architecture/overview.html

  • Server:代表整个容器
  • Service:是一个中间的桥梁,用于连接server和一个或多个Connector。
  • Connector:处理和客户端交互的请求。
  • Executor:代表一个线程池
  • Engine:作为pipeline,管理多个虚拟主机
  • Host:代表一个域名,可以支持多个虚拟主机。
  • Cluster:用于管理集群
  • Manager:用于管理session。

Tomcat两个核心组件:
对外:Connector
对内:Containner,源码中的关系:Container--Engine--Host--Context--Wrapper
SpringBoot内置的tomcat:
也有Connector,去掉了JIO的绑定。内置tomcat的源码和tomcat的架构基本一致。

2,Connector:

 


Connector

(1),EndPoint:监听通信端口,是对传输层的抽象,用来实现TCP/IP协议的。
对应的抽象类为AbstractEndPoint,有很多实现类,如NioEndPoint,JIoEndPoint。在其中有2个组件,一个是Acceptor,另一个是SocketProcessor。
Acceptor用来监听Socket连接请求,SocketProcessor用来处理接收到的Socket请求。

  • BIO/JIO:同步阻塞的IO,针对并发量较大的时候,效率很低,一个连接一个线程
  • NIO:同步非阻塞IO,并发量比较大的时候,比较占优势,单独一个线程,处理并发
  • Apr:与本地方法库进行交互
    Tomcat8默认使用NIO的方式,Tomcat默认使用BIO的方式。
    org.apache.catalina.connector.Connector#setProtocol
 public void setProtocol(String protocol) {
    if ("HTTP/1.1".equals(protocol)) {
         setProtocolHandlerClassName ("org.apache.coyote.http11.Http11NioProtocol");
    } else if ("AJP/1.3".equals(protocol)) {
         setProtocolHandlerClassName("org.apache.coyote.ajp.AjpNioProtocol");
    } else if (protocol != null) {
       setProtocolHandlerClassName(protocol);
    }
}

(2),Processor:Processor是用于实现HTTP协议的,也就是说Processor是针对应用层协议的抽象。Processor接受来自EndPoint的Socket,然后解析成Tomcat Request和Tomcat Response对象,最后通过Adapter提交给容器。
对应的抽象类为AbstractProcessor,有很多实现类,比如AjpProcessor、Http11Processor等。
(3),Adapter:ProtocolHandeler接口负责解析请求并生成Tomcat Request类。需要把这个Requert对象转换成ServletRequest。 Tomcat引入CoyoteAdapert,这是适配器模式的应用,连接器调用CoyoteAdapter的service方法,传入的是Tomcat Request对象,CoyoteAdapert负责将Tomcat Request转成ServletRequest,再调用容器的service方法。

优化后的Connector

3,request请求
UML图:http://tomcat.apache.org/tomcat-8.0-doc/architecture/requestProcess/request-process.png

Connector UML图

四,Tomcat启动流程

1,BootStrap:
BootStrap是Tomcat的入口类:org.apache.catalina.startup.Bootstrap#main

//bootstrap.inin()
initClassLoaders(); //初始化自定义的类加载器
Thread.currentThread().setContextClassLoader(catalinaLoader); //启动线程
 SecurityClassLoad.securityClassLoad(catalinaLoader); //安全相关
//初始化组件,并进行协同工作
daemon.load(args);
daemon.start();

2,Catalina:
解析server.xml文件
创建server组件,并且调用其init和start方法
3,Lifecycle:
用于管理各组件的生命周期,包含init、start、stop、destroy方法
LifecycleBase实现了Lifecycle,利用的是模板设计模式
4,Server:
管理Service组件,并用调用其init和start方法
5,Service:
管理连接器和Engine
启动全流程:http://tomcat.apache.org/tomcat-8.0-doc/architecture/startup.html
启动流程的UML:http://tomcat.apache.org/tomcat-8.0-doc/architecture/startup/serverStartup.pdf

你可能感兴趣的:(Tomcat架构及源码学习笔记)