相信我!

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

回溯到我们要讲的这个系统的设计之初,架构师的架构师命令说这个系统的通信机制将采用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! ]
分享这篇文章:

8 Responses to 相信我!

  1. camelwoo says:

    我没太看懂,什么是“架构师的架构师”?

  2. Lewis says:

    Architect 只能翻译为 架构师?
    感觉如果翻译为“架构师的架构”会跟好理解。

  3. David says:

    架构师的架构师 ………………

  4. 忧郁 says:

    我以后也写这种代码,真他妈的神奇

  5. wsmithril says:

    竟然是从TDWTF上的来的文章。强烈推荐TDWTF

  6. Lewis says:

    另外给楼主的建议是,中式英语的对立面就是西式中文,翻译不仅仅是逐字替换,语法和修辞也必不可少,英语的表达方式没有必要直译,换成更通俗的中式语法会更好。

发表评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据