当前位置: 首页 > news >正文

Tomcat响应数据过程

        我们在用Tomcat响应数据给客户端的时候,一般会调用如下代码

OutputStreamoutputStream=resp.getOutputStream();
outputStream.write("test".getBytes());

        Tomcat在响应客户端或者接受客户端消息的时候会用到门面模式,所以响应的时候Response的类型其实是ResponseFacade(接收的时候是RequestFacade),得到的socket.getOutputStream()得到的类型是CoyoteOutputStream类型(接受端也是,Coyote是核心类)。CoyoteOutPutStream中有一个属性ob(OutputBuffer),write方法调用的就是ob.writeBytes(),底层代码如下

    private void writeBytes(byte b[], int off, int len) throws IOException {if (closed) {return;}append(b, off, len);bytesWritten += len;if (doFlush) {//每次把缓冲区的数据发送出去flushByteBuffer();}}

        OutputBuffer中有个属性是bb(ByteChunk类型),里面有一个字节数组buff(8092kb),每次往缓冲区里添加数据的时候,就是往buff中写数据。代码中可以看到必须要满足doFlush的时候才会清空缓冲区,doFlush基本上就是在Servlet代码执行完前开发手动的调用OutputStream.flush()方法就会把它设置成true。这里就需要思考,什么时候会将buff中的数据放到socket中?

        ByteChunk有一个属性out(ByteOutPutChannel),本质上就是一个管道,实现了数据流向到哪里,里面有一个realWriteBytes方法。当我们调用的时候就会把数据往下游(可以先理解为往socket发,实际是往socketbuff中发,第二层缓存)发送。

public void realWriteBytes(ByteBuffer buf) throws IOException {outputChunk.setBytes(buf,off,cnt);coyoteResponse.doWrite(buf);
}

这里面主要就是通过一个outputChunk来标记这些数据是要传输下去的,真正实现发送功能的就是coyoteResponse.dowrite。

        ByteChunk里面有append方法,来表示往buff中添加数据,当缓冲区大小满了之后,也会触发数据清空操作。还有一种情况就是上述说的,在缓冲区没满的时候,开发手动调用flush方法,也会执行数据清空下发操作。

        当我们调用outputStream.flush()方法的时候

                1.判断是否生成过响应头,有的话就不生了,没有的话说明是第一次发送,那么生成响应头。

                2.因为调用了flush方法,所以会调用ByteChunk的flushBuffer方法,将buff中的数据发出去,然后清空

                3.2中的数据其实是发送给另一个缓存(socketBuffer,但是这个缓存你是可以不用的,通过一些设置),SocketBuffer中也有一个ByteChunk,数据也是存放在这里面的,所以最后做的是将SocketBuffer中的数据发送到socket

        有一个属性useSocketBuffer,默认是false(如果要用必须你将socketBuffer设置大小超过500才会启用,这个可以自己去配置)

        我们最后调用的是coyoteResponse.doWrite方法,这里往下推调用的是outPutBuffer.doWrite方法(执行AbstractOutPutBuffer的逻辑)

                1.doWrite方法会先判断响应头是否已经发送,如果还没有,那么会先构造响应头然后发给socketBuffer

               2.发送完响应头,就会去判断你的数据到底是用Chunk还是ContentLength发送,对应着三个Filter(ContentLength->IdentityFilter,分块响应体->ChunkedFilter,不发送->VoidFilter)

        所以需要确定的是,到底是执行哪个Filter的逻辑,Tomcat的选择逻辑如下:

                Servlet中的所有代码执行完之后,就会调用response.finishResponse()->OutputBuffer.close()。close方法中会去判断响应体是否已经发送过了,如果一直没有发送过,说明缓冲区肯定是没满的,并且玩家没有执行过flush,那么第一缓冲区中的数据就是我们这次要发送的所有数据,所以缓冲区中的数据大小就是我们要的ContentLength大小,如果说在调用close之前已经发送过数据了,那么就会调用ChunkedFIlter的逻辑,比如我们自己调用flush,或者缓冲区满了,就会执行这个逻辑。

                在执行close方法的时候,会先将响应头的数据发送到socketBuffer,然后再将响应体的数据通过对应的OutputFilter发送,最后会调用OutputFilter的end方法,分块发送的时候会循环掉(因为有很多块),IdentityFilter就会一次性全部发送出去。

        上文就是Tomcat响应数据的过程

               

                

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 背单词工具(C++)
  • stm32番外-----0.96寸OLED播放电影《你的名字》
  • vue、react前端框架实现TodoList页面案例
  • HTTP模块(二)
  • “论大数据处理架构及其应用”写作框架,软考高级论文,系统架构设计师论文
  • HTML常见标签——超链接a标签
  • 10 VUE Element
  • 【概率论】-2-概率论公理(Axioms of Probability)
  • pyqt designer使用spliter
  • NumpyPandas:Pandas库(50%-100%)
  • 微信小程序配置访问服务器失败所发现的问题及解决方案
  • 接入百度文心一言API教程
  • Godot入门 05收集物品
  • Windows 端口占用 Port 端口占用 如何发现端口占用并且强杀?
  • 【七】Hadoop3.3.4基于ubuntu24的分布式集群安装
  • 【Leetcode】101. 对称二叉树
  • __proto__ 和 prototype的关系
  • 【刷算法】求1+2+3+...+n
  • 〔开发系列〕一次关于小程序开发的深度总结
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • Effective Java 笔记(一)
  • git 常用命令
  • isset在php5.6-和php7.0+的一些差异
  • js操作时间(持续更新)
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • Python 基础起步 (十) 什么叫函数?
  • scala基础语法(二)
  • Spring Boot MyBatis配置多种数据库
  • tensorflow学习笔记3——MNIST应用篇
  • TypeScript实现数据结构(一)栈,队列,链表
  • uni-app项目数字滚动
  • 理解在java “”i=i++;”所发生的事情
  • 聊聊sentinel的DegradeSlot
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • 在Docker Swarm上部署Apache Storm:第1部分
  • AI又要和人类“对打”,Deepmind宣布《星战Ⅱ》即将开始 ...
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • # 学号 2017-2018-20172309 《程序设计与数据结构》实验三报告
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • $.ajax,axios,fetch三种ajax请求的区别
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (C#)一个最简单的链表类
  • (HAL库版)freeRTOS移植STMF103
  • (附源码)c#+winform实现远程开机(广域网可用)
  • (黑马点评)二、短信登录功能实现
  • (机器学习-深度学习快速入门)第三章机器学习-第二节:机器学习模型之线性回归
  • (接口自动化)Python3操作MySQL数据库
  • (一)Neo4j下载安装以及初次使用
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • (自适应手机端)行业协会机构网站模板
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • . NET自动找可写目录
  • .NET MVC第三章、三种传值方式
  • .NET Remoting学习笔记(三)信道