集成的故事 - 性能

正如在“O/X Mapping的故事续集”中提到的,当你的系统如期上线,一切顺利运行,准备接受客户和领导的赞誉的时候,性能问题便一如既往地如期而至。原因很简单,你的系统做得太好了,人们是如此的喜欢它,热切地期望着亲自去体验那些激动人心的新功能,于是人潮蜂拥而入。附近停车场的纷纷爆满根本无法阻挡他们的热情,聚拢而来的人群把满载的地铁和公交车都挤得水泄不通,交通开始陷入瘫痪。然而,这些可怜的人们并不知道同样的事情在他们期待已久的系统中也发生了,网络和处理器都是100%的负荷,虚拟内存已经消耗殆尽,消息队列中的等待项目还在疯狂地增长。管理员开始发号施令,彪悍的门卫堵住了大门,漂亮的接待员把人群依次分组,耐心地向人们解释为什么他们只能分批进入系统。于是,性能监视器上的曲线慢慢平缓下来,队列中的消息还是一条条地不断被处理,每个事务的状态也在按部就班地发生着变化。监控室里的IT人员终于松了一口气,沾沾自喜地向他们的经理汇报,看,我们的系统还不错吧,虽然会变慢一点,这么高的负荷还能稳定运行。直到一个用户尖叫起来,我刚刚输入的数据找不到了;旁边一个用户还惊讶地发现,他个人信息页面上的大头相竟被换成了他们家小狗的照片。这些平时看起来不可理喻的问题,在高压力下不可理喻地发生了,这些问题是如此的偶然,而且无法重现,却总在你不注意的时候突然冒出来。开发和测试人员提出各种猜测和可能的办法,试图绕开这个问题,但就像敲鼹鼠的游戏一样,棒槌落在一个洞口的时候,鼹鼠又从另一个洞口冒出来。无奈的是,事先精心设计的性能监视器和日志系统里面,都无法看到这个问题,每次报告问题的都是那些你曾经的最忠实的用户。直到有一位耐心的工程师打开一页3年前写的并经过3000轮测试的代码,才发现里面生成ID的算法在复杂的并发线程环境下会出现ID重复。更可怕的是,包含这个算法的组件,已经在30000个终端上运行。。

很遗憾只能使用这种墨菲式的开局,毕竟自古行文都讲究个不破不立,而且要破也要走极端,弄得有点危言耸听,矫枉过正,否则你的观点就不会得到足够的重视。正如性能问题一样,尤其在项目刚开始的时候,迫于功能和进度上的种种压力,很多技术取舍和设计考量都会把性能暂时放在一个次要的位置。对一般的业务信息系统来说,很多人常常会牺牲性能来换取更灵活的体系结构以应付需求的频繁变化,性能通常被认为是在项目后期或者实施的时候,通过系统软件的调优和硬件的升级可以解决的问题。这有时的确无可厚非,但对于集成系统,情况可能跟这些特定的业务系统不太一样。比如PACS主要需要关注大数据量传输的性能和可靠性;RIS需要关注工作流和业务状态控制;收费系统需要关注交易的完整性。而所有这些问题,在集成系统中都可能会碰到。因为集成系统是为这些业务系统服务的,所有这些业务系统的需求会或多或少的投射到集成平台上,最后要求集成平台做成三头六臂,无所不能。比如,尽管你的集成平台是基于异步消息实现的,用户硬是需要同步操作的时候,你也不得不通过等待一个消息往返来进行等效,类似的机制也可以支持工作流定义,分布式事务等等。我们再往前一步,当所有这些工作你都可以做到近乎完美,所有业务系统都依赖于你的时候,你就得考虑自己会不会成为整个系统的性能瓶颈了。相信在很多关于SOA的文章里面,只要讲得足够深入,而单不是摆弄一些蛊惑大众的概念,都应该会提到如何来提高ESB数据吞吐能力的一揽子方法。然后就可以对一些很小的技术问题也要搞出一套计划-分析-实施-反馈的过程模型来确保你不会出什么差错,还有一堆的checklist去检查你在这个小问题上的能力成熟度,最后还美其名曰这是一种充分考虑到各种技术风险的基于墨菲法则的设计。

---

我们这里不需要这么复杂,下面一些方法可能不系统不全面也不够专业,但慢慢积累,留备今后吹牛之用,还是值得总结一下的。这些方法的前提是系统功能是坚固可靠的,比如代码里不存在象上面那样的线程安全问题(尽管这个问题可能在系统处于某种性能状态下才会出现)。这些问题应该是用其他的软件工程方法来防范,而不是下面这些方法所能解决的了。下面的方法所能解决的问题的典型表现就是系统功能正常但是运行得很慢,比如一条消息从一个系统要过很长时间才传到另外一个系统。

要处理性能问题,当然首先要识别性能瓶颈,这时候日志以及相关的监视系统就是你最好的朋友。这听起来好像有点亡羊补牢的味道,为什么我们不能在需求或者设计阶段先验地预防性能问题呢。如果你有足够的基于事实的经验,这当然可以,最可怕的是在项目的初始阶段,根据自己的想象或者过时的经验,而且没有经过充分原型试验,武断地臆测出性能瓶颈,导致设计偏差,劳力又伤神。与其这样,还比如在关键的地方,主要的业务逻辑判断和需要大量计算的步骤前后加上写日志的代码,以便你在测试(尤其是单元测试)中尽早发现性能问题,如果单元测试发现不了,这些日志在后面的系统测试和压力测试中也会起到很大作用。但正如前面例子里说的,有些时候日志里并不能看出什么问题。不要难过,不要彷徨,更不能随意怀疑和猜测,赶紧回去改代码,在你曾经随意怀疑和猜测过的地方都写上足够多的日志,必要的话每个逻辑路径/角落都加上日志,然后再运行,你就会很快发现问题。因此,为了让日志真正发挥作用,下面的一些实践可能会有帮助,尤其是排在前面的那些。如果说解决性能问题能有什么先验的方法,这些可能是最实在的了。

