对于程序员来说,我一直认为代码是展示能力的关键。很容易看出优秀程序员写的代码和普通程序员写的代码的区别。代码是展现程序员硬实力的一张名片。如何提高写代码的能力一直是一个重点话题,可惜本文不讲具体步骤、灵丹妙药、武功秘籍等,大大提高写代码能力的4条经验,不妨参考。第一段:第一次体验亿级系统天天挑战。2008年,HSF第二版在当时淘宝最重要的交易中心上线。上线当天,淘宝网站访问异常缓慢,交易页面几乎无法访问。打开,最后还是靠离线HSF来恢复。下线后,我开始排查问题。HSF的第二个版本基于JBossRemoting。目前版本的JBossRemoting,代码中写了远程同步调用的超时时间是60s,调用的服务确实有一些超过10秒左右的现象,导致web应用的线程池无法处理web请求逐渐被这些慢请求占据,请求越积越多,最后页面打开非常慢。查明原因后,当时决定基于Mina重写整个HSF通信。两个月的重写,无论是对网络IO处理的深入研究,还是对高并发系统的深入研究,都大大提高了我写代码的能力。现在想想学习的方式,就是看各种网络IO科普资料,然后看Mina和Java网络IO的源码。并发的学习主要靠经典的《Java并发编程实战》和阅读JavaJ.U.C中的代码。这段时间的学习和之前的翻车《Think in Java》最大的区别在于,学完了,就付诸实践了。随着HSF新改写版本的上线,我也基本逐渐掌握了这些部分的编码能力。除了代码能力的提升,我学到的另一个最大的教训是,对于一个亿级、长时间运行的系统来说,很多看似小概率的问题,肯定会变成大问题。这也是高并发系统难写的原因。需要非常清楚自己写的代码和代码调用的各种API中的实现,这样才能真正保证最终代码的健壮性。第二段:民间“救火队”的故事第二段大大提升自己代码编写能力的经历是在民间“救火队”的日子。2009年淘宝出现了很多故障,但没有一个标准的系统和组织来处理故障。结果出现了很多故障无人处理,或者处理效率不高。所以当时运维组的一个同学拉了一些人组了个群。团名是淘宝救火队,用来处理淘宝的各种故障。我也是机缘巧合加入了这个群。还有一个全阿里公认的超级科技大神:多龙。刚开始看到各种失败,不知如何下手。处理故障通常不仅需要编写代码的能力,还需要对系统的全局有一定的把握。比如几年前特别火的一篇文章,点击搜索背后发生的事情,其实就是要特别熟悉一个系统的处理流程,这在处理故障时非常重要。知道了故障出在哪个环节之后,控制这个环节的代码运行机制的细节就很重要了。这时候使用各种工具通常就显得非常重要了,可以有效的帮助你知道发生了什么,比如系统层面的top-H,Java层面的BTrace等等,都可以让你根据运行情况来定位问题。这段时间,我觉得自己的进步靠的是大量的练习。确实有很多毛病。一开始是靠别人的处理方式,主要是向多龙学习,然后尝试自己解决一些故障。解决的问题越来越多,熟练度也逐渐提高了。除了提高解决故障的能力之外,由于我看到了很多代码层面导致的故障,对我在写代码的时候更好的保证健壮性,避免故障也有很大的帮助。比如我见过很多因为滥用线程池而创建大量线程,最终导致线程无法创建的情况。我会理解,在使用线程池的场景中,最大数量必须控制的非常明确,包括入栈策略等等。再比如,我见过很多自增容数据结构导致OOM的案例,理解写代码的时候不能假设数据结构不会增长到超大,所以没有case对于任何保护。这期间让我体会到的是,写出一段可以运行并满足要求的代码并不难,但是要写出一段可以在各种情况下长期稳定运行的代码,真的不容易。我觉得这是专业写商业系统的程序员和只写程序找乐子的程序员最大的区别。第三段:重写通信框架2010年离开中间件团队去做HBase。当时HBase中的通信实现方式非常简单。想着把HSF用的东西移植到HBase上。这时多龙正在用C写一个通用的通信框架libeasy,用于各种C应用,于是就有了测试。记得第一次从这个测试的结果可以看出,原来HSF中通信框架的高并发能力与libeasy有很大的不同。我跟多龙讨论过他是怎么实现的,我看看能不能学起来,在Java版本改一下,所以就有了这次重写通信框架的经验。本来以为自己在写HSF的这些年里,已经很好的掌握了通信框架的代码相关能力。在用多隆改写的过程中,发现还是有很大的差距。多隆教会了我很多细节。基于NIO的通信框架的核心是使用极少的IO线程来处理IO事件(太多了也没用,因为有些部分只能序列化),那么如何高效的使用它们呢,这些IO线程是非常关键的。我们应该尽量减少这些IO线程来处理一些不相关的动作。还有一点就是尽量减少IO线程和业务处理线程之间的切换。一次向业务处理线程抛出多个请求。这段经历非常有助于我对代码逻辑的整体细节有更深入的把握,这对于编写要求高的系统非常重要。毕竟对于一个超大规模的系统来说,1%的提升还是很可观的。第四段:在学习JVM之前,因为要处理的fault比较多,开始和公司的同事分享了一段时间如何处理fault,后来发现有些问题我解释不清楚,或者我不知道怎么对付他们。我必须深入学习JVM,但其实一开始想不通,打开JVM代码的时候不知道从何下手。幸运的是,我遇到了一个同样热爱JVM并且比我优秀很多的同学,那就是Sakya,圈内通常叫R。我和Sakha约好几个周末一起在公司看JVM代码。在Sakha的指导下,我终于入门了,也知道怎么读了。而且我们两个人一起看代码,互相分享和讨论,效率非常高。高的。有了这段经历,再加上不断处理一些失败,基本上对JVM的代码实现有了更深的理解。后来在做故障分享和问题解决的时候,终于能更好的理解这是怎么回事,为什么。同样,这对处理故障的能力和编写代码的能力也很有帮助。比如你会更加理解之前认为的所谓GC-friendly代码的含义。我还有一个更深的感受,那就是其实Java代码通常不会写的太烂,因为JVM在运行时会尽可能的做很多优化,拉到平均线,但是要写的好,难度非常大,因为需要了解JVM和JVM下的OS。其实也没什么好总结的,因为每个人的环境不同,适合自己提升的方法也不同。我总结了自己的经验,我认为:如果环境不适合,给自己一个命题挑战。比如你想学习高并发通信,你可以试着自己写一个跟别人对比一下,做性能PK。这通常会改善很多。学习GC,可以尝试给自己出几个问题来控制GC的行为等等,如果环境可以的话,确实会更有好处。向优秀的程序员学习更多。我自己也从多隆和萨迦身上学到了很多。我也从很多优秀的开源代码中学到了很多,比如Netty、OpenJDK,所以参与一些优秀的开源项目也是一个很好的提升途径。《Oracle JRockit: The Definitive Guide》、《深入理解Java虚拟机》等),也是向优秀程序员学习的好方法。多次尝试解决问题/故障。这绝对是一个非常好的提升自己代码综合能力的方法。如果你的工作机会不多,网上有很多平台,比如StackOverflow,都是很好的练习场。最后还是想说,代码能力作为程序员的硬名片,永远是区分程序员能力最有效的东西。“说话便宜,给我看代码”,我觉得这句话永远是对的。
