tomcat假死分析 连接\请求\线程 io模式

服务挂掉的两种现象

504 Gateway Time-out ---05月16 13:22:17
the gateway did not receive a timely response from the upsteream server or application.
页面访问https://bi.pp.com/rsbi/frame/Frame.action 504
504超时:这种应该是tomcat接收了请求,放到了请求对列,但是因为线程等资源被前面的资源一直占用,导致一直在排队所以超时。

502 Bad Gateway---05月28日 14:18:05
the proxy server received an invalid response from an upstream server.
页面访问:
此时说明tomcat的连接已经满负荷运行,acceptCount也已经达到了最大值,再来的反应被tomcat拒绝了,返回无效的响应
此时tomcat不再打印任何日志,但是进程和端口还在被占用。

上面两个结果是nginx返回的,此时查看tomcat日志,会发现日志不再打印,感觉停止了一切服务,其实这个就是程序假死。

程序假死的理解

程序假死直观印象
你肯定遇到过word软件无缘无故没反应了,或者某个程序点什么按钮都不再有反应(一直打转),唯一的办法就是进入进程管理器杀掉进程并重启该软件。这其实就是程序假死的现象。

程序假死原因
资源问题:从根本上说,程序无响应是因为这个程序在运行时向系统请求资源,但一直处在资源不足的状态下,久而久只,出现了饿死现象。如jvm资源,cpu被别的程序占用,自己内部线程资源等
程序自身问题:应用本身程序的问题,造成死锁,无法继续运行;

下面是一些分析tomcat假死的实例。
https://www.iteye.com/blog/bijian1013-2271600 --分析tomcat假死 jvm导致,新生代已满,tomcat无法新建对象
https://my.oschina.net/u/1176977/blog/759554  --tomcat假死  程序资源未释放
https://www.zhangjianyu.top/2017/09/15/jvm调试/ --tomcat请求未释放,超过当前最大线程数

tomcat因连接阻塞导致假死原因分析

我的tomcat会假死?有没有什么日志能佐证?阻塞多少tomcat会假死?
tomcat默认bio(8.0开始默认nio),然后因为每次请求都是需要查库的耗时连接,所以导致连接阻塞,maxConnection默认为200 acceptCount默认值100,换句话能承受的最大连接数是300,超过就会拒绝。此时nginx就会提示502或者504
猛地一看300个连接好像不少了,但是这里面tomcat里面一共两个项目,其中报表并发性比较高(报表中一个面板的访问是多个请求),且包含很多大sql执行+大量定时任务执行的时候确实可能干到最大连接数,而超时回收需要60秒。
tomcat连接超时时间是20000ms,即20s,这个时间很长了。

现在bi使用人数共计200人,高峰期并发使用数肯定能达到300。注意如果点击后没有反应,那么我们的做法通常是再次点击重试,反而会增加tomcat的连接数。这是一个恶性循环,不是想象中的连接拒绝后就没事了,然后会释放。

遗憾的是并没有找到日志能够证明是连接或线程耗尽导致的程序假死。

上面tomcat假死,并没有找到确定的原因和答案。。。。。希望大家补充。。。。。。。。。。。

注意:原本笔者错误的以为项目中的数据库连接、调用远程的dubbo服务也会走tomcat的连接,其实不经过tomcat,我们浏览器输入网址经过tomcat是因为端口的绑定。

tomcat的连接、请求和线程

点击多个菜单,会有多个连接吗?还是一个连接多个请求???????
这个答案是 一个连接多个请求,
BIO是一个连接一个线程。
NIO是一个请求一个线程。
我的理解是这样的,在bio和nio下,长连接下,单个连接都可以处理多个请求。
但不同点是,因为bio一连接一线程,且bio会导致线程一致耗在当前处理的请求上,所以bio中的多个请求只能排队处理,不能并发处理。所以如果一个请求比较大时,长时间占用连接。
但是nio是一个请求一个线程,所以nio中的多个请求会并发处理,能大大提高效率,但是多个请求的结果需要按照请求进入连接的顺序来返回。

对于同一个tcp连接,http1.1 允许一次发送多个 http1.1 请求,也就是说,不必等前一个响应收到,就可以发送下一个请求,这样就解决了 http1.0 的客户端的队首阻塞。但是,http1.1 规定,服务器端的响应的发送要根据请求被接收的顺序排队,也就是说,先接收到的请求的响应也要先发送。这样造成的问题是,如果最先收到的请求的处理时间长的话,响应生成也慢,就会阻塞已经生成了的响应的发送。也会造成队首阻塞。
参考:https://www.v2ex.com/amp/t/525759
https://tools.ietf.org/html/rfc2068#section-8.1