- 在关键日志加上时间戳,如果条件允许,每行都加,而且时间的精确度能满足你的需要。
- 在关键逻辑路径上写日志,便于看日志的时候确定某个事件在逻辑路径中的位置,在调试的时候,根据需要可以增加日志的详细程度。
- 如果有不同的模块或业务功能,可以根据需要对日志进行分类,可以在每行日志中用标记区分其类型,或者放在不同的日志文件中。
- 对于并发事务的记录,日志不要求事务上的连续和完整,但时间上必须连续,每行日志要包含所属事务的ID。
- 在任何的系统间接口部分写日志,详细记录双方通信的关键内容。
- 把尽量多的异常,最好是所有能捕获到的异常,都记录到日志里面。
- 写日志的时候也会有异常,需要想想怎么处理这个异常。
- 运行时日志会不断增加,需要设计一个自动化的日志管理机制。
- 用级别区分不同严重程度的日志,维护时比较有用。
- 为了便于分析,可以用报表和图表可视化地显示日志。
- 为了提高并发性或便于远程控制,可以设计异步的日志机制。

除了日志以外,有时你可能还得写一些程序,比如做一些特殊的工具出来进行测试,才能找出性能瓶颈。作为一个严谨的工程师,这些工作会比臆测花费更多的时间,但却是非常值得的。当然,真正决定做这些耗时费力的事情之前,先沉住气,一个人或者几个人一起,好好读一读有嫌疑的代码,可能会更快地发现问题,然后就可进行试验验证加以确认。重视代码,以及写代码的人,永远是个好习惯,不管你是工程师还是管理者。

---

当然有人会追问,怎么才能知道哪些代码有嫌疑,那就看你自己的经验和对系统的了解程度了。也许多年以后,会有一本书叫做,性能瓶颈的几大罪状,把常见的性能问题整理成模型供大家膜拜。但在这之前,有一个最简单的事实,就是只要有高进低出,就一定会阻塞,这跟堵车和洪水的原理完全一致。比如在集成系统中,一个消息从一个数据库到另一个数据库需要经过好几个队列,好几个接口,那你就依次打开每个队列的数据和每个接口的日志,从这些记录中可以查看相邻两条记录的时间差,从而得知其数据传输速率,挨个比较这些速率,便可得知数据在哪个地方出现了拥堵。

---

高进低出的事实,很自然地导出解决性能问题的两类办法,减低入口速率和提高出口速率。这里的速率是指单位时间内的数据流量,因此速率的调控又可以从控制总数据量和提高时间利用率两方面着手。对于后者,又可以用空间换时间,既把并行操作分摊到多个计算单元上进行。这样说比较抽象,有忽悠人的嫌疑,下面具体化一下,主要针对集成中最常见的异步消息系统,希望以后还是多发现一些类似的具体技巧和方法,而不是一堆抽象的概念和理论:工程师的头脑往往就是这么的庸俗。

- 为了减低入口数据流量,你可以尽可能地减少不必要的数据进入队列,比如某个系统往队列里提供了其他任何一个系统都不需要的消息。
- 如果你的集成接口是用轮寻的方式从某个系统获得数据输入,缩短轮寻的时间间隔可能可以稀释一下数据流量,避免一次查询突然返回太多的数据导致数据拥堵,在数据出口也可以采用类似方法。
- 操作数据库的时候,尽可能在一次查询中批量访问更多的数据,而不是一条条记录地访问,当然也不能一次访问太多,因为数据库一般都有查询超时时间。
- 在超时时间方面,要给自己留下足够的余地。现场网络的数据吞吐量往往难以预测,理论分析和实验室结果只能给出超时时间的一个常规值,这只是你的默认设置,并允许现场人员设定更长的超时时间,在严酷的性能环境下也能确保数据通信的完整。
- 当你尽可能地做了很多软件上的调优,但是用Windows的性能监视器看到CPU,内存,网络都消耗殆尽的时候,就可以考虑升级硬件或者用多台机器并行地工作。

更多关于性能问题的解决办法,还可以在程序员杂志上一篇关于MySpace网站的文章里找到。不过工程上的很多办法都是针对特定场景的,只能借鉴并获得启发,却难以复制和推广。那些能用普适办法来解决的问题,一般都可以借助现成的工具了。事实上,最普适的办法还是组建一个高效的团队,遇到问题的时候,有人跟你一起讨论和分析,以上的一些办法也是大家的成果,而且可操作性还算比较强。还有一个办法,也是大家的成果,但不知道什么时候才能实施了。

---

国内医院的高峰时段大多在每天上午10点左右,每周视医院性质不同可能在周一左右,这个时候整个医疗信息系统都在高负荷运转,能平稳度过这个时段的系统,才能算是真正符合中国国情的系统。如果有性能方面的问题,也常常在这个时间发生,因此大家查问题也只需要关注这段时间的日志即可。为什么我们不能象疏导交通一样,把病人流量分摊到其他时段去呢。原因很简单,病人如果下午来就诊,可以避过高峰,但却挂不上号了。众所周知的看病难,实际上这就是病人和医生之间的一种高进低出。就跟房地产商捂盘一样,拥堵的经济学结果就是价格的提高,这里的价格涨幅还没有考虑见不得光的那一部分。于是大家提出小病到社区,大病到中心,社区中心双向转诊。如何实施呢,很多方法,很多人会得益,不少人也会受损,最后能实施得如何呢,让我们拭目以待。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值