-
Notifications
You must be signed in to change notification settings - Fork 218
About
HouseMD
的诞生并非一次艳遇的产物, 而是一个酝酿了两年的结晶.
日期: 2010-04-06 关键字: TimeTunnel2
2010年我开始参与TimeTunnel2
的开发, 目标是为全网日志提供可靠的收集分发渠道, 其架构与消息中间件非常类似.
TimeTunnel
是原阿里妈妈用于日志收集的系统, 2010年TimeTunnel
团队加入到我所在团队后,TimeTunnel
开始了2.0
的开发, 简称TimeTunnel2
. 同年底,TimeTunnel2
在淘蝌蚪上发布开源.
当时我在网络服务器开发上经验尚浅, 加上单元测试不太能覆盖持续高负载下暴露的诡异问题, 一旦问题出现了, 还是要依赖打印的日志来可视化服务器的行为和状态, 再进一步分析原因, 找解决办法.
为什么不用断点调试? 确实, 在自己的开发环境中, 系统与外部的交互是自己可控的, 断点调试是首选. 但在交互变得频繁, 复杂, 不可控, 又是多线程并发的情况下, 断点调试不是那么容易. 最关键的问题还是, 断点意味着线程阻塞, 有些问题是在高负载的情况才会出现的, 用了断点问题就无法重现了.
我很反感在代码充斥着各种DEBUG
日志, 它们会使得代码看上去不是那么干净, 干扰关键逻辑的阅读. 可是问题来的时候, 没有它们又没有其他更好的办法, 为此我每次都要纠结于要不要在这里或那里写上一段打印调试的语句.
为了不让自己再纠结下去, 一定要有个一劳永逸的办法, 我想到了AOP
.
大部分关于AOP
的资料中都会以日志作为其典型应用场景, 显然实现它是不难的. 综合考虑后, 我在TimeTunnel2
中使用Google-Guice
实现对所有被管理对象的所有方法切面增强(即方法进入和退出进行"日志埋点"), 并提供一个配置接口, 以限定需要输出调用调试日志的方法范围.
这样做了之后, 代码清爽了不少. 在开发环境调试的过程中, 也很方便的通过修改配置, 来实现按需输出方法调用日志. 后来, 为了方便生产环境中快速调试, 借助JMX
实现动态修改配置的接口, 不错很先进.
爽了没多久, 便发现一些问题:
- 日志埋点的对象太多, 一些对象频繁创建会带来性能上的损耗
- 输出的内容(如参数值, 返回值)的范围和格式不能灵活调整, 还是得修改代码, 重新编译
- 能够显示的信息还是太有限了
日期: 2010-11-11 关键字: BTrace
, TimeTunnel2
, Hadoop
同年11月, 我看到公司牛P毕玄写的一篇博客, 是介绍了BTrace
的, 看后惊呼"神器出现"! 因为它改变我以往调试程序的思维方式, 强大的脚本定制特性, 驱使我欣喜若狂地研究它所有的范例, 心想着TimeTunnel2
线上诊断调优就全靠它了.
毕玄(花名), 真名林昊, 网络ID是
bluedavy
. 他是国内OSGI
第一人, 加入淘宝后 成为淘宝3.0
架构的核心人物之一, 公司内外技术影响力强大. 他是将BTrace
引入淘宝的人, 此后还写两篇博客分享了使用BTrace
解决问题的案例.
不负众望, 在BTrace
帮助下我解决不少实际问题, 为此我还将BTrace
和常用脚本作为TimeTunnel2
发布包的一部分, 这样部署到生产环境后, 用起来就很方便了.
这里不得不提一下BTrace
的一个更有分量的成功案例. 当时, 淘宝Hadoop
平台的应用已经上了规模, Hive
的引入大大提升了离线数据分析作业的开发效率, 每日剧增的作业量和数据量, 使得本身已是集群性能瓶颈的NameNode
每况愈下. 我们的Hadoop
技术专家周忱想到了BTrace
, 编写了一段脚本在作业高峰期的时候收集NameNode
内部调用的性能数据, 这些数据指导了后续优化方向, 并且收效喜人.
周忱(花名), 真名周敏, 网络ID是coderplay. 2009年当时还是实习生的他, 就已经成为淘宝第一个
Hadoop
平台的核心人物, 在构建基于Hive
的数据仓库平台上, 他的贡献也是至关重要的.
日期: 2011-08-15 关键字: BTrace
, Hadoop
, ADFS
2011年, 我的工作从TimeTunnel2
转移到了TBFS
的开发上. 历时大半年的开发, 为了确保平滑上线, 我们基于社区的测试用例做了很多功课. 但直觉告诉我, 一旦上线肯定还会有我们没有预想到的问题. 产品永远不可能完美, 即使如此也不能放任问题不管. 试想, 要是我们能缩短发现问题到解决问题的周期, 降低问题影响面, 这也是相当值得做的一件事情.
TBFS
是淘宝自主研发的NameNode
的HA
方案, 现已经更名为ADFS
(Ali Distributed File System
), 现在也已开源在Github.
我最先想到的还是BTrace
, 它的强大已无需再多言, 可是用过的人, 应该都会有这样一些经历:
- 修改脚本时拼写错误导致代码校验失败, 只得改好再来;
- 修改的正则表达式匹配的范围过大(或小), 得调整调整再来;
- 打印输出的信息不够, 改吧;
- ......
每多一次反复, 可能十多秒或半分钟就过去了, 不知不觉就错过了发现问题的最好时机. 编辑器一开一关, 一天就过去了.
当然, 如果是经验足够, 事先准备好一些常用脚本模版, 配合动态语言, 倒是可以加快一点速度. 呵呵, 要想把
BTrace
玩得出神入化, 还是有些门槛的.
另外, BTrace
有个让我不能接受的问题, 就是每次退出后, 它所增强过的字节码是不会被还原的, 这意味一旦某些消耗性能的脚本被应用后, 除非目标进程重启, 不然它们依然还在那儿起作用.
直到写本文为止,
BTrace
的最新版也未解决这个的问题, 不过最近的源码显示他们有解决的办法啦, 敬请期待吧.
不过, 还是有个奇淫技巧可以实现不用重启进程也可以让上一次的增强失效的办法, 就是准备一个脚本里面只有一个空方法, 但一定要保证脚本被应用的范围要覆盖上一次的, 然后用这个脚本
Attach
目标进程, 成功后立即结束, 就达成了. 原理这儿就不细说了, 这不是技术贴.
下一步, 就是怎么改进BTrace
了. 本以为动手写个Patch
就可以搞定的, 但一番研究后, 发现这其实是脚本灵活机制的代价. 看来我得依着它这个葫芦画个小瓢出来啊.
两周后, 我写了一个Demo
验证了自己动手的可能性, 这为后来的HouseMD
打下关键的基础.
这个
Demo
我放到了Github上, 非常适合对其中原理感兴趣的人研究一下.
日期: 2012-06-13 关键字: HouseMD, Notify
令人遗憾的是Demo
写好之后, 我并未一蹴而就的完成一个实用的版本, 因为一些事情就搁置了.
一晃10个月过去了, 我的工作一如既往的又转移了, 现在是加入到Notify
的团队.
Notify
是淘宝2009年自主研发的消息中间件, 一直沿用至今, 其地位比肩各大核心业务系统.
Notify
是连接各大核心业务系统的信息管道, 由于其系统环境的复杂性, 加上消息异步传输的特点, 使得业务系统在开发中诊断调试问题的难度较高. BTrace
仍旧在其中扮演重要角色, 正如前文所述, 改进BTrace
是非常值得做的一件事情. 于是, 这驱使我两个月前开始继续之前未完成的任务.
4月30日, HouseMD
内部仓促发布第一个版本0.1.0
, 由于并没有解决BTrace
最痛的问题, 而且在复杂的容器环境中还会导致目标进程运行异常, 我保持低调立即投入0.2.0
的开发.
一个月后, 我重写了大部分的代码, 加强了测试, 引入了可交互的特性以加快诊断问题的迭代过程(改变了BTrace
的诊断模式), 还在易用性上花费了些心思, 0.2.0
发布了!
乘热打铁, 我鼓足勇气在微博上@了一群公司的牛P们帮我推一把(这里真心的感谢他们), 反响远远超出了我的预期. 当天, HouseMD
就跻身Github上Scala
这个语种下当日被Watch
和被Fork
的双料榜首. 这让我动力百倍, 面对网上随之而来疑问和建议, 迅速在接下来的两周, 依次发布了0.2.1
和0.2.2
.
HouseMD
现在被Watch
的人数已经过百, 但我依然感觉有遗憾. 开发HouseMD
的初衷仅仅只是为了方便自己, 但过程中意识到它应该能帮助到更多苦逼在一线的程序员, 可惜我一个人的力量是有限.
我一个人无法让HouseMD
像Java
一样跨平台!
我一个人无法让HouseMD
在每种特定应用场景下都能用着很方便!
我一个人无法让HouseMD
没有任何Bug
!
我一个人无法让HouseMD
......
我希望HouseMD
不是我一个人的HouseMD
, 而是所有工作在Java
平台上的工程师们的HouseMD
!