tomcat reactor通信模式

Reactor模式的优点很明显,解耦、提升复用性、模块化、可移植性、事件驱动、细力度的并发控制等。Reactor模式的缺点也很明显,模型复杂,因为涉及到内部回调,多线程处理,不容易调试;需要操作系统底层支持,这就导致不同操作系统可能会产生不一样的结果。所以总的来说如果并发要求不是那么高,使用传统的阻塞线程池模型足够了,而且调试、查问题都会简单很多;如果我们的使用场景是会产生瞬时大并发,可以使用Reactor模式来实现,目前大部分的NIO框架或者容器都是实现了Reactor模式,Tomcat、Jetty的NIO都是实现了Reactor模式,Netty和Mina是两套NIO的框架,也分别对Java NIO进行了二次封装实现了Reactor模式。
博客如下:
https://blog.csdn.net/h2604396739/article/details/81123143

BIO/NIO模式对tomcat的影响

无论是BIO,还是NIO,Connector处理请求的大致流程是一样的:
在accept队列中接收连接(当客户端向服务器发送请求时,如果客户端与OS完成三次握手建立了连接,则OS将该连接放入accept队列);在连接中获取请求的数据,生成request;调用servlet容器处理请求;返回response。

在BIO实现的Connector中,处理请求的主要实体是JIoEndpoint对象。JIoEndpoint维护了Acceptor和Worker:Acceptor接收socket,然后从Worker线程池中找出空闲的线程处理socket,如果worker线程池没有空闲线程,则Acceptor将阻塞。其中Worker是Tomcat自带的线程池,如果通过<Executor>配置了其他线程池,原理与Worker类似。

在NIO实现的Connector中,处理请求的主要实体是NIoEndpoint对象。NIoEndpoint中除了包含Acceptor和Worker外,还使用了Poller。

Acceptor接收socket后,不是直接使用Worker中的线程处理请求,而是先将请求发送给了Poller,而Poller是实现NIO的关键。Acceptor向Poller发送请求通过队列实现,使用了典型的生产者-消费者模式。在Poller中,维护了一个Selector对象;当Poller从队列中取出socket后,注册到该Selector中;然后通过遍历Selector,找出其中可读的socket,并使用Worker中的线程处理相应请求。与BIO类似,Worker也可以被自定义的线程池代替。

在NIoEndpoint处理请求的过程中,无论是Acceptor接收socket,还是线程处理请求,使用的仍然是阻塞方式;但在“读取socket并交给Worker中的线程”的这个过程中,使用非阻塞的NIO实现,这是NIO模式与BIO模式的最主要区别(其他区别对性能影响较小,暂时略去不提)。而这个区别,在并发量较大的情形下可以带来Tomcat效率的显著提升:

目前大多数HTTP请求使用的是长连接(HTTP/1.1默认keep-alive为true),而长连接意味着,一个TCP的socket在当前请求结束后,如果没有新的请求到来,socket不会立马释放,而是等timeout后再释放。如果使用BIO,“读取socket并交给Worker中的线程”这个过程是阻塞的,也就意味着在socket等待下一个请求或等待释放的过程中,处理这个socket的工作线程会一直被占用,无法释放;因此Tomcat可以同时处理的socket数目不能超过最大线程数,性能受到了极大限制。而使用NIO,“读取socket并交给Worker中的线程”这个过程是非阻塞的,当socket在等待下一个请求或等待释放时,并不会占用工作线程,因此Tomcat可以同时处理的socket数目远大于最大线程数,并发性能大大提高。

bio nio 和aio区别可以参考文章;可以参考https://blog.csdn.net/h2604396739/article/details/82534253
http://tomcat.apache.org/tomcat-7.0-doc/config/http.html---tomcat connector配置官网说明
https://blog.csdn.net/m0_37797416/article/details/83505663----tomcat中server.xml中Connector各个参数的意义
https://www.cnblogs.com/kismetv/p/7806063.html#t2--详解tomcat的连接数与线程池
https://blog.csdn.net/binglong_world/article/details/80748520----杜绝假死,Tomcat容器设置最大连接数

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值