高并发的解决思路 - wtdig/study GitHub Wiki

高并发解决思路

一、基本概念

何谓高并发
所谓高并发指的是:在同时或极短时间内,有大量的请求到达服务端,每
个请求都需要服务端耗费资源进行处理,并做出相应的反馈。
n 从服务端视角看高并发
服务端处理请求需要耗费服务端的资源,比如能同时开启的进程数、能同
时运行的线程数、网络连接数、cpu、I/O、内存等等,由于服务端资源是有限
的,那么服务端能同时处理的请求也是有限的
高并发问题的本质就是:资源的有限性
n 高并发带来的问题
服务端的处理和响应会越来越慢,甚至会丢弃部分请求不予处理,更严重
的会导致服务端崩溃。
n 高并发问题并不是互联网应用独有
n 高并发问题的层面
比如:前端请求、Web服务器、Web应用、数据库等

二、解决思路

高并发处理的基本思路

一:从客户端看
1:尽量减少请求数量,比如:依靠客户端自身的缓存或处理能力
2:尽量减少对服务端资源的不必要耗费,比如:重复使用某些资源,如连接池
客户端处理的基本原则就是:能不访问服务端就不要访问
二:从服务端看
1:增加资源供给,比如:
(1)更大的网络带宽
(2)使用更高配置的服务器
(3)使用高性能的Web服务器
(4)使用高性能的数据库
2:请求分流,比如:
(1)使用集群
(2)分布式的系统架构
3:应用优化,比如:
(1)使用更高效的编程语言
(2)优化处理业务逻辑的算法
(3)优化访问数据库的SQL
服务端的处理基本原则是:分而治之,并提高单个请求的处理速度

三、具体手段

一、是手段而非具体的方案

下面按照每个层面来谈谈处理的具体手段,注意不是高并发处理的方案,
方案是要结合具体的应用,综合分析,选择合适的手段组合起来。
另外还要注意,下面提到的手段都是“包含但不限于”
n 客户端发出请求层面,常见的手段有:
1:尽量利用浏览器的缓存功能,减少访问服务端,比如:js、css、图片等
2:可以考虑使用压缩传输的功能,减少网络流量,也会提高传输速度
3:考虑使用异步请求,分批获取数据
n 前端接收客户端请求层面,常见的手段有:

一:比如Nginx这一层
1:动静分离,部分静态资源可以直接从Nginx返回
2:按请求的不同,分发到不同的后端进行处理,比如:负载均衡、业务拆分访问等
3:前面再加上一层来做多个Nginx的负载均衡,比如:LVS、F5等
4:还可以在更前面使用CDN服务

二:比如Varnish这一层
1:还可以对动态内容进行缓存,尽量减少访问后端服务
2:使用页面片断缓存技术,比如ESI(Edge Side Includes )
n Web服务器层面,常见的手段有:
1:使用最新的JVM,并进行配置优化
2:合理选择服务器的运行模式,比如有些服务器有Client和Server之分
3:对Web服务器进行配置优化,比如:调整内存数量、线程数量等
4:提供多个能提供相同服务的Web服务器,以实现负载均衡
5:仔细规划Web服务器上部署的应用规模
6:对Web服务器进行集群
7:提供专门的图片、文件、视频等静态资源服务器

Web应用层面,常见的手段有:
这个可能全在Web服务器里面,也可能有单独的服务层
1:动态内容静态化
2:Java开发优化
3:优化处理业务逻辑的算法
4:合理高效的利用缓存
5:优化访问数据库的Sql,可以考虑利用存储过程等数据库的能力
6:合理使用多线程,加快业务处理
7:部分业务可以考虑内存数据库,或者是进行纯内存处理
8:尽量避免远程调用、大量I/O等耗时的操作
9:合理规划事务等较为耗资源的操作
10:合理使用异步处理
11:对部分业务考虑采用预处理或者预计算的方式,减少实时计算量
12:内部系统间的业务尽量直接调用、直接处理,减少WebService、工作流等

数据库层面,常见的手段有:
1:合理选择数据库的引擎,比如Mysql的InnoDB与MyISAM引擎
2:进行配置优化
3:可以考虑使用存储过程来处理复杂的数据逻辑
4:数据库集群,进行读写分离
5:合理设计数据库的表结构、索引等
6:分库、分表,降低单库、单表的数据量
7:合理使用NoSql

四、web缓存

什么是Web缓存
Web缓存指的是从发起请求的客户端,到执行功能的web服务器之间的,用来保存服
务器输出结果的副本,并提供给发起请求的客户使用,这样的一些缓存的统称。
n Web缓存的类型
1:浏览器缓存
2:CDN(Content Delivery Networks)
3:反向代理服务器缓存
4:Web服务器端的缓存,通常是应用程序来实现的动态页面缓存

