本篇和大家聊聊我理解的并发中我们需要学习的东西,我们之前的博文已经写了
- 并发编程(异步的方式提高程序的整体性能)
- 分布式消息中间件(部分)
后续我的想法是聊:
- 分布式存储(优化IO部分)
- 分布式架构(服务治理等->架构层面的优化)
- 性能优化(Jvm、Tomcat、MySQL、算法)
有时候发现学习一些技术,并不知道他有什用处,所以本篇,我想对并发这里这的一些点做一个梳理,看看什么时候可以使用什么技术。这里使用一个1000w用户的并发问题来阐述使在并发中用什么技术能够达到问题落地。
当我们收到这样一个需求的时候,我们关心的肯定是TPS(客户端发送一个请求,服务端返回一个请求)、QPS(每秒查询数量-1个TPS中可能有多个QPS)、并发数、RT(平均响应时长)、DAU(日活)等,我们需要根据这些指标对整个架构进行设计。
【通过数据进行判断】,在之前的系统运行期间,肯定有监控,可以知道那个页面的QPS等这些参数是多少
【通过经验判断】:二八定律(这里想清楚一个概念,1000w的用户不一定是1000w的并发数,因为这些用户不可能实时的访问)按照这个定律来讲,
- 一天访问的用户量可能就占用了20%(200w),假设每个用户点击50次,那我们的pv就是1个亿。
- 再次按照这个法则,每天大部分活跃用户的集中在一天中的20%的时间去访问(这个就是峰值,淘宝的一天访问量就下午的两点,和晚上的九点)。
- 那一天是24小时的20%那就是5个小时。那就意味着有(1亿pv的80%)8000w的pv在一天内的5个小时中集中访问。
- 那就意味着每秒大概有4500个的请求(这个意味着是这5个小时的平均值,不包括峰值),
- 按照经验我们把这个数字4500*4=18000个请求1s(峰值),最终就算出来了,我们服务器要承载的是18000/s(qps)
- 并发量=QPS*RT 比如说一个请求,平均处理速度是3s 那就是18000*3=54000(并发数) 那1000w的用户,我们的服务器要支撑54000/S的并发数
知道了并发数量,那我们就开始设计架构,首先我们要知道影响我们并发的因素有哪些,以及如何优化:
【Tomcat】:
(请求到首先到Tomcat,在NIO的模式下,默认的数量是1w,如果请求超过1w,那Tomcat就拒收请求,tomcat内部把请求变成一个个request转发到我们的controller中,所以首先优化连接数量
系统层:
- 优化连接数量:一个请求就是一个连接数量。一个请求过来就会生成一个FD文件在linux中,默认情况下一个进程能够打开的文件是1024个,所有用户的进程打开文件上限改为65536
- 修改系统层面的连接数:一个tcp连接有两个缓冲区一个是4096(缓冲区和&接受缓存区)会占用8kb的内存(那对于一个8G的内存,最多我们支持的是100w(服务器能够支撑的并发数量)
应用层:
- NIO: 他采用了多路复用机制,当一个请求过来他不阻塞,这样就可以处理N个连接
- 线程池:max-therad(设置工作线程数量 默认是200) max-connection(最大连接数量 在NIO模式下默认是1000)
查看tomcat官网http://tomcat.apache.org/tomcat-8.0-doc/config/http.html
【JVM】:Tomcat是用java写的,那我们肯定要看对JVM进行优化,jvm其实就是一个虚拟机,我们的VMware一样,他也有自己的内存等。我们针对两点进行调优:
- GC算法和内存空间:空间不足的情况下就会导致频繁GC,随之就会暂停所有线程,那就会造成系统卡顿,那就会造成请求堆积。后面关于JVM调优这里我会专门写一篇博文。
【服务器数量评估】:
服务器可以支撑的并发可以通过压测得出,比如一台服务器可以支撑500个qps, 那我们的18000就需要36台服务器,天哪,太多了,实际上我们这样干公司要换人了。我们肯定是针对频繁访问的服务进行机器的堆积。那服务器的架构就是这样的,比如我这个服务是需要5台Tomcat集群,然后我们给tomcat前面架Nginx集群进行分发,防止Nginx挂,我们给他前面放LVS对他进行主备。
【应用层面(RT值)】:业务逻辑处理的本质就是io
- 查询数据库(磁盘IO):数据库层面的优化、分库分表、索引、读写分离、so on
- 访问磁盘(磁盘iIO):磁盘的页缓存(异步刷盘、同步刷盘)、顺序读写、零拷贝、mmp(内存映射、减少拷贝次数)、异步化
- 内存运算(内存IO):内存缓存
- 远程通讯(rpc)(网络io):池化技术(一次性创建多个连接)、长链接、同网段通信(内网通信)、减少网络通信的场景
- 数据结构算法
架构层面:分布式架构(分摊压力,提升性能,单点增加服务等优势使其成为承载并发的一个利器)