tomcat架构学习笔记

tomcat是一款基于servlet规范开发的应用服务器。(http服务器+servlet容器)

概述

整体架构包含两个核心组建 连接器和容器。连接器对外 处理连接,容器对内处理业务请求

每个service里面有多个连接器和一个容器

连接器使用ProtocalHandler接口封装通信协议和IO模型的差异

 

连接器

主要有三块

【Endpoint】底层socket维护,维护连接,解析tcp ip协议 把字节流送给processor

【Processor】应用层协议解析器  解析http/ajp/之类,把请求处理成TomcatRequest传给adapter

【Adapter】连接器和容器的桥梁,把tomcatRequest转换成servletRequest

ProtocalHandler包含endpoint和processor两个模块,就是把socket处理成tomcatRequest屏蔽底层网络连接和应用层协议的解析

NIO-CONNECTOR

NIO2 类似就是没有了Poller,这个遍历可读时间交给内核了,自己注册回调函数 直接用数据就好了

APR是C++写的直接用了操作系统的底层命令,多路复用用的是操作系统里面的epoll命令

  • 通过DirectByteBuffer避免了JVM堆内存和本地内存的拷贝
  • 利用操作系统的sendFile减少了用户态和内核态的切换 减少了用户内存和内核缓冲区数据的拷贝

 

tomcat支持的最大连接数

说下结论,tomcat能接受的最大连接数 maxConnections + acceptCount

acceptCount是存放建立好的长连接,tcp握手阶段 完成三次握手会把tcp丢到这个队列 长度可以简单理解成是accepCount

如果maxConnections满了 不会再去accpetCount这个队列里面取连接了

maxConnection是LimitLatch控制的【limitLatch也是基于aqs实现的,有兴趣可以看我对aqs的介绍 】

  • BIO默认最大连接是200
  • NIO默认最大连接是1W
  • APR默认连接是8192
<Executor
    name="tomcatThreadPool"
    namePrefix="deppyu-exec-"
    //处理连接的最大请求数-BIO模式下 就是最大连接数
    maxThreads="4000" 
    //初始化启动的线程数
    minSpareThreads="1000" 
    //超过这个线程数 会关闭空闲线程
    maxSpareThreads="2000" 
    maxIdleTime="60000"
/>

<Connector 
    port="80" 
    maxHttpHeaderSize="8192"  
    enableLookups="false" 
    redirectPort="8443" 
    //保持建立好的tcp连接 太小了容易 connect reset 太大了就容易长时间等待
    acceptCount="2000"  
    connectionTimeout="20000" 
    disableUploadTimeout="true" 
    //NIO一般用这个参数
    maxConnections=10000
    executor="tomcatThreadPool"
/>  

 

容器

tomcat的容器主要分四个组建,基本都是1对N的关系。

host域名/context代表一个web服务/wrapper就是servlet。这几个使用的是组合模式,都有一个父接口Container。

 

来简单看下外部请求是如何定位到具体的servlet的。

请求过来一定是先建立连接的,这个时候Connector就被确认了,connector属于一个service,一个service里面只有一个容器。

现在容器也确定了,后面按照 url context就能找到context,再根据conetxt的web.xml按照映射配置找到servlet

tomcat server.xml片段
<Server>
    <Service>
        <Connector>
        </Connector>
        <Engine>
               <host>
                   <Context></Context>
               </host>
        </Engine>
    </Service>
</Server>


web.xml片段
<!--****************************servlet映射关系配置*************************--> <servlet>  
    <servlet-name>XxServlet</servlet-name>  
    <servlet-class>com.xx.XxServlet</servlet-class>   
</servlet>   
<servlet-mapping>  
    <servlet-name>XxServlet</servlet-name>  
    <url-pattern>/xx</url-pattern>  
</servlet-mapping>  
请求流程

 

启动脚本看启动流程

启动流程

里面用的是组合模式 catalina调用server的start方法,server调用service的start。

service调用连接器和Engine的start,他们都是Container的实现,也都实现了LifeCycle接口

 

tomcat实现servlet规范

如上面的图-请求流程里面的结构。每个context里面有多个servlet,但不是直接持有servlet的。而是支持持有的wrapper

wrapper里面有servlet实例,servlet的处理范围(就是映射的url),servlet的初始化参数。

 

实例化servlet

是调用loadServlet方法,主要两步 

step1.实例化servlet 

step2.调用servlet的init方法

loadServlet的调用时机 一般类似懒加载,只有对应请求来了 才会调用。(但是wrapper对象一定会实例化的)

当然如果初始化参数loadOnstartUp=true,就会直接加载初始化

 

调用servlet的service方法

容器的pipeline模式

上面这张图很容易看出,warpper的责任链默认里面的basic【StandrandWrapperValva】节点会调用servlet 

这个warpper里面的invoke主要做了以下几件事

  1. 获取servlet实例(单例的)
  2. 组建filiterChain
  3. 调用doFilter

看下filterChain的代码,也是一种责任链的写法。传递filterChain自身,每个filter调用chain的doFilter传递。

最后一个fliter执行完了,会调用servlet.service()


public final class ApplicationFilterChain implements FilterChain {
  //Filter链中有Filter数组,这个好理解
  private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0]; 
  //Filter链中的当前的调用位置
  private int pos = 0;   
  //总共有多少了Filter
  private int n = 0;
  //每个Filter链对应一个Servlet,也就是它要调用的Servlet
  private Servlet servlet = null;
  
  public void doFilter(ServletRequest req, ServletResponse res) {
        internalDoFilter(request,response);
  }
   
  private void internalDoFilter(ServletRequest req, ServletResponse res){
    if (pos < n) {
        ApplicationFilterConfig filterConfig = filters[pos++];
        Filter filter = filterConfig.getFilter();

        filter.doFilter(request, response, this);
        return;
    }
    //如果filter结束了 调用servlet
    servlet.service(request, response);
}

tomcat

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值