n 为何要使用Web缓存
1:加快Web应用响应速度,提高用户满意度
2:减少服务端的处理压力,以同样的资源来支撑更大的访问量和高并发

n 重验证
通常存放在缓冲中的内容是有时效性的,因此需要经常对缓存中的内容做有效性检
查,也叫“重验证”。
n 更新
更新操作主要是为了保证缓存中的内容与服务器中的内容保持一致

一、浏览器缓存

工作机制
浏览器缓存主要是通过在Http头部增加:Last-Modified,If-Modified-
Since,Expires,Cache-Control等标识,和服务器进行协商,以确定是否采用浏览
器的缓存。
n Http中的更新途径:定义文档过期时间、执行重验证

一:文档过期时间
1:在服务端返回的Http头设置:Expires
2:在服务端返回的Http头设置: Cache-Control: max-age
3:同时具有的时候,max-age具有更高的优先级
4:要注意:就算是过期了,并不标志内容一定不对了,只是提醒要求重验证
5:在Java中的设置示例:response.setHeader("Cache-Control","max-age=100“)

二:执行重验证
1:重验证的目的:是与服务器交互,判断缓存中的文档是否已经改变。如已经改变,就
重新下载一份最新的文档,来代替缓存内容;如没有做修改,则只需获取新的HTTP头
部(可能包含新的过期时间),并更新缓存中的头部。
2:在request的Http头设置:If-Modified-Since
如果服务端返回的报头中有“Last-Modified”,那么客户端在下一次请求
报头中会包含“If-Modified-Since”,这两个头部是相互对应的。
当服务器收到客户端请求的“If-Modified-Since”之后,服务器通过比较
这两个时间,若“Last-Modified”更大,表明客户端缓存中的内容已经过时,
服务器会将最新的文档(新的Header)返回给客户端,状态码为200;否则认为
客户端缓存中的内容仍然是最新的,只需向客户端返回304状态码,同时包含最
新的HTTP头部。
3:在request的Http头设置:If-None-Match
这是一种比较文档标签(Entity tags, Etags)的方式。基本思想是为每
一个文档生成一个Etag,它可以是某个序列号、版本号或者检验码。同样“If-
None-Match”头部是与服务器端的“Etag”头部相对应的,这样服务器端只需要
比较标签号就可以判断出客户端缓存中的文档是否是最新的。

浏览器缓存控制
HTTP规范中定义了服务器如何约束、限制客户端缓存的头部,按照优先级分别有:
1:Cache-Control: no-store :禁止缓存,浏览器会删除缓存的内容
2:Cache-Control: no-cache :禁止缓存,浏览器可能会缓存,只是限制本地缓存不能在没
有与服务器执行一致性检查的前提下直接响应用户
3:Cache-Control: must-revalidate :要求缓存在响应用户请求之前一定要先保证缓存中
的文档副本是最新的
4:Cache-Control: max-age :设置过期时间,若max-age=0,则表示不能缓存文档或者每次
访问缓存前必须执行一致性检查
5:Expires
6:在Java中设置示例:
response.setHeader("Cache-Control", "no-cache");
response.addHeader("Cache-Control", "no-store");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", -1);
response.setDateHeader("max-age", 0);

要注意:不同浏览器对这些功能的实现可能不同
n F5和Ctrl+F5 刷新的实现也不同:F5通常是驱使浏览器去执行一次一致性检查;而
“Ctrl+F5”则是在删除本地缓存的前提下,去执行一致性检查
n 如何主动通知浏览器缓存失效
这个问题其实也是静态资源版本更新的问题,基本的解决思路:
1:页面引入js、css等统一做成单独的jsp
2:页面上使用ESI来引入这些jsp
3:如果后端修改了这些静态资源的内容,那么在这些单独的jsp上,修改链接,给这些链接加
上“?版本号”或者“?时间戳”等,反正要修改一下这些链接
4:然后主动请求PURGE,以让Varnish里面缓存这些jsp的内容失效,这样Varnish会从后端重
新获取这些jsp的内容,拼接好新的内容后返回给客户端
5:客户端浏览器会发起新的请求,去重验证资源是否有更新,发出的请求是按照这些新的链
接发出的,那么服务器端是没有这些链接对应的Etag的,就会重新下载新的资源了
6:当然,由于更新资源和缓存内容之间会有一个时间差,对于大型的高并发的应用,这种不
同步可能会造成一点小问题,这就需要更专业的工具来同步更新服务器的静态资源了。

二、反向代理缓存

三、

五、

六、