鲁迅说过:如果你也想戴上高级Java程序员这顶高帽子,那么高并发相关解决方案你必须深入骨髓.
高并发场景下,主要解决几个问题:
①请求的响应时间变长,如何才能减少请求响应时间,提升用户体验.
②数据的安全,在高并发多线程场景下,由于竟态条件,指令重排等影响,很容易出现数据不安全问题,需要避免.
③高并发场景下,容易造成服务器过载,造成单点故障.
...
为了改善高并发带来的种种问题,已经有了很多前车之鉴,现开篇总结之,虽然在过去几十篇里有总结过,但零零总总,不成体系,这里再次系统总结.
JavaScript文件源代码可以采用混淆压缩的方式,CSS文件源代码进行普通压缩,JPG图片可以根据具体质量来压缩为50%到70%,PNG可以使用一些开源压缩软件来压缩,比如24色变成8色、去掉一些PNG格式信息等。
如果图片颜色数较多就使用JPG格式,如果图片颜色数较少就使用PNG格式.
包括CSS、JavaScript和小图片,减少HTTP请求。有很大一部分用户访问会因为这一条而取得最大受益.
这对文本资源非常有效,对图片资源压缩效果感人...
使用CDN加速或者一些公开库使用第三方提供的静态资源地址(比如jQuery、normalize.css)。一方面增加并发下载量,另一方面能够和其他网站共享缓存。这里推荐一个免费开源的CDN加速网站:https://www.bootcdn.cn/
如此,频繁访问网站的访客就能够更快地访问。不过,这里要通过修改文件名的方式,确保在资源更新的时候,用户会拉取到最新的内容。
这样就不会阻塞页面渲染,让页面出现长时间的空白。
这里以Vue为例,Vue具有一些强大的功能和高级特性,可以使得页面渲染变得非常快,从而减少提高高并发场景下的部分延迟.
①Vue一般是单页面应用,这样如果有一个组件非常大(个人认为超过1M)就有必要对其进行异步组件处理,也就是在组件注册时采用箭头函数的语法对其进行优化:
#同步组件引入方式:
import Detail from '@/pages/home/Home'
{
path: '/',
name: 'Home',
component: Home
}
#异步组件引入方式:
{
path: '/city',
name: 'City',
component: () => import('@/pages/city/City')
}
这样在页面初次加载时就不会加载太久,在用到时异步加载,可以减轻服务器IO压力和提高初次访问时的页面加载速度.
②使用ES6箭头函数配合定时器,限制一些监听器的刷新频率,比如我们常用到的屏幕滚动时触发的纵坐标改变,如果不进行限制,所涉及的函数会被高频执行,影响性能.
③使用
④可以使用Vue的一些高级特性,比如服务端渲染,来提高页面的渲染速度.
①nginx对静态资源的访问性能是非常高的,可以每秒处理2万个以上的并发.
②合理配置nginx,对Nginx进行性能调优,比如尽量使用epoll模式,开启gzip压缩,对静态资源进行缓存等.
在页面小图片过多但页面布局已经稳定的情况下,可以考虑使用精灵图,减少请求发送,提高性能.
前端部分就总结这么多,毕竟我是个做后端的,前端部分就知道这么点,还希望各位看客能在评论处不吝赐教.
1.扩容
扩容包括水平扩容和垂直扩容,垂直扩容是在硬件层面进行扩展,比如增大内存CPU数量等,垂直扩容难度和挑战比较小,但成本较高,尤其是在到达一定程度以后,而且有极限,不能无限扩展.水平扩容是指通过一些技术手段,将请求分发到不同的服务器上,以此来降低单台服务器压力.比如可以使用Nginx对后端项目进行负载均衡(常用),还有一些采用DNS甚至硬件来完成,小公司一般不会用.
2.缓存
在绝大多数情况下,服务器的压力都会集中在数据库,减少数据库的访问次数,就可以减轻服务器的压力.所以,在高并发场景下,缓存的作用是至关重要的,常见的缓存有对象级缓存,还有缓存数据库如memcache,redis,encache等.通过对一些数据不常发生改变,但查询操作较频繁的接口添加缓存,减少对后端数据库的访问,大幅提高服务器性能.
3.消息队列
消息队列可以将应用解耦,可以用来削峰,同时异步的操作可以减少请求响应时间,降低单台服务器压力,在一些场景下还可以配合quarz/elastic-job提高服务器的利用率,避免服务器白天过于繁忙,晚上过于空闲.
4.应用拆分
当应用膨胀到一定程度后,可以对应用进行拆分,拆分可以按模块甚至功能去拆,把控好现阶段要拆分的粒度,然后选用适合的rpc/微服务框架,拆分后的系统会比较易于管理和维护,采用分布式后也可以提高性能,但相应的风险和复杂度以及对人员/技术的要求也会上升.
5.限流
单台服务器的处理能力总是有限的,具体能承受多少QPS可以通过Apache Bench,jmeter等工具测出来,然后预计最高的并发量也能大致估算出来,两者相结合可以大致估算出单台服务器是否能承受峰值并发,如果不能,需要对服务进行限流,以保障服务器不会因为过载而宕机,限流可以通过redis等高性能数据库来实现,当然也可以使用spring-cloud的zuul来实现,前提是你的项目是微服务架构.
6.服务降级/熔断
通过对服务降级可以有效降低服务器负载,熔断机制则可以起到保护作用,单台服务器在已经过载的情况下,拒绝所有新的请求,从而逐步恢复正常,spring-cloud提供了hystrix组件,可以方便的实现服务降级/熔断.
7.数据库读写分离,分库分表
当该优化的都优化了,但数据库依旧承受不住相应的并发,这时候就需要对数据库进行读写分离,甚至水平和垂直拆分,来避免单库过载,单表数据量过大等问题影响数据库性能.遇到这种场景时,可以使用Mycat对数据库做读写分离,采取一主多从,多主多从的数据库架构,对于单表数据量过大的情况,还需要进行分库,甚至分表.Mycat分库分表我在Mysql章节已有总结,有兴趣可以去看.
8.使用多线程,并发编程.
JUC提供了很多并发容器和工具,帮助我们在高并发场景下高效安全的进行各种操作,充分利用CPU多核性能,提高服务器性能,降低请求耗时.
9.生产环境关闭不必要的日志打印
在生产环境下,尤其是高并发场景下,日志的打印会拖慢系统响应时间,占用服务器资源,所以可以关闭一些不必要的日志,将日志级别设为error级别.实际压测表明,此举可以大幅提高QPS.
未完待续...