tomcat的连接器和容器的调用过程

一、连接器的调用过程

NioEndPoint工作流程
源码
参考资料
https://time.geekbang.org/column/article/100307
https://juejin.cn/post/6844903626175954952

1.生产消费者模式

生产者:Acceptro开启一个线程(Springboot的内嵌tomcat)监听连接请求(只是TCP连接,不包括请求)。生成的SocketChannel,添加到队列中EventQuen中,当队列长度达到8*1024时,就不从内核态的ACCPET队列里获取 。

  • TCP三次握手建立连接的过程中,内核通常会为每一个LISTEN状态的Socket维护两个队列:SYN队列(半连接队列):这些连接已经接到客户端SYN;ACCEPT队列(全连接队列):这些连接已经接到客户端的ACK,完成了三次握手,等待被accept系统调用取走。
  • Acceptor负责从ACCEPT队列中取出连接,当Acceptor处理不过来时,连接就堆积在ACCEPT队列中,这个队列长度也可以通过参数设置。
    消费者:Poller,从队列里消费SocketChannel

2.AQS使用 LimitLatch

连接数达到8*1024,则Acceptor线程挂起。
释放连接,换起线程。

3.NIO的使用

4.线程池拓展

Tomcat 在线程总数达到最大数时,不是立即执行拒绝策略,而是再尝试向任务队列添加任务,添加失败后再执行拒绝策略
https://blog.csdn.net/mulinsen77/article/details/84583716
https://javadoop.com/post/AbstractQueuedSynchronizer

5.IO模型

I/O 模型是为了解决内存和外部设备速度差异的问题。我们平时说的阻塞或非阻塞是指应用程序在发起 I/O 操作时,是立即返回还是等待。而同步和异步,是指应用程序在与内核通信时,数据从内核空间到应用空间的拷贝,是由内核主动发起还是由应用程序来触发。

6.Acceptor的一些疑问

断点打在Acceptor的run方法的while循环内为什么不会一直跑着?
答案:会一直跑着,但代码会阻塞在接收socket的方法上,直到有新的连接进来唤醒线程。
在这里插入图片描述

二、容器的调用过程

在这里插入图片描述

  1. 容器的调用
    使用Pipeline-Value。每个容器都有一个Pipeline,只要触发这个Pipeline的第一个Value,这个容器里的pipeline里的Value都会被调用到。
    不同容器的 Pipeline 是怎么链式触发的呢,比如 Engine 中 Pipeline 需要调用下层容器 Host 中的 Pipeline。这是因为 Pipeline 中还有个 getBasic 方法。这个 BasicValve 处于 Valve 链表的末端,它是 Pipeline 中必不可少的一个 Valve,负责调用下层容器的 Pipeline 里的第一个 Valve。
    基础筏
    StandardEngineValve
    StandardHostValve
    StandardContextValve
    StandardWrapperValve
  2. 什么是Value
    Valve 表示一个处理点,比如权限认证和记录日志。Valve 完成自己的处理后,调用getNext.invoke来触发下一个 Valve 调用。
public interface Valve {
 //链表将他们串起来
 public Valve getNext();
 public void setNext(Valve valve);
 
 //处理请求
 public void invoke(Request request, Response response)
}


public interface Pipeline extends Contained {
//维护value链表
 public void addValve(Valve valve);
 public Valve getBasic();
 public void setBasic(Valve valve);
 public Valve getFirst();
}
  1. 为什么会有Wrapper
    Servlet有多个实例,Context 容器直接维护一个 Servlet 数组不就行了吗?这是因为 Servlet 不仅仅是一个类实例,它还有相关的配置信息,比如它的 URL 映射、它的初始化参数,因此设计出了一个包装器,把 Servlet 本身和它相关的数据包起来,没错,这就是面向对象的思想。

  2. 总结
    请求的链式调用是基于 Pipeline-Valve 责任链来完成的,这样的设计使得系统具有良好的可扩展性,如果需要扩展容器本身的功能,只需要增加相应的 Valve 即可。

Wrapper持有servlet实例


public synchronized Servlet loadServlet() throws ServletException {
    Servlet servlet;
  
    //1. 创建一个Servlet实例
    servlet = (Servlet) instanceManager.newInstance(servletClass);    
    
    //2.调用了Servlet的init方法,这是Servlet规范要求的
    initServlet(servlet);
    
    return servlet;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值