`
nnwq
  • 浏览: 203585 次
社区版块
存档分类
最新评论

真实的现场高并发笔记

阅读更多

引言

 

  由于最近LZ负责的业务系统频繁宕机,导致LZ疲于本命,上一个星期(因为现在是周一了,0.0)连续加了五天班,其中还包括周末,就是为了出一套应急方案。宕机的根本原因,现在已经渐渐真正的明晰了,最早的一次是因为消息发送与数据库操作的顺序错误导致的数据库宕机,目前已经通过顺序的调换解决了数据库的压力。然而数据库的问题解决之后,则开始是应用服务器出问题。最近频繁宕机的原因是连接数经常爆满,完全无法应付nginx的疯狂攻击。

  经过与公司领导与业务人员的交流,最终才知道,由于业务模式的变化,导致LZ负责的业务系统用户剧增。因为高并发的原因,LZ的系统现在已经频繁的不堪重负,数次被压垮,提升服务器的响应速度已经迫在眉睫。最终定制的解决方案是比较主流的解决方案,也就是将前端采用集群部署,而后台与其它业务系统的交互,则会采用独立的服务器处理。不过这个方案并不能一解燃眉之急,集群的部署和前端与后台的分割都需要不短的时间进行部署和测试,因此只能安排到这周一(其实就是今天,0.0)才开始推行。

  为了避免在系统向集群转换的过程中再出现问题,LZ与各位领导商量之后就制定了一个简单的应急方案,而LZ则担任了编写应急方案的职责。最近的几天,LZ就是在忙于编写这个应急方案(除此之外,还要边应付业务人员和其它同事对系统的不满,0.0),怎一个焦头烂额可以形容。

 

并发的意识

 

  应急方案采用的方式是,增加用户数限制以及优先级的功能。用户数限制的功能类似于火车站之前的抢登陆,简单的说,就是这个系统只能若干个(比如1000个)用户登陆,后面来的用户将被拒绝登陆。优先级的功能,则是指在人数达到一定数目时,需要将某些角色的用户踢掉,让另外一部分角色的人优先使用系统(这是因为那些被踢的角色查询的数据量较大且对系统的依赖性不高,容易给服务器造成不必要的压力)。这个功能LZ一开始觉得挺简单的,但是当LZ真写起来的时候,才发现真的没有想象中的那么简单。

  最开始的难度在于用户数的精确统计,因为用户数与session数量并没有直接关系,要想统计精确的用户数,必须按照用户名去重。这一点在找到适合的监听器(LZ使用的监听器是存在于web服务器中的HttpSessionAttributeListener,但这不一定适用于所有项目)之后被解决,方案就是记录每个用户的session数量,为0则代表该用户已退出,否则代表正在使用系统(也就是会算作1个用户)。

  然而最难的地方却不是用户数的精确统计,而是并发所导致的难度。因为用户数是在高并发的情况下统计的,因此必须考虑并发的情况,在代码中添加适当的同步,即要保证统计数据的正确性,又得保证足够的性能。如果因为这个数量统计而影响性能,那就与这个功能的意义背道而驰了。

  这还是LZ第一次在高并发的情况下编程(以前其实也有,只是由于功能并不核心,所以从未考虑过性能,只是无脑的在方法上使用synchronized),每写一句代码,都要考虑如果有成百上千个线程同时运行会如何。这每一句代码似乎都成了美女,每一个都可能有成百上千个大爷翻牌,而且还是同时,因此到底如何同时伺候N(N>1)个大爷,自然就成了一个问题。这也算是LZ第一次在编程的过程中,真真切切的产生了并发的意识。

 

书中自有黄金屋

 

  或许是老天开眼,也或许是LZ运气尚且说的过去,在这之前的几个星期,LZ刚买了一本关于并发编程的书籍,一直都没有看。这下可好了,刚好派上用场,因此拿起这本书不到两天,LZ就一口气读了将近一半。最终也算是临时抱佛脚,将这个应急方案给应付过去了。

  由于LZ只是为了应付当前的情况,所以并没有细读,尽管读的过程中都读懂了,也与作者有深深的共鸣,但过后其实印象并不深。不过这足以让LZ度过当前的难关了,在编写这段并发代码时,LZ主要采取了以下几种小技巧(基于书中的思想)。

  1、将原本存在于监听器和过滤器的属性全部提出,使得两者不再需要考虑线程安全的问题。

  2、提出的属性放在单独的两个类(session有效列表和session无效列表,无效列表其实就是可能要被踢的session)当中,这两个类都是单例,并确保这两个类是线程安全的。

  3、由于需要遍历一个装满session的集合实现踢人的功能,因此采用备份的方式。如此一来,在遍历session并使得session失效时,并不会锁住失效session的列表,这样可以极大的提高性能(前提是限制的用户数并不高)。

  4、在监听器与过滤器使用这两个单例类时,坚决杜绝各种竞态条件或者复合操作。

  5、重构现有的代码,让需要同步的地方集中在一起,减少性能的损耗。

  这算是LZ从书中紧急领略的几个方式,今天LZ的应急方案已经正式上线,是否能顶住高并发还有待考量。不过LZ是领略了书中的一部分真谛才下的手,而非一时臆测,因此还是有一定把握的。(希望明早一上班不会被业务部门炮轰,0.0)

 

黄金屋的诱惑

 

  由于这次事件,LZ已经彻底爱上了这本并发编程(前几天还说爱上了深入理解那本书,有点花心啊)。这本书并不厚,才200多页,LZ用了一天半不到的时间看了80页,准备直接趁热打铁,等看完这本书之后,再继续深入理解和设计模式这两本书。因此最近的计算机系统原理系列可能要延迟一下了。

  本文写的十分匆忙(今晚其实刚加过班,0.0),因此难免漏洞百出,各位猿友如果遇到过类似高并发的问题,可以畅述己见,让LZ等一届屌丝得以一窥天机。时间已经不早了,各位猿友明早见分晓吧。

5
4
分享到:
评论
19 楼 一个java程序员 2013-11-21  
总是看到架构,架构。就说yahoo 提供的34条吧,  网上千篇一律, 没看到一个解决方法。

很无语。http 的各种头  谁能应用的随心所欲?
etag 这个玩意 ,谁在项目中用到了?

其他头呢?  没看到一个真实的有效的案例来使用这些。

html 和jsp 中的meta  中的头都有什么作用呢?  为什么没有一个人 有案例呢,不要那么吝啬啊  大神们。  谁能好好研究研究啊。

不要天天架构架构的,  一天到晚的意淫。有用吗?
如果分库分表吧。    用框架到是可以实现,  什么一致性啦,各种。
真是受不了。

再比如说吧,  一台机器上面,   apache+tomcat  集群  +负载均衡。 
网上千篇一律啊,  全都不能实现。 后来 我发现根本不能实现,必须借助虚拟机才可以。

人云亦云,真是误人。
18 楼 一个java程序员 2013-11-21  
大多数做javaweb的程序员都不会去考虑多线程编程.
yutaozxy 写道
大多数做javaweb的程序员都不会去考虑多线程编程.

中枪。 真的 ,大多数都不会考虑的吧。
17 楼 javatozhang 2013-11-21  
关注lz的解决方案,仅仅是泛泛而谈有些空洞!
16 楼 skzr.org 2013-11-20  
yutaozxy 写道
这种情况不要直接操作数据库,加上一个缓存层,效率提高很多的

非常同意你的观点。
不见楼主在缓存这一层的考虑,程序代码的性能提升总是不明显的(除非写得太烂了),而缓存层带来性能的提升一般是成倍的效果。
15 楼 yutaozxy 2013-11-20  
这种情况不要直接操作数据库,加上一个缓存层,效率提高很多的
14 楼 yutaozxy 2013-11-20  
大多数做javaweb的程序员都不会去考虑多线程编程.
13 楼 刷酷的高手 2013-11-20  
   
12 楼 xia5203166 2013-11-20  
呵呵 完全可以不考虑session  很多方案可以替代session 数据库嘛 不到淘宝的级别 完全可以考虑简单的hash或者分库分表 首先考虑 摒弃掉session共享 session共享是一个不明智的选择 然后考虑多站点 选择无共享架构
11 楼 神之小丑 2013-11-20  
越看到最后 越觉得是给那个什么书打广告。。。
10 楼 mfkvfn 2013-11-20  
基于session的统计完全不靠谱。session的有效期是大于实际使用的。1000个有登录一下,然后所有的人都不注销而是直接关闭浏览器,该怎么办。
9 楼 20131007 2013-11-19  
楼主的博客真多啊,博客园还有一样的文章,年轻人精力旺盛啊
8 楼 jimmee 2013-11-19  
估计是刚入职的菜鸟程序猿吧, 悲哀.
7 楼 heuzxl 2013-11-19  
牛人,能把情况讲详细一点吗,比如什么需求,多少用户,并发量是多少。前端部署集群是怎么部署的,集群的拓扑是什么样子的,怎么分发的。门户都用什么缓冲。数据库是如何优化,仅仅说并发,让我等摸不着啊
6 楼 jsnewland 2013-11-19  
不是混乱 是跳跃 楼主说的时候他眼前有一幅场景 只是你没看到
5 楼 ccccccc2003 2013-11-19  
是java并发编程实战吧,其实就是要把同步的锁粒度变小,以及对不必要加锁的地方clone的技巧,我说的可能比较轻松,不要见怪。学习到楼主的思路了,祝楼主系统hold住~
4 楼 sgq0085 2013-11-19  
做一个标记
3 楼 maoweiwer 2013-11-19  
好吧。。我表示完全不知道你想表达的是什么。。
2 楼 sootv 2013-11-19  
我很好奇LZ看的是什么书
1 楼 bewithme 2013-11-19  
楼主思维果然混乱,严重加班的后果。

相关推荐

Global site tag (gtag.js) - Google Analytics