Springboot 内嵌Tomcat 的http连接池与thread的关系
前言
- 最近看了很多tcp/ip 连接以及 IO相关的文章,但是依旧对数据库连接池等的部分不是很清楚, 所以这里仅是简单描述一下tomcat对应的http连接池数量的情况,不考虑与数据库的连接池的情况.
Linux内核相关
- 周天时简单总结了下linux内核的两个参数.somaxconn以及tcp_max_sync_backlog.这两天又学习了解了下.发现这两个配置文件其实讲的是全连接以及半连接的队列, 但是真正开始进入数据传输时应该就已经不在这两个队列里面了. 如下图所示.
- 所以前面两个参数应该是负责处理连接队列的,整整进入tomcat与client的交互时应该就不需要使用者两个队列了.核心就会变成其他的参数.
- 这里我理解核心的参数应该是 1. 当前操作系统剩余内存能够支撑的tcp连接数, 2.nofile 当前进程能够打开的文件数减去程序已经加载的文件数. 比如我们springboot的项目如果有1000个jar包可能就会产生1000-2000个fd的连接数,加上日志,以及一些监听pid等文件nofile -2000 左右才是可以使用的tcp连接数
- 这里 我的理解不一定正确, 我认为一个与tomcat 进行的tcp连接至少要占用一个文件描述符, 但是不清楚一个tcp连接复用多个http连接会不会占用更多的fd.
Tomcat相关
- 还是回到之前的配置参数
server:
#tomcat配置
tomcat:
# 当所有线程都在使用时,建立连接的请求的等待队列长度,默认100
accept-count: 1000
# 线程池维持最小线程数,默认10
min-spare-threads: 4
# 允许最大连接数,默认10000,当达到临界值时,系统可能会基于accept-count继续接受连接
max-connections: 10000
# 最大线程数,默认200
max-threads: 1000
- 这里进行解释:
max-thread: 应该就是 jstack-l 里面出现的 http 开头的thread信息, 随着threads 的数量的增加, 能够创建的线程会更多, 但是线程的创建和切换都是有成本的, 虽然线程能够共享进程的内存以及部分寄存器,但是上下文还是需要每次切换时进行switch, 线程多了切换的次数会变多,并且管理成本也比较高, 不建议设置的特别多,除非操作系统的cores 数特别多.
min-spare-threads: 这个参数可以应付在冷启动之后突然爆发的大量请求,避免一开会无法批量创建threads 时造成影响非常缓慢,建议可以保留一些.
需要注意的一点是 这两个线程都是 jvm 内部的线程, 内个现场都需要有 java的stack的size. 理论上默认值是 1m 左右, 可以设置为 256k 或者是更小 但是不能低于 172KB 还是一个具体的多大的数值, 但是如果栈空间过小, 会出现stack over flow的错误,并且递归的深度可能会不够, 不建议将栈空间设置的过小,毕竟会导致栈帧数量下降.
需要注意的另外一点,除非tomcat的http线程 还需要有类似于1. redis的连接线程. 2.gc线程. 3.数据库连接线程. 但是数据库的连接池好像不是在jvm的堆区和栈区管理的, 这一块需要找专家同事学习沟通一下. 我还没看到那一块内容.
max-connections: 关于这个参数,可能需要专门说明一下, 因为linux有BIO NIO以及AIO等IO模型,一般的说法是,自从tomcat 7 之后已经不支持BIO模型了,BIO时 没一个线程只能为一个 connection服务, 会导致吞吐量下降的很厉害. NIO非阻塞的IO时, 因为在内核和网卡驱动这一块时是不需要thread等待的, 所以thread可以为其他进程服务, 所以这个时候thread可以为远远大于自己的connections 来提供服务, 但是需要注意的一点是,如果是高CPU 低IO的场景, connection 是thread 的比较高的倍数时就显得不太合适了, 只有IO占用较多资源和时间时可以将connection 数值设置的thread大很多, 默认值就是10000.
关于这个10000 我这里的理解时 如果没个connection的round time 都是10s 左右的话如果每个线程只需要有1s左右的线程计算时间,那么理论上1000个thread就可以提供服务了. 但是具体的算法需要参照源码,可能比我想象的要复杂很多.
accept-count: 这个参数就会到了咱们内核参数里面的 somaxconn 参数对应了,就算这个参数可以设置的很大, 比如1000 但是实际上 具体的连接池大小是收到somaxconn和accept-count里面的较小值来决定的, 所以如果线程数较少,并且并发数产生了很多的连接数时很容易就会将max-connections 的数值打满,然后开始用accept-count的参数值,如果somaxconn是默认值的话 比如centos7 上面都是 128 那么第 10129个连接应该直接就会被linux 给drop 客户端返回connection reset 的提示信息 (自己推断的,还没明确实验)
IO相关
- 最近有很多公众号在将linux的IO模型,最近一个月以来也看了很多内容,理解的不是很透彻, 这里简单总结一下.
IO有很多种类,磁盘是IO,键盘是IO,网络栈的收发其实也是IO操作.
因为CPU都是纳秒级别的反应, 网络的IO都是几十上百毫秒的延迟, 这里面有六七个数量级的延迟,为了不让CPU干耗着去等待缓慢的网络IO(机械磁盘IO也是如此),在最开始的blocked IO 基础之上 慢慢研发了NIO和AIO.
需要注意的是linux比较多的是NIO noblocked 但是AIO 也就是异步非阻塞IO实现的比较少一些.
阻塞和非阻塞IO的核心区别在于 在CPU获取到需要的IO数据之前 用户态的线程是在等待还是在干别的
如果在等待,那么就是阻塞IO,如果不等待而去干别的了 就是非阻塞IO.
CPU获取到数据之后,如果从内核态往用户态传输数据时是需要用户态线程参与的,就还是同步的
如果只是CPU将需要的IO数据复制到了用户态需要使用的地方,直接通知用户线程进行处理,那么就是异步的.
需要注意的是 linux还有一个zero copy的概念, 其实与内存里面的 copy on write 类似
都是避免不必要的内存读写,节约宝贵的总线带宽或者是内存带宽拉实现提高性能的操作.
nginx 就使用了sendfile的方式进行 zero copy的机制来提高静态文件的传输速度, 记得能够减少一次内核态到用户态的文件copy,只是传递fd就可以让网卡直接传输client想服务器申请访问的资源.
tomcat 作为 app server 感觉这一块不如 nginx这种io复用的纯web server 处理静态资源来的省时省力.
所以tomcat有一个handler 可以进行判断请求类型,如果是静态类型的话 交由一个类似的nginx web server 来处理,但是还是感觉会导致tomcat的负载变大, 建议还是前端静态文件还是专门有一个静态文件服务器来跑比较好一些.
疑惑的地方
- springboot 开起来的进程之后线程数其实非常多,有redis的,有操作连接池的,也有tomcat用来实现http连接等的. 还有跟当前CPU数目一致数量的GC线程. 但是我一直不知道数据库连接池是如何管理的,虽然能在jstack 打开的thread 信息里面看到hikari pool 等的相关信息.但是感觉这些只是springboot 进行使用数据库连接池的进程,而不是管理数据库连接池的线程.
- dump堆栈信息里面包含的内容,是否不包含native memory和method pool等. 以及连接池到底存放在何处,如何进行监控,如果单一个db多个app-server时 如果每一个app-server都保持一个比较多的数据量连接池,那么会不会对数据库服务器有较大的压力存在?
Springboot 内嵌Tomcat 的http连接池与thread的关系的更多相关文章
- 查看和指定SpringBoot内嵌Tomcat的版本
查看当前使用的Tomcat版本号 Maven Repository中查看 比如我们需要查Spring Boot 2.1.4-RELEASE的内嵌Tomcat版本, 可以打开链接: https://mv ...
- SpringBoot内嵌Tomcat开启APR模式(运行环境为Centos7)
网上查到的一些springboot内嵌的tomcat开启apr的文章,好像使用的springboot版本较老,在SpringBoot 2.0.4.RELEASE中已经行不通了.自己整理了一下,供参考. ...
- [Web Server]Tomcat调优之SpringBoot内嵌Tomcat源码分析
以springboot:2.3.12.RELEASE中内嵌的tomcat-embed-core:9.0.46为例,进行分析 1 概述 1.0 关键依赖包 spring-boot-autoconfigu ...
- Spring Boot启动过程(五):Springboot内嵌Tomcat对象的start
标题和上一篇很像,所以特别强调一下,这个是Tomcat对象的. 从TomcatEmbeddedServletContainer的this.tomcat.start()开始,主要是利用Lifecycle ...
- maven打包排除spring-boot内嵌tomcat容器依赖jar
在pom文件中添加打包排除配置信息. <plugin> <artifactId>maven-war-plugin</artifactId> <version& ...
- springboot去除内嵌tomcat和打包在tomcat中运行需要做的步骤
去除内嵌tomcat和添加jsp依赖 去除内嵌tomcat 在springboot启动依赖中去除内嵌tomcat <dependency> <groupId>org.sprin ...
- 如何优雅的关闭基于Spring Boot 内嵌 Tomcat 的 Web 应用
背景 最近在搞云化项目的启动脚本,觉得以往kill方式关闭服务项目太粗暴了,这种kill关闭应用的方式会让当前应用将所有处理中的请求丢弃,响应失败.这种形式的响应失败在处理重要业务逻辑中是要极力避免的 ...
- 学习Tomcat(七)之Spring内嵌Tomcat
前面的文章中,我们介绍了Tomcat容器的关键组件和类加载器,但是现在的J2EE开发中更多的是使用SpringBoot内嵌的Tomcat容器,而不是单独安装Tomcat应用.那么Spring是怎么和T ...
- c3p0、dbcp、tomcat jdbc pool 连接池配置简介及常用数据库的driverClass和驱动包
[-] DBCP连接池配置 dbcp jar包 c3p0连接池配置 c3p0 jar包 jdbc-pool连接池配置 jdbc-pool jar包 常用数据库的driverClass和jdbcUrl ...
- 内嵌tomcat最简单用法
maven项目引入内嵌tomcat依赖 <dependency> <groupId>org.apache.tomcat.embed</groupId> <ar ...
随机推荐
- 网络性能总不好?网络调优专家AOE帮你来“看看”
摘要:为提升网络性能.降低人工调优成本,CANN推出了自动化网络调优工具AOE,通过子图调优.算子调优与梯度调优的功能,让网络可以在AI硬件上获得最佳性能. 本文分享自华为云社区<网络性能总不好 ...
- Github 自建一个 Helm Charts 库
前言 在构建私有的 charts 仓库之前,有几个先决条件: Helm 已经安装,版本号是 v3 拥有一个 Github 账号 初始化仓库 在 github 仓库上新建一个仓库,我这里命名为 helm ...
- Python数据预处理:彻底理解标准化和归一化
数据预处理 数据中不同特征的量纲可能不一致,数值间的差别可能很大,不进行处理可能会影响到数据分析的结果,因此,需要对数据按照一定比例进行缩放,使之落在一个特定的区域,便于进行综合分析. 常用的方法有两 ...
- Vue框架基础
博客目录 前端发展介绍 Vue的快速使用 插值语法 指令系统之文本指令.事件指令.属性指令 style和class 条件渲染 列表渲染 使用v-for进行循环 监控失效 双向数据绑定 input输入框 ...
- Win 下 Redis 设置开机启动
1,在redis的目录下执行(执行后就作为windows服务了) redis-server.exe --service-install redis.windows.conf 2,安装好后需要手动启动r ...
- Windows 系统如何完全卸载 VSCode
0. 参考资料 Uninstall visual studio code in windows 1. 删不干净的用户数据 最近正在从 Sublime Text 3 环境切换到 VS Code,看重的是 ...
- fetch概述
1.基本特性 更加简单的数据获取方式,功能更强大.更灵活,可以看做是xhr的升级版 基于promise实现 2.语法结构 3.fetch的基本用法
- Delete `␍`eslint(prettier/prettier)错误
最佳实践: 现在VScode,Notepad++编辑器都能够自动识别文件的换行符是LF还是CRLF. 如果你用的是windows,文件编码是UTF-8且包含中文,最好全局将autocrlf设置为fal ...
- 这才是你应该了解的Redis数据结构!
深入了解Redis数据结构 Redis,作为一种高性能的内存数据库,支持多种数据结构,从简单的字符串到复杂的哈希表.在这篇博文中,我们将深入探讨Redis的一些主要数据结构,并通过详细的例子展示它们的 ...
- idea导入maven项目结构不全
本文为博主原创,转载请注明出处 将本地的项目导入idea中,其操作第一步为: File->open->选中导入maven项目的pom文件,正常情况通过该步骤项目就会导入到idea中. 通过 ...