出自架构师的架构师的源代码里的注释:”相信我!“

jopen 11年前

相信我!

        普瑞特有幸争取到了为一个架构师的架构师工作的机会。这位架构师的架构师能够设计出功能更强,性能更佳,比任何其它设计更优的系统。任何出自这 个家伙之手的设计或编码,跟其它任何人设计的相似的组件相比,跟任何地方已经有了的相似系统相比,都会具有更全的功能,更强的能力,更坚不可破的性能。无 人能企及。

        回溯到我们要讲的这个系统的设计之初,架构师的架构师命令说这个系统的通信机制将采用 JMS 消息传送。并且,要准备两个队列;一个传送普通消息,一个传送高优先级消息。其它应用软件对这个新系统的服务的要求是,普通优先级的消息,系统收集后批量 处理,高优先级的消息在用户间直接传送。这个两个消息队列的活动情况都受应用软件的监控,但高优先级的消息能跳到队列的最前面以达到最快的响应。还有,由 于这个系统将要去替代的系统是长久以来以 bug 多多和稳定性极差而闻名,所以,这些新系统必须要刀枪不入。它绝对不允许宕机。

        当普瑞特接受培训了解这个系统时,他问架构师的架构师,当如果有这样或那样的错误发生时,系统会做什么响应?

        架构师的架构师高傲的宣称,绝对不会有任何事情能导致系统宕机。没有任何错误能阻挡它运行。没有任何情况能使它失去控制。它是无可阻挡的。它会绝对可靠,直到最后一分钟。你要相信我!

        普瑞特明白这位架构师的架构师对自己深信不疑。然而,事情并不是总会按计划运行。

        一天,普瑞特接到一个负责监控这个系统运行的人的电话:“你们的这个系统的日志体积增长出现异常。你们的系统在过去 24 小时里产生了以前一个月才会有的体积量,系统负载上没有特别的增长;请检查一下。”

        普瑞特登录生产服务器,发现了一排排按序号排列的日志,每个日志文件都有 20GB,全是这一天产生的!没有任何编辑器能打开这样大的文件。办法只能是用grep搜寻里面的异常。异常多的如火山汹涌。看起来系统会每秒钟吐出数百次异常事件和堆栈信息。用tail获取日志尾部片段,显示所有的异常都相同:“无法访问队列:队列控制器似乎已经停止运行。”

        不幸的是,队列控制器并不认可这种说法;它很健康,并在处理着消息。

        与此同时,客户对系统性能的抱怨不断升级。经理跑过来询问怎么回事。耳朵在冒烟。眼睛在喷火。普瑞特感觉到死神正在上面盯着他。

        进一步调查显示,虽然有一部分应用的实例在不断的出现并抛出大量的异常,但有些却在顺利的收发信息、处理数据。

        深挖之后,普瑞特发现处理消息的外层代码是这样写的:

    Connection          conn;                    // injected via Spring        Queue               receiveQueueNormal;      // injected via Spring      Queue               receiveQueuePriority;    // injected via Spring      ...        Session session = conn.createSession(true,Session.SESSION_TRANSACTED);      MessageConsumer consumerNormal = session.createConsumer(receiveQueueNormal);        MessageConsumer consumerPriority = session.createConsumer(receiveQueuePriority);      ...        while (true) {    // AA: This will never fail: trust me!         try {               Message msg = consumerPriority.receiveNoWait();                 if (msg == null) {                   msg = consumerNormal.receiveNoWait();                     if (msg == null) {                       continue;                     }               }               // process the message here         } catch (Throwable t) {              log.error("...",t);         }      }

        进一步在队列配置文件里发现问题:

<policyEntry topic=">" producerFlowControl="true" memoryLimit="1mb">

        当消息的体积很小或消息很少时,这段代码会呼啸的运行,它能每秒钟检查无数次队列看有没有消息可处理。

        但随着业务的增长,当消息的体积增长到某种程度,消息控制器就会耗尽内存,结果就会放弃一些消息,但并不是放弃所有的连接(可能是采用了自我保 护模式)。这个系统——设计和开发都基于不会出现意外情况的假设——仍然在快速的最大限度的利用着 CPU,但现在却因为无法和队列管理器取得联系,每个循环都会抛出异常日志信息。

        没有重新获取连接的代码。没有让连续相同的日志错误信息做合并延迟输出。没有邮件发送给支持人员说“不好的事情发生了!

        出自架构师的架构师的源代码里只有一句孤单的注释:”相信我!“        

英文原文:Trust Me!