精华内容
下载资源
问答
  • tomcat9请求过程

    2019-06-10 16:52:08
    谈起tomcat请求过程,我们就要从 Connector 组件说起 一、结构和职责 1、Connector 结构: Connector 具体细化为 Connector(连接器)、Protocol(协议)、Processor(处理器) 2、职责:负责处理浏览器发送...

    谈起tomcat请求过程,我们就要从 Connector 组件说起

    一、结构和职责

    1、Connector 结构:

    Connector 具体细化为 Connector(连接器)、Protocol(协议)、Processor(处理器)

    2、职责:负责处理浏览器发送过来的tcp连接请求,创建request 和 response 对象用于和请求端交换数据,connector 会把 request 和 response 传给处理请求的 container 组件,该组件会创建一个线程来处理这个请求。

    3、通过源码我们发现,tomcat9 已经废弃了BIO,只有NIO 模式了,支持的协议有 http 和 AJP ,http 对应的处理类是 org.apache.coyote.http11.Http11NioProtocol 和 org.apache.coyote.http11.Http11AprProtocol,AJP 对应的处理类是 org.apache.coyote.ajp.AjpAprProtocol 和 org.apache.coyote.ajp.AjpNioProtocol,默认是协议是http协议,如下图所示:

    二、start 方法简介

    1、由于请求分不同的协议,这里我们讲一下常见的http协议,也就是 NIoEndPoint 处理,NIO核心的模块有 Channel、Selector 和 Buffer, 下面简单梳理一下流程,总流程图:

    下面看一下源码:

    2、由以上过程我们可以得出,最终的逻辑都是在NioEndpoint中实现的,下面分析分析 NioEndpoint

    2.1、结构,它主要有内部类 Poller、PollelEvent、NioSocketWrapper、SocketProcessor、SendfileData 组成,源码如下:

    2.2 处理流程,NioEndpoint 中 有以下四个步骤

    2.2.1、创建SocketProcessorBase处理器、PollerEvent 事件、NioChannel 缓存

    2.2.2、创建 corePoolSize 10、maximumPoolSize 200、keepAliveTime 60s、LinkedBlockingQueue、 名称前缀是 TP-exec- 的 线程池

    2.2.3、初始化最大连接数为 10000 的连接限制

    2.2.4、开启数量是 2 和 CPU 核数中的较小值的 Poller 轮询器,线程开启后一直轮询处理 PollerEvent 事件,PollerEvent 事件执行就是将 NioSocketWrapper(NioChannel 和 NioEndpoint封装对象) 注册到 selector ,NioSocketWrapper 和 SelectionKey 绑定,事件执行完之后放入缓存,这样做为了避免频繁创建事件和销毁事件而消耗资源。

    2.2.5、开启默认数量是1 的 Acceptor 接收器,开启后线程一直运行着,Socket接收连接,将NioChannel 和 NioEndpoint 封装成 NioSocketWrapper ,添加PollerEvent 事件到队列中

    3、下面重点分析一下 Poller、PollerEvent 和 Acceptor

    Poller

    wakeupCounter

    1)、统计Poller中有多少个新连接,这样当Poller进行 selector 时可以根据连接数量来决定是否需要阻塞来等待读写事件的到来

    2)、标识Poller进行 selector 时是否有连接到达,如果有就会立刻返回,否则就会阻塞等待1s

    keyCount

    1)、注册到 Poller 的 NioChannel 中,I/O状态已经ok的个数

    run方法源码:

    PollerEvent

    run方法:

    Acceptor

    Socket接收请求,run方法:

    三、处理Socket请求

    1、从 NioEndpoint 中的内部类 Poller 的 run 方法可以得知,处理Socket请求是从调用 processKey 方法开始的,具体的整个过程是 SocketProcessor(NioEndpoint内部类).doRun -> ConnectionHandler(AbstractProtocol内部类).process -> AbstractProcessorLight(实现了 Processor).process -> Http11processor(继承了 AbstractProcessor,它又继承了 AbstractProcessorLight).service -> CoyoteAdapter(实现了 Adapter).service,代码如下:

     SocketProcessorBase 的 run 方法直接调用了 SocketProcessor(NioEndpoint内部类) 中的 doRun 方法,代码如下:

    核心部分就是 getHandler().process 方法调用,getHandler 就是 ConnectionHandler ,也就是调用的 ConnectionHandler(AbstractProtocol 内部类) 的 process方法,代码如下:

    从上图看出,调用的是AbstractProcessorLight(继承了 Processor) 处理器 的 process 方法,process 方法 然后调用的是 Http11Processor 的 service方法,该方法中对 request 和 response 做了前期准备工作,最核心的就是调用CoyoteAdapter 的 service 方法处理 request 请求,代码如下:

    经过上述的层层过程,在CoyoteAdapter(实现了 Adapter)的service方法中终于见到了我们熟悉的 HttpServletRequest 和 HttpServletResponse,postParseRequest 方法设置了 request 的一些特殊参数,比如 代理端口、请求类型(GET, HEAD, POST, PUT, DELETE, OPTIONS)、URL Decoding、编码设置、SessionId、版本(version)、重定向URL等等,代码如下:

    接下来的重中之重就是理解整个责任链对请求的处理,也就是connector.getService().getContainer().getPipeline().getFirst().invoke(request, response) 这个方法的调用

    四、Host、Context 和 Wrapper 的映射

    CoyoteAdapter 把请求交给 Container 之前,会决定具体使用哪个 Host,哪个Context 和 哪个Wrapper,这个过程是怎样的呢?代码入口是CoyoteAdapter  service 方法中的postParseRequest(req, request, res, response) 调用,下面我们来分析一下:

    1、根据 host 从 hosts 列表中获取需要使用的 Host

    2、根据请求URL获取需要使用的 Context

    3、根据请求URL获取需要使用的 Wrapper

    上述数据来源都是从 Mapper 的 hosts 中获取的,那么这个对象的数据从哪里来的呢,下面看一下:

    上述分析得知:Mapperhost列表是在 MapperListener 启动时候注册过来的,MapperListener 还起到监听器的作用,容器的变化都会引起 MapperListener 处理,刷新所有的Host、Context 和 Wrapper。

    五、Pipeline(管道) & Valve(阀)

    我们知道 Engine、Host、Context 和 Wrapper 四个 Container,采用了责任链模式,每一个 Container 都定义了一个 Pipeline(StandardPipeline),每一个 Pipeline 又定义了多个 Valve,比如:first、basic, 而 Valve 包含 nextValve,Pipeline 就像是控制逻辑总线一样控制着执行顺序,而Valve 就是具体的执行任务者,每到一个 Pipeline就会执行其挂着的多个 Valve,多个Valve 按照first 、 nextValve 和 basic 的顺序进行。具体总的执行过程如下:

    StandardEgineValveStandardEngine 中唯一(basic)的阀门,主要用于从request 中选择其host映射的StandardHost容器

    AccessLogValveStandardHost 中第一个(first)阀门,主要用于Pipeline执行结束后记录日志信息

    ErrorReportValveStandardHost 中第二个(next)阀门,主要用于获取request中的错误信息,并将错误信息封装到response中返回给用户展示

    StandardHostValveStandardHost 中最后(basic)一个阀门,主要用于从request 中选择其context映射的 StandardHost 容器 和获取 request 中的 Session

    AuthenticatorValveStandContext 中第一个(first)阀门,主要用于用户权限的验证以及对response 设置header部分属性

    StandardContextValveStandContext 中最后一个(basic)阀门,主要用于从request 中选择其 wrapper 映射的 StandardWrapper 容器以及控制禁止直接对  /META-INF/ 和 /WEB-INF/ 目录下资源的直接访问

    StandardWrapperValveStandardWrapper 中唯一(basic)的阀门,主要用于调用StandardWrapper 的 loadServlet 方法获取 Servlet 实例、调用 ApplicationFilterFactory的createFilterChain 方法创建 request 过滤器链、记录请求次数、请求时间、请求最大时间、最小时间等

    AppliactionFilterChain doFilter 方法中执行了过滤器链中每一个过滤器的职责,过滤器执行后就是调用请求 servlet 的 service 方法,也就是请求url最终要执行的逻辑,代码如下:

    扩展:从上述代码可以看出,如果要实现自定义的过滤器,只需要实现 Filter,实现相应的方法即可,自定义过滤器中的doFilter方法需要调用 AppliactionFilterChain 的 doFilter方法,这样子才能让所有的过滤器执行,示例如下:

    servlet.service 方法就是调用具体的 Servlet 的 service 方法处理请求,tomcat 默认的 Servlet 只有 DefaultServlet(处理静态资源,比如html、图片等) 和 JspServlet,其对应的路径分别为(conf/web.xml 文件中定义了):

    从上述图可知,不同的请求URl对应不同的Servlet请求处理,其中最常用的就是 JspServlet,而DefaultServlet 只是处理一些静态资源,处理url 请求,代码如下:

    这里扩展一下:Spring 中处理请求的 Servlet 是 DispatcherServlet (继承了HttpServlet),结构和代码如下:

    请求返回:最终通过 CoyoteAdapter 中的 service 方法调用 response.finishResponse ,最后调用 NioSocketWrapper(NioEndpoint内部类) 中的 doWrite 方法写 response 返回结果

    六、tomcat热部署(backgroundProcess )

    tomcat 的热部署是通过 $CATALINA_HOME/conf/context.xml 配置文件中的属性控制的,即 reloadable="true"开启后tomcat所有应用都会支持热部署了,默认是reloadable="false",具体实现的方法是 backgroundProcess ,如下图:

    如果是指定某一个应用需要热部署,就需要在 conf/server.xml 中context 中配置 <Context path="" docBase="/home/myproject/webapps/myproject" reloadable="true"></Context>,如下图:

    1、backgroundProcess(后台线程)

    backgroundProcess 方法中实现了热部署的功能,到底是怎么实现的呢,下面我们来具体看看:

    1)、StandardEngine 实例的时候,设置了 backgroundProcessorDelay = 10(周期间隔10s),大于0才会开启后台线程,后台线程可以做很多事情,比如热部署、资源重加载等,代码如下:

    2)、StandardEngine 容器启动的时候会调用 ContainerBase 的 startInternal 方法,该方法通过backgroundProcessorDelay 参数判断是否开启后台线程,代码如下:

    3)、通过 ContainerBackgroundProcessorMonitor(ContainerBase内部类)-> ContainerBackgroundProcessor(ContainerBase内部类)来开启后台线程,代码:

    4)、调用StandardContext 的 backgroundProcess 方法,代码:

    5)、调用 WebappLoader 的 backgroundProcess 方法,代码:

    6)、StandardContext 的 reload 方法实现了重新加载的逻辑,步骤就是 setPaused(true) -> stop -> start ->   setPaused(false),代码如下:

    总结:

    tomcat处理请求过程大致分为以下八个步骤(这里以http协议为例):

    1、启动Server,Server启动 Service,Service启动 Connector,Connector连接器初始化 Socket连接(在NioEndpoint实现),绑定 ip(localhost) 和 port(8080)并监听 8080 端口

    2、Connector 接收到这个请求,调用 ProtocolHandler 完成请求协议解析,然后交给 SocketProcessor(NioEndpoint 的内部类) 解析请求 header(Http11Processor实现),接着将请求转交给 CoyoteAdapter 处理

    3、CoyoteAdapter  解析请求行和请求体,并根据请求URL 匹配 MapperListener 中注册的 hosts 的 Host,继而匹配 Context 和 Wrapper,将解析信息封装到request 和 response中,将请求交给 Container 处理

    4、Container 容器从 StandardEngine 开始,使用责任链模式,按照 StandardEngineValve -> StandardHostValve -> StandardContextValve -> StandardWrapperValve 的顺序执行,最终是 StandardWrapperValve 处理 request 请求

    5、StandardWrapperValve 依据请求获取到 Host、Context 和 Wrapper ,从 Wrapper 中拿到需要处理的 Servlet,然后创建了 ApplicationFilterChain(过滤器),对请求做些特殊处理等

    6、ApplicationFilterChain 中调用 Servlet 的 service 方法对请求做最终的处理,处理后

    CoyoteAdapter  对 request (finishRequest)和 response(finishResponse) 做最终处理

    7、Container 容器将 response 交给 Connnector,Connector 将请求结果返回给浏览器

    8、浏览器解析 response报文,展示内容给用户

    至此,tomcat整个请求的过程我们就讲完了。。。。。

    展开全文
  • tomcat统计QPS

    千次阅读 2019-09-28 20:34:57
    利用tomcat的access log # 设定log的目录,默认: logs server.tomcat.accesslog.directory 是否开启access log,默认:...假设访问日志文件名字为access.log,请求方式GET,请求接口/hello cat access.log |grep 'GET ...

    利用tomcat的access log

    # 设定log的目录,默认: logs
    server.tomcat.accesslog.directory
    是否开启access log,默认: false
    server.tomcat.accesslog.enabled
    
    

    假设访问日志文件名字为access.log,请求方式GET,请求接口/hello
    cat access.log |grep 'GET /hello '|cut -d ' ' -f4|uniq -c|sort -n -r

    输出:

    2 [27/Dec/2018:20:40:44
    1 [27/Dec/2018:20:47:58
    1 [27/Dec/2018:20:47:42
    1 [27/Dec/2018:20:41:57
    
    • grep ‘GET /hello’ : 将文件内容按照GET /hello 进行过滤
    • cut -d ’ ’ -f4 : 过滤出来的内容按照空格进行分割,取第四列内容
    • uniq -c : 每列旁边显示该行重复出现的次数
    • sort -n -r : 依照数值的大小排序
    展开全文
  • 二、Tomcat读取请求体的两种方式1、使用Content-Length来确定请求的结束位置2、使用Transfer-Encoding来确定请求结束的位置 一、Tomcat是如何从TCP连接中获取数据的? 主要是通过输入流,从socket的缓冲区拿到对应...

    笔者昨晚上了一节关于Tomcat读取数据的底层运行细节的课,其实反反复复的都是对数据的多读或者少读做处理,但是就是这样的一节课也上了两个多小时。。。不过中途有一点点细节还是值得记录下的。


    一、Tomcat是如何从TCP连接中获取数据的?

    主要是通过输入流,从socket的缓冲区拿到对应请求的输入流,然后将它转化为字节数组,再根据Http协议定下的格式来甄别出想要的数据(主要就是请求行、请求头)。

    有个细节需要注意一下:
    tomcat读数据的时候只会读取相关数据在字节数组中的下标开始位置和结束位置,并不会一步到位的将字节转化成对应的字符串,这样可以减少内存的消耗品

    二、Tomcat读取请求体的两种方式

    读取请求体的方式其实就是确认一个请求结束位置的方法,这种方法有两种:

    1、使用Content-Length来确定请求的结束位置

    一般来说这个方式是用在请求头部的,tomcat在读取请求体的时候会先通过设置在请求头部的这个字段来确定请求体的长度,然后在读取请求体的时候读取出对应长度的请求体数据,然后将之后多出来的数据当成下一个请求的请求行(Content-Length在请求方法为GET的时候不能使用,原因是GET方法没有请求体)。

    吐槽一句,昨晚那个讲师就是在请求体这里围绕多读数据和少读数据反复展开解读源码,讲了一晚上。还有就是笔者发现个攻击Tomcat的方式,如果将Content-Length长度足够长,而当前请求的请求体加上下一个请求的所有http数据才能达到这个长度,那么下一个请求是不是会被完全忽略掉,因为下一个请求的数据已经完全被上一个请求体读取掉了。

    2、使用Transfer-Encoding来确定请求结束的位置

    对于某些请求体长度不好判断的请求来说,使用Content-Length可能会增加内存的开销,因为需要给出一个足够大的内存去统计大小。而此时Transfer-Encoding就可以派上用场了,它使用的分块上传的方式,将一整块数据分成许多分然后分块上传,然后以 0/r/n /r/n结尾。具体的请求体格式如下:

    5\r\n
    人间烟火气\r\n
    
    5\r\n
    最抚凡人心\r\n
    
    0\r\n
    \r\n
    

    注意:上述两种方式不仅仅是请求头用来确定结束位置的标志,响应头也可以用这两种方式来确定响应的结束位置,不过Content-Length一般用于请求头,而Transfer-Encoding一般用于响应头(因为无法知道服务端能否解析这个请求头,但是浏览器能解析这个响应头)

    再拓展一下:
    tomcat只会处理表单的content-type为application/x-www.-form-urlencoded和multipart/form-data的参数。springmvc之所以能接受到content-type=application/json类型的数据,是因为它本身实现了对json数据的读取工作,也就是从输入流中将数据取出来然后封装成服务端想要的json数据格式。

    展开全文
  • tomcat访问日志 ip 请求次数

    千次阅读 2018-08-03 16:36:22
      cut -d ' ' -f 1 access.log | sort | uniq -c | sort -nr | head -n 5     [devuser@33]$ cut -d ' ' -f 1 localhost_access_log_keystore_8085.2018-07-18.txt | sort | uniq -c | sort -nr  ...

     

     

    cut -d ' ' -f 1 access.log | sort | uniq -c | sort -nr | head -n 5

     

     

    [devuser@33]$    cut -d ' ' -f 1 localhost_access_log_keystore_8085.2018-07-18.txt  | sort | uniq -c | sort -nr 

         159 821.522.69.594

          2    806.55.26.548

          1    80.12.78.10

          1    818.13.201.99

          1    802.329.16.49

          1    839.362.17.50

          1    819.39.141.16

    展开全文
  • Tomcat是一个web应用服务器,是一个Servlet/Jsp容器,主要负责将客户端请求传递给对应的Servlet,并且将Servlet的响应数据返回给客户端。 Tomcat是基于组件的服务器。 二、Tomcat体系结构 Tomcat是一个基于组件的...
  • Tomcat处理请求过程和重要参数详解

    千次阅读 2018-04-21 16:22:59
    Tomcat处理用户连接请求模式 BIO:阻塞模型 NIO:非阻塞模型 APR:高性能,可扩展的模式,Tomcat8版本默认模式 在使用tomcat时,经常会遇到连接数、线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的...
  • 从一台机器给另一台机器tomcat请求,查看各个环节的耗时时间 - 业精于勤,荒于嬉;行成于思,毁于随。 - CSDN博客https://blog.csdn.net/YAOQINGGG/article/details/50585240 用redis实现tomcat集群下的session...
  • tomcat日志文件 访问IP统计

    千次阅读 2018-09-19 15:02:35
    tomcat localhost_access_log.2018-09-19.txt日志文件 访问IP统计 172.16.8.11 - - [19/Sep/2018:12:35:21 +0800] "GET /console/stat/onlineVisitorRefresh HTTP/1.1" 200 7613 172.16.8.1 - - [19/Sep...
  • Tomcat处理HTTP请求原理&...Tomcat作为Servlet容器,负责处理客户端请求,把请求传送给Servlet,并将Servlet的响应返回给客户端。 三.Tomcat的两个核心组件:Connector和Container 1.Connector组件 ...
  • tomcat 启动和关闭 首先确定%JavaHome%已经配置过 进入tomcat的bin目录,找到startup.bat,双击打开,就启动了tomcat(如果窗口一闪而过,说明JavaHome配置有问题) 在浏览器地址栏输入http://localhost:8080或...
  • tail -1000 localhost_access_log.2020-12-27.txt |grep mobileapp/v2.1|awk '{sum+=$11} END {print "Average = ", sum/NR}'
  • Tomcat面试题+http面试题+Nginx面试题+常见面试题

    千次阅读 多人点赞 2019-12-12 15:04:43
    Tomcat面试题 1、Tomcat的缺省端口是多少?怎么修改?...2、Tomcat有哪几种connector运行模式(服务的请求方式)? 答:三种。修改它的运行模式需要在主配置文件中找到connector字段中的protocol进行修改...
  • tomcat的日志分类 http://blog.csdn.net/fly910905/article/details/78463909 tomcat产生的访问日志数据 【localhost_access_log.Y-M-D.txt】 它记录的访问的时间,IP,访问的资料等相关信息 ...
  • 由于公司的业务比较特殊,对速度比较在意,客户最近反应我们的平台时间比较久,处理一个请求十秒...配置nginx统计请求和后端服务Tomcat服务响应时间 编辑nginx的配置文件nginx.conf log_format main '$remote...
  • Java编写的山寨QQ,多人聊天+用户在线 21个目标文件 摘要:JAVA源码,媒体网络,山寨QQ,Java聊天程序 Java编写的山寨QQ,多人聊天+用户在线,程序分服务端和客户端,典型C/S结构, 当用户发送第一次请求的时候,验证...
  • tomcat Access Log 统计相应时间

    千次阅读 2015-02-04 13:53:24
    Access Log Valve用来创建日志文件,格式与标准的web server日志文件相同。...Access Log Valve的很多配置和行为特性与File ...Access Log Valve可以和任何Catalina容器关联,记录该容器处理的所有请求。 例子如下:
  • 第一时间送达关注公众号后台回复pay或mall获取实战项目资料视频点击此链接:多套SpringCloud/SpringBoot实战项目,资料文档教程齐全作者:编程迷思来源:cnblogs.com/kismetv/p/7806063.html前言在使用tomcat时,...
  • 根据Tomcat的日志统计系统QPS
  • 上一篇文章说到了Tomcat的启动,但是Tomcat作为一个Server,就必须要接收请求,这次分享就着重说一下这部分。说到Tomcat的接收请求,就要想到上节课提到的Connector,提到Connector,就要想到默认的NIO方式。OK,接...
  • nginx+tomcat重复请求

    千次阅读 2015-06-23 10:22:03
    可是通过看网站的统计数据,访问的人数并没有明显的增加。这时自己更加坚定一定是被攻击了! SSH 连上服务器查看日志,居然连 SSH 都特别慢,这让我更加坚定自己的判断,妈蛋绝对被攻击了!但是后台日志没有什么明显...
  • Linux下查看Apache和tomcat请求

    千次阅读 2013-03-18 12:05:38
    在Linux下查看Apache的负载情况,最简单有有效的方式就是查看Apache Server Status,在没有开启Apache Server Status的情况下,或安装的是其他的Web Server,比如Nginx的时候,下面的命令就体现出作用了...统计httpd
  • Tomcat一次http请求处理,filter、servlet调用流程
  • 史上最强Tomcat8性能优化

    万次阅读 多人点赞 2019-10-25 15:33:32
    文章目录授人以鱼不如授人以渔目的服务器资源Tomcat配置优化Linux环境安装运行Tomcat8AJP连接执行器(线程池)3种运行模式部署测试用的web项目查看服务器信息部署web应用使用Apache JMeter进行性能测试下载安装修改...
  • tomcat自带的配置可以对所有访问的ip进行统计,并记录到日志中,但是如果想要 对请求做一些处理, 比如:对ip做一些格式化的操作,tomcat做了磁盘地址映射之后对直接的文件url请求做响应时的Header处理以解决跨域问题等 ...
  • 一、Nginx通过$upstream_response_time requesttime统计请求和后台服务响应时间nginx.conf使用配置方式:logformatmain′request_time统计请求和后台服务响应时间 nginx.conf使用配置方式: log_format main &#...
  • 业务逻辑程序和业务量统计程序不解耦。 2.每次接收到用户请求,在处理完业务逻辑后,将用户业务量记录redis 问题: 每次请求过来都会操作redis,频繁操作redis,会造成redis压力过大; 每次请求过来都会操作一次...
  • 有的时候服务器端接口允许请求的方式多样化且不过定,没有nginx的内网服务还需要统计分析post请求日志 1) 在项目中加入相应的包和类,加载那里无所谓,只要web.xml配置正确即可 package filters;  import ...
  • tomcat localhost_access_log查看http请求

    万次阅读 2016-04-25 09:46:15
    Tomcat接收到的http请求log,都在localhost_access_log_yyyy-MM-dd.log,如 log配置位置在server.xml中 <!-- Access log processes all example. Documentation at: /docs/config/valve.html N

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 30,757
精华内容 12,302
关键字:

tomcat请求统计