回顾过去看IaaS的Next

IaaS层经历了多年的发展,这里也只能以我自己所经历的来进行回顾,之所以要回顾,是为了通过过去的发展,来看这个领域发展的动力,从而更好的创新,引领未来。

物理机->虚拟化阶段


阿里大概是在2010年开始用Xen来做虚拟化,推动这件事的是另外一位同学,问了下他,当时推进这件事最大的动力是两个,一是资源管理方式,在虚拟化前,都是直接用物理机,物理机的规格会不同,这会导致在LB上配置起来非常麻烦(我印象中记得以前我们在LB上开启权重,导致了一次严重故障,后来就不太敢用了),另一个是成本,站在外围,我看到的最主要是成本,不过说实话,以当年阿里的机器规模而言,尽管通过虚拟化把1台物理机虚拟成3个虚拟机,节省的机器比例看起来是非常高的,但由于盘子就这么大,所以这点成本在当时很难成为推进演进的关键因素,但资源管理方式那个确实是个推动的非常好的动力,因为那个是会影响稳定性的。

这件事我印象中当时的推进还是比较顺利的,主要的原因应该还是虚拟机和物理机还是非常像的,当时因为虚拟化这件事推进,我还写了淘宝当时比较统一的一版Java应用启动参数,后来在进展了可能两年后,阿里尝试把Xen换成KVM,但当时上线碰到了些问题,后来就没去尝试了,直到后来阿里云做虚拟化,阿里在虚拟化的技术掌控能力才真正的开始变得非常深入。

这个阶段的演进动力主要是为了更好的屏蔽机型不同,资源归一化,次要的是成本,现在的云用虚拟化最主要的还是为了提供多种类型的资源规格。

虚拟化->容器化阶段


2011年,我看了《Web容量规划的艺术》这本书后,觉得运行成本对于一家公司是非常重要的,从自己的技术角度来看,降低机器数是一个有效的方法,于是就去想有什么办法可以降低机器总数,找人拿了机器的一些数据后,看到机器的整体利用率是非常低的,于是想既然一虚三利用率还很低,那能不能在一台机器上跑更多呢,了解了下,如果用虚拟化的方法的话,内存超卖不好弄,所以就得找另外的办法。

和多隆说了这个想法后,多隆也很感兴趣,于是就来摸索有什么办法,最早的时候尝试了直接在物理机上跑多个业务进程,结果碰到了各种冲突的问题,例如典型的监听端口冲突,更麻烦的是运维,因为出问题了,不知道哪个应用,查起来特别麻烦,于是觉得直接跑进程不行,还得有一定的隔离性,这个时候尝试了各种黑科技,例如自己改sshd、各种命令行对应的背后的函数,确保可见的隔离性,但这个方法的最大问题是无法穷举,所以总是有各种问题。

突然有一天多隆和我说有个叫Linux Containers(LXC)的东西,好像可以很好的满足需求,于是开始试验,基于LXC包装了我们自己的代号叫T4的容器,我们把这个东西改造的和虚拟机特别像,对于用户来说登录到T4的容器,所有的感受和虚拟机几乎是一样的,这个方案从落地执行角度来说就比较好推进了,毕竟对用户来说几乎是无感的,并且到了2012年,机器资源的申请也变的比较紧张,T4可以用更少的物理机提供更多的“虚拟化”资源,比较受用户的欢迎,到了2013年,交易的核心业务开始切换到T4后,后面的推进就越来越快了,于是阿里就此迈进了IaaS层主体是容器化的时代。

这个阶段的演进动力主要是对规模化后成本控制诉求的预判。

容器化阶段->容器+Docker镜像阶段


2015年,Docker火爆,我们也开始尝试将Docker的镜像+T4的容器进行结合,在这个尝试的过程中,我们切实的感受到了容器+镜像化给运维带来的巨大改变和帮助,这里要多说几句,当时我们对Docker的镜像机制能带来多大帮助一直存有质疑,争论非常大,所以从这件事来看很多东西还是得试试才知道,对于应用而言,在没有把容器+镜像结合起来以前,部署方式通常都是先申请机器资源,然后在机器资源里部署应用,但应用由于有各种语言、架构,所以部署的方式通常会有很大的区别,这个时候对运维类型的系统就非常复杂了,但容器+镜像这种方式使得交付应用这个过程标准化,把交付的这个概念从分离的机器资源到应用部署这两个过程合并了,这对实际业务而言才是更加合理的,有了容器+镜像这种方式后,运维的变更就可以用一套统一的运维平台来标准化了,当然,这也不是Docker首创的,Google家很早前就是这样,但可惜Google当年没开源,导致镜像的标准化现在基本是Docker的格式。

容器+镜像这种站在交付的最终产物诉求的思想延伸到了后来接下去的一些产品的进一步创新中,例如Terraform、Helm等。

这个阶段的演进动力主要是更好的满足交付物的诉求,而这种的结果就是在下层的东西会越来越不可见。

容器+Docker镜像阶段->统一调度阶段


这几年阿里除了在继续推进容器+镜像化(这个产物已经开源:PouchContainer)外,另外一个很大的演进是推进统一调度,推进这个的诉求主要是成本,容器化后可以看到机器上就算能运行更多的容器,但成本下降的还是不够,因此继续进一步看,非常显然的问题还是资源利用率不够高,在做T4的阶段,就听说了Google的Borg,Borg最重要的是通过把资源都归拢在一个池里,并且通过在线任务和离线任务部署在同一台机器(混部)上来大幅提升资源利用率,统一调度可以用一个非常简单的指标去评估做的怎么样,就是平均的资源利用率,Google家大概应该在50%,阿里目前开启了混部的集群一个月下来的CPU平均利用率大概在40%上下,这个阶段的方向是非常清楚的,但要做到这样的程度,对基础设施、内核的改进、调度系统的建设都有很高的要求。

这个阶段的演进动力主要是成本的诉求。

IaaS的Next


以上的各个阶段的演进的具体技术细节在阿里系统软件的公众号里都有分享,感兴趣的同学们可以去找找看。

回顾上面几个阶段的发展,我们能够看到,IaaS的发展/创新主要有两个非常明显的点:

  1. 成本IaaS层随着规模的不断增大,成本的优化动力会越来越大,从目前的状况来看,怎么更好的优化资源利用率仍然是IaaS层技术创新的核心动力,这个对于云厂商而言,一方面是优化自己的利用率,另一方面是给用户更好的提升资源利用率的产品;软硬件结合也是目前看到的另外一条很好的路径。
  2. 被屏蔽从物理机->Xen/KVM->容器->K8S/Terraform/Helm,可以看到非常明显的趋势是IaaS越来越被标准化接口屏蔽,未来上层会越来越不关心IaaS的这个具体的运行单位是什么(但始终会需要安全、资源的隔离性,至少是可见的隔离,以及越来越强调的启动速度),从目前的状况来看呢,具体的运行单位在3-5年内应该还会是容器,但容器下面是什么就出现了非常大的优化机会,从硬件,到虚拟化,到操作系统,这两年无论是Google,还是AWS,都已经开始展现了下面这几层的优化创新(gVisor、Firecracker等),但现在并没有霸主出现,这种机会就像是虚拟化刚诞生的阶段,是多年才能一遇的。

按照这样的创新路线下去,技术门槛太高,未来IaaS这层大部分企业都没有能力自己做,不像以前弄个Xen或者KVM,大家差距就很小,以后还是直接用云就好了,毕竟人才也多数会被这些公司垄断掉,云的公司一定会在IaaS这层继续加速演进,并且由于动力大,我相信会比前面很多年IaaS层的技术演进速度快非常多,对云类型的公司而言,比拼对IaaS层方向的掌控力会至关重要,我的建议是围绕在优化资源利用率、软硬件结合、从成本/启动速度等角度思考彻底重写容器下的各层三大方向来进行IaaS的优化和创新,当然,其实方向很多人都能看到,但是否能坚定的在方向上走下去最终会成为分水岭,这也同样意味着方向的判断就非常重要了,毕竟技术的创新不像业务模式,它需要更长的时间。

最后用一张图总结上面所写的:


欢迎关注我的公众号hellojavacases,

聊聊编程能力的高级进阶,

聊聊系统设计,

聊聊技术方向,

聊聊职业生涯的发展。

开发者生态,未来云的胜负手?

过去一年云厂商在开发者生态上的争夺开始变得激烈,为什么会出现这样的现象呢,是不是开发者生态,已经成为了云这场战争的胜负手呢?这篇文章就来探讨下这个话题。

事件


我们先看看在过去一年发生的几起重要的开发者生态的事件:

  1. 微软75亿美金收购Github,Google领投1亿美金Gitlab,使得Gitlab估值突破10亿美金;
  2. Coding获腾讯云一亿元战略融资;
  3. 开源厂商 Vs 云厂商开源厂商和云厂商在2018年发生了非常多的状况,关系在开始变得微妙,有几种现象出现:1). MongoDB、Kafka、Redis纷纷修改开源协议,限制云厂商,Neo4j企业版不再提供免费下载;

      2). 微软在2018年非常明显的加大了在开源的投入,上面说到的收购github,还有例如加入OIN,开源的VS Code在2018年是github上吸引到最多contributor的项目;

       3). Pivotal、ElasticSearch上市,目前的市值都超过50亿美金,Confluent(主要产品Kafka)、Databricks(主要产品Spark)宣布完成新一轮融合,市值均突破25亿美金,国内的话主要是Pingcap完成的新一轮5kw美金的融资,致敬下,作为技术人员对在国内能创办出Pingcap这样的技术产品公司无比佩服;

        4). 阿里巴巴9kw欧元收购Flink母公司,微软收购开源公司 CitusData(PostgreSQL 商业化的Startup);

海外三家云厂商的观点


再来看看海外几家云厂商自己在开发者生态这块传达的信号:

  1. AWS”大概12年之前,我们深知云将给软件带来翻天覆地的变化,我们创造了AWS。一直以来AWS希望与软件开发者密切合作,打造出一个现代化的软件开发框架。而不是告诉客户,你们需要什么工具。在AWS的信念中,我们认为真正知道软件应该如何开发的只有一个人,就是客户本人。”这是AWS CTO在去年中国的AWS Summit上讲的,其实在其他很多场合,尤其是每年的AWS:reInvent上也都会不断的表达这个观点,就是AWS和软件开发者是在一起的,AWS的会议吸引了无数顶尖开发者参加和关注,毕竟里面讲的很多都是未来的软件发展趋势。尽管Amazon给人的感觉在开源上贡献不大,但在技术发展的引领上我觉得还是起到了不小的作用的,在开发者群体中的认可度也足够高。
  2. 微软
    微软作为一家操作系统起家的公司,在开发者生态上一直就非常重视,而随着云的发展,感觉更进一步了,除了上面的github收购外,微软也开始非常大力的加大在开源上的投入,可以说,微软对开源的贡献是非常有助于推进这个世界技术的发展的,微软之前的形象开始有了不少的扭转。
  3. Google

       Google早期通过发表论文,在开发者群体中得到了非常高的认可,同时也非常切实的影响了世界的技术发展,例如大数据领域。

       近几年Google通过各种开源,更是形成了不错的开发者生态,无论是K8S、TensorFlow,都对世界技术的发展起到了很大的推进作用。

       Google Cloud的CEO最近还公开的讲”谷歌云:我们对开源的态度与AWS不同“来怼AWS,讲的核心的一段是”一直以来,谷歌云采取与开源社区合作的方式,而不是在自己的云平台中使用并出售开源技术。“,结合上面的开源厂商 Vs 云厂商的一些事件来看这段就更明白了。

关于开发者生态,我的观点


从上面的这些内容可以看到的现象是,各家云厂商都在通过开源、收购等方式加强对开发者生态的投入,拥有众多开发者用户的开源软件厂商在资本市场得到了很好的认可,开源厂商和云厂商由于利益上的冲突,关系尚待理清。

开发者生态为什么会发展到今天的这个局面,必须说说云的发展趋势。

最早用户对云的使用基本是纯粹的使用机器资源,和以前的虚拟主机等其实没有太大的区别,而发展到今天,几个大的云厂商强大的资源集约形成的规模效应,更是让用云的机器资源这件事成为了不需要再纠结的点,尤其是对初创公司而言。

随着对云机器资源的使用后,慢慢的开始有了用户开始使用更多的云的软件服务,例如存储、数据库等,在美国这个趋势非常明显,越来越多的公司画的技术栈中有越来越多的云软件产品的出现,下面这张图是Next Platform上对于AWS中计算、存储、网络和软件收入的分析:

可以明显看到软件这块越来越高,意味着越来越多的用户除了使用云机器资源外,开始使用云软件服务。

从对客户的价值上来说,越多的使用云软件服务,也就意味着自己在这方面投入的人员可以大幅减少,更加专注在自己的业务上,这一点随着经济形势的变化会更加的重要,而站在云厂商角度呢,客户使用越来越多的产品当然是更好,所以从趋势上来说,越来越多的使用云软件服务会加速。

而从技术趋势上,看到非常明显的两点:

  1. 通过PaaS屏蔽IaaS,对客户价值而言这是非常有益的,同时对云厂商来说也意味着IaaS层拥有了巨大的创新机会,以及不透明后带来的利益机会;
  2. No Lock-in,由于越来越多的使用云软件服务,客户心里上会非常担心Lock-in的问题,尽管我认为不会有多少客户真的同时部署在多家云上,但一定会需要具备这个能力,就是可以很简单的进行切换。

从这些趋势来看,也就意味着云的竞争进入云软件竞争的时代,云软件的用户群体是开发者(当然,有另外一种观点是通过强有力的SaaS软件直接服务最终用户,但我认为那样覆盖的面始终是有限的,云厂商自己很难去做好各种SaaS,只能是构建好一个平台,让上面有更多的SaaS厂商),并且软件和其他很多产品不一样,尤其是那些渗透到代码中的API,通常来说切换的代价很高,例如开发框架用了Spring,要想切换成别的很复杂,所以这层的竞争非常重要的一点就是谁能拥有对应最核心的非标准化领域的最多的开发者用户,也就是开发者生态。

要想获得开发者用户,和2C的很多产品竞争完全不同,这个领域基本不是靠砸钱就能获得用户的,很重要的三点是:

  1. 开源触达通过开源,让更多的开发者用户能即使不使用云软件服务的时候也能接触到,从而培养大量会用的开发者。同时借助开源,也可以更好的吸收各行各业的需求,使得产品更加的具备通用化的能力,覆盖更大的规模和更广的场景。怎么做好开源,对中国的公司是很大的挑战,这里面的套路非常的深。成功的开源软件因为在相应领域覆盖了大量的开发者用户,当在云上推出相应的商业服务时也会自然的收获用户,但由于目前这些利益基本都被云厂商拿走,这让相对应的开源厂商的努力得不到回报,导致产生矛盾。关于云厂商和开源厂商的关系,我觉得在2019应该会进一步明晰,一方面云厂商自己会加强在核心领域的开源,触达更多的开发者用户,另一方面会通过收购去补强核心领域的能力,很多人可能觉得这样不好,但我还是坚定的认为正因为有商业利益的诉求,这样的开源反而才能更为持续、健康快速的发展,对这个社会的发展而言是更有利的。开源对这个世界的技术发展、业务创新是起到了很大的帮助的,真心希望这个世界越来越多的开源,而不是越来越封闭。
  2. 技术领先在开源界中,同技术领域同质的产品基本只会留下一个,必须保持持续的技术领先,否则就算一个阶段领先,也很容易在下一轮技术迭代中格局被改变。
  3. 工具触达

       触达开发者用户的另一个很好的方法是工具,开发者用户群体最大公约数的工具是IDE,这大家就很容易看懂为什么微软开源vs code,并且那么重视,另外一个方面的工具就是开发流程方面的,代码是整个开发流程流转的核心产物,这也是Github巨大的价值。

综合来说,我认为开发者生态是未来云的胜负手的关键,从上面也可以看出,要做好开发者生态并不简单的是一件运营的事,而是产品规划、技术创新、社区建设、工具建设、运营等一起的事,这也是为什么我们看到海外的几家云公司是把这个上升到非常高的高度的原因。

最后,对于中国做这块的创业公司而言,我认为以下的两个方向是非常好的时机点:

  1. 社区一个优秀的开发者社区对形成繁荣的开发者生态是至关重要的,无论是问题、讨论、线下活动等,国内现在好像已经基本没有优质的开发者社区了,前几年还是有几个的,可惜当年做社区的同学都太难获得利润,导致很难运转下去,但到了今天这个局面下,我觉得会很有机会,不过要做起一个社区必须有长时间投入的打算。
  2. 开源技术产品技术领域需要的产品其实是非常多的,即使是云厂商自己,也很难去全部覆盖,因此这个方向的机会空间还是不错的,首先需要的是对相应有一定规模的技术领域的洞察,影响力,同时需要长时间的投入和经营。

衷心希望看到国内在为程序员这个行业群体服务的创业越来越繁荣,那样一定会让中国在IT技术层面逐渐对世界产生越来越大的影响力,更好的推进世界技术的发展。


欢迎关注我的公众号hellojavacases,

聊聊编程能力的高级进阶,

聊聊系统设计,

聊聊技术方向,

聊聊职业生涯的发展。

来测试下你的Java编程能力

上篇整理了下后面准备更系统化写的Java编程进阶的思路,如果仅看里面的词,很多同学会觉得都懂,但我真心觉得没有多少人是真懂的,所以简单的想了一些题目,感兴趣的同学们可以来做做看,看看自己的Java编程水平怎么样。

懒得去做小程序了,所以大家就直接回复你的答案吧,我会来一一点评下,友情提醒下,有些题目有点坑。

  1. 基于BIO实现的Server端,当建立了100个连接时,会有多少个线程?如果基于NIO,又会是多少个线程? 为什么?
  2. 通常来说基于NIO实现的Server端,会用多少个线程去处理IO事件,为什么?
  3. 一个典型的客户端集群->LB->服务端集群这样的结构中,如客户端采用连接池,长连接的方式,这种设计你觉得可能会出现什么问题?如果客户端采用的是单个长连接的方式呢?如果有问题,你觉得应该怎么解决?
  4. cglib和Java的动态代理相比,具体有什么不同?
  5. 在基于Netty实现FrameDecoder时,下面两种代码的表现会有什么不同?第一种
  6. private void callDecode(…) {       List<Object> results = new ArrayList<Object>();       while (cumulation.readable()) {             int oldReaderIndex = cumulation.readerIndex();             Object frame = decode(context, channel, cumulation);             if (frame == null) {                  if (oldReaderIndex == cumulation.readerIndex())                        break;                  else                       continue;            }           else if (oldReaderIndex == cumulation.readerIndex()) {                  throw new IllegalStateException( “…..”);            }            results.add(frame);     }     if(results.size() > 0)         fireMessageReceived(context, remoteAddress, results);}第二种private void callDecode(…) {
           int oldReaderIndex = cumulation.readerIndex();       Object frame = decode(context, channel, cumulation);       if (frame != null)              fireMessageReceived(context, remoteAddress, frame);}
  7. 用Executors.newCachedThreadPool创建的线程池,在运行的过程中有可能产生的风险是?
  8. new ThreadPoolExecutor(10,100,10,TimeUnit.MILLISECONDS,new LinkedBlockingQueue(10));一个这样创建的线程池,当已经有10个任务在运行时,第11个任务提交到此线程池执行的时候会发生什么,为什么?
  9. 实现一个自定义的ThreadFactory的作用通常是?
  10. 除了用Object.wait和Object.notifyAll来实现线程间的交互外,你还会常用哪些来实现?
  11. 为什么ConcurrentHashMap可以在高并发的情况下比HashMap更为高效?
  12. AtomicInteger、AtomicBoolean这些类之所以在高并发时高效,共同的原因是?
  13. 请合理的使用Queue来实现一个高并发的生产/消费的场景,给些核心的代码片段。
  14. 请实现让10个任务同时并发启动,给些代码片段。
  15. 在Java程序运行阶段,可以用什么命令行工具来查看当前Java程序的一些启动参数值,例如Heap Size等。
  16. 用什么命令行工具可以查看运行的Java程序的GC状况,请具体写出命令行格式。
  17. 用什么工具,可以在Java程序运行的情况下跟踪某个方法的执行时间,请求参数信息等,并请解释下工具实现的原理。
  18. 当一个Java程序接收请求,很长时间都没响应的话,通常你会怎么去排查这种问题?
  19. Java进程突然消失了,你会怎么去排查这种问题?
  20. 以下这段代码思路,你觉得在运行时可能会产生的风险是,应该如何改进?public List<User> getUsers(String[] userIds){       // 从数据库查找符合userIds的user记录      //  将返回的记录组装为User对象,放入List并返回
    }
  21. 以下两种代码,在运行时有什么不同?为什么?第一种private static final boolean isLoggerDebugEnabled = log.isDebugEnabled();
    public void xx(User user){     if(isLoggerDebugEnabled){          log.debug(“enter xx method, user id is: ” + user.getId());     }}第二种public void xx(User user){
         log.debug(“enter xx method, user id is: ” + user.getId());}
  22. Java程序为什么通常在刚启动的时候会执行的比较慢,而处理了一些请求后会变快,AOT能带来什么帮助?
  23. Parallel GC、CMS GC、ZGC、Azul Pauseless GC最主要的不同是?背后的原理也请简单描述下?
  24. 请写一段程序,让其运行时的表现为触发5次ygc,然后3次fgc,然后3次ygc,然后1次fgc,请给出代码以及启动参数。
  25. Go的Coroutine和Java的线程机制最主要的不同是?如果Java语言要透明的实现Coroutine,你觉得主要的难点是?

欢迎关注我的公众号hellojavacases,
聊聊编程能力的高级进阶,
聊聊系统设计,
聊聊技术方向,
聊聊职业生涯的发展。

Borg:G家最重要的基础设施

即使是在Borg论文发表前,从各种渠道了解也都能知道G家有一个挺神秘,非常重要的系统叫Borg,在Borg论文发表后,更是让人可以确信,再加上近两年和G家的朋友们的接触,更加可以知道对于G家的研发人员而言,说Borg是G家最重要的基础设施应该不为过,如果有看过《Google SRE》书的同学,可以看出有一点是在G家对Borg的认识是深入各研发同学的,Google SRE书里讲到G家的编译打包这种临时性任务,其实都是提交一个临时性的任务到borg来完成,而我想在传统或者说目前多数的做法里都会采用固定的机器资源来做这些事。

对Borg带来的收益,我想只用摘取Borg论文里这一小段就足以说明:
“Since many other organizations run user-facing and batch jobs in separate clusters, we examined what would happen if we did the same. Figure 5 shows that segregating prod and non-prod work would need 20–30% more machines in the median cell to run our workload.”
G家的服务器数量是百万数量级,20-30%这数量级的节省简直了…

既然Borg这么的好,为什么现在在其他互联网公司还没看到采用一样的方式去做呢(要知道Borg差不多是2003年就开始做了),从我的接触来看,我了解到的原因主要是这两个:
1.技术难度,有一些声音是觉得Borg这条路线太难走了,里面要解决的技术问题太多;
2.离线任务的规模量还不够大,这个时候Borg采用的user-facing and batch jobs混合在一台机器上运行的方式的优势就不存在了。
从上面这两个原因可以看到,要去打造一套Borg这样的系统,基本上只有机器到达一定规模,以及大数据也发展到比较大规模的公司才能有足够的收益比,当然,以现在大数据、AI的火热程度,排行前十甚至前几十的互联网公司其实都已具备这样的前提条件。

那么要打造Borg这样的系统,要突破哪些技术难度呢?

1.容器化
Borg把所有的task都放在cgroup里运行,这种方式相比Docker基于的LXC的差别在于没有namespace的隔离,简单来说就是当你登录到机器上,看到的是整个物理机的状况,这对于运维来说其实是相当痛苦的,从Borg论文也可以看到Borg为了方便对task进行运维,做了很多辅助工具和系统,所以在容器化这个方面我会更加倾向于LXC,具备namespace的隔离,对运维来说就会友好非常多。
为什么一定要容器化呢,原因在于如果对资源的需求都是物理机,那资源的调度的灵活性将会大幅下降,所以容器化是非常重要的一个基础前提,容器化的难题一方面是对LXC的掌握,另一方面则是任何类型的软件都要放在LXC中跑,会碰到各种问题,无论是性能还是namespace隔离不完整带来的支持问题。

2.复杂的调度器
当一家大规模的公司的所有业务都要通过同一个调度层来分配资源时,这个调度层所要面临的业务复杂性是非常可怕的,再加上batch jobs的调度,各种调度需求混合在一起,以及要管理巨大的机器规模,如何在保证业务需求满足的同时的规模、效率、稳定,绝对不是一件容易的事,现在业界有的其他的例如swarm、k8s、mesos、yarn等等,离borg这种级别的调度器是有巨大差距的。

3.资源隔离
Borg需要把不同优先级的任务跑在同一台机器上,non-prod优先级的任务会share prod优先级任务的资源,这个时候如何保障好non-prod任务不影响到prod任务的性能等就非常非常重要了,而这个目前业界并没有什么很成熟的方案,无论是cpu、内存、IO(磁盘/网络),离要成熟的支撑这样的资源隔离都还有非常大的差距。

4.历史包袱
Borg在2003年开始做的话,我想那个时候G家的历史包袱应该是不大的,但现在其他的大的互联网公司要做的话,显然都有不小的历史包袱,例如通常都会需要面临多种不同的基础设施、运维模式等,怎么在背着巨大的历史包袱走到期望的那步,其实是一件非常不容易的事。

可以说,这四点技术难度都是世界级的,因为碰到这样的技术难度的机会其实本来就很少,显然只有巨大的收益才能产生这样的驱动力,所以说这种类型的系统只有大规模的公司才会投入力量去做,而现在阿里就在投入力量打造这样的系统,如果你正好对这些领域有兴趣,并且在这些领域有一定的积累,我想这样的好的难得的机会(就像一直说,只有少数几家公司有做这样的系统的动力)不容错过,应该毫不犹豫的来加入我们,直接发送消息来联系我吧,期待你的加盟!

=============================
欢迎关注微信公众号:hellojavacases

公众号上发布的消息都存放在http://hellojava.info上。

高质量的工程代码为什么难写

之所以想起写这篇文章,是因为最近看到的一个著名的开源项目在内部使用时的各种问题,不得不说,很多的开源的东西思想是不错的,但离真正工程化都有不小的距离,所以没什么商业公司采用的开源产品如果要引入的话一定要慎重,通常会有N多的坑等着你去填,而比较成功的开源项目的背后多数都会有商业公司在背后不断的改进。

遥想我00年开始学习写asp代码时,觉得写代码也不难呀,无非就是学学语法规则、库就可以写出来,记得有一次我实习面试的时候是让我在一个下午左右的时间写一个完整的留言板,那也就是刷刷刷就写好了,但随着后来工作,尤其是加入阿里以后,越来越明白高质量的工程代码为什么难写。

在写代码初期,最关注的是如何用代码实现需求,如果是仅仅实现业务需求的话,即使是刚上手的程序员,只要解题能力还OK,基本上都是可以写出代码来的,所以我自己一直认为数学成绩是程序员的一个非常重要的要求,数学好的人通常解题和逻辑思维能力是还不错的。

上面的这个基本的写代码的过程中,写的更好的同学的体现会在对业务的深刻理解以及抽象上,写出的代码会具备一定的复用能力,这个在这里不多加探讨。

但代码是不是实现了业务需求就结束了呢,其实远没有,这其实只是写代码的开始,除了正向的逻辑实现外,任何一个点的异常的分支逻辑怎么处理才是工程化的代码中更难处理的部分,这个问题在单机式的系统中会相对还好处理,在分布式的环境会变得非常的复杂,例如调用其他机器的功能超时了,出错了,到底该怎么处理,这也是为什么有了那么多的分布式的理论的东西出来,在增加了异常分支的处理逻辑后,通常会发现这个时候正向逻辑的代码在整个代码的占比中会大幅下降。

异常分支逻辑处理好后,通常还需要增加必要的日志信息,以便在出问题时方便排查,而不是到了要排查问题的时候,一点目前系统的状况都搞不清楚,所以吃掉重要的异常信息不抛出这种行为在写代码中是非常可耻的。

在处理好上面异常的相关动作后,代码的健壮性也要处理好,这个主要指:
1. 自我保护能力
对外提供的接口是否具备足够的自我保护能力,就是即使使用的人没仔细看API文档随便乱用也不会导致系统出问题,这种案例非常的多,例如对外提供了一个批量查询接口,结果用户一下传了一个里面有上千个用户id的数组,查询一下直接把内存耗光,像这种情况下不能怪使用的人,而应该怪实现API的这一端的保护做的不够好,按照这样的标准去看,会发现开源的很多东西的API都不太合格;
还有一种就是能力保护,如果超出了处理的并发量的能力,这个时候会发生什么;
2. 对资源的使用限制
这也是代码新手或一些开源产品中做的比较差的地方,很容易出现规模一上去,资源使用量也一直涨,没有限制,然后导致系统挂掉,很常见的案例是对线程池的使用,例如像Java中的Executors.newCachedThreadPool,这个接口很多人会用到,但很多用的人都没有仔细想过会不会在某种情况下这里创建出巨多的线程;还有例如用Map做cache,也没考虑大小限制的问题,结果就是随着数据量增长,某天突然就挂了;
健壮性是代码中比较复杂的部分,通常也是比较展现代码能力的部分,可能看起来就几行代码,但其实背后反映的差距是巨大的。

开源产品除了在健壮性上的差距外,通常还会出现的一个巨大差距就是整个系统的设计的伸缩能力,伸缩能力不够的话通常会导致结构性的重构,另外常见的就是在并发的处理上不够高效,例如锁的合理使用、无锁算法的引入等等,而这些需要非常强的系统设计和代码功底能力。

除了上面说的这些外,高质量的工程代码还需要考虑可维护(例如监控信息暴露)、安全性等,对我而言,我一直认为所谓的工程化其实就是把一些玩具性质的代码变成可在商业系统中真正健壮运行的代码。

上面的内容写的比较简略,不过应该也能看出,对于高质量的工程代码而言,其实实现业务逻辑只是其中占比很小的一部分,甚至花的时间是相对最少的一部分,所以我确实非常赞同面试的时候让同学写代码,这个时候很容易看出同学写代码的功力;有些时候为了考察同学写代码的熟练程度,我会问问IDE的快捷键,或者让手写一段不是太复杂的代码。

=============================
欢迎关注微信公众号:hellojavacases

公众号上发布的消息都存放在http://hellojava.info上。

程序员的成长路线

工作这么些年了,看到了各种各样的程序员,也看到了各种各样的成长路线,说说自己的一些观点吧。

作为技术人员,在刚起步阶段时,首先需要拓宽自己的技术宽度,对自己所做的项目/产品所涉及的方方面面的技术都应该有所了解,另外对于就是学习工程化,让自己真正具备开发商业软件的能力。

在工程化和知识宽度达到一定阶段后,需要开始根据自己的兴趣和工作内容有所选择,主要是加强在某一领域的技术深度。

在技术深度达到了一定阶段后,需要对自己做出一个选择,就是偏业务方向,还是偏基础技术方向。

偏业务方向的技术人员,我认为做的好的表现是:
1. 对业务发展的未来有一定的预判,有商业敏感意识;
2. 能对复杂的业务进行合理的抽象;
3. 在系统的设计上能对未来业务的变化有一定的预留处理。

偏基础方向的技术人员,我认为做的好的表现是:
1. 能结合业务的发展趋势对基础技术的方向有一定的预判,避免业务发展受到基础技术的拖累;
2. 对业界的技术发展方向有自己的认知和判断;
3. 在对应的基础技术领域有不错的技术深度。

结合自己的特质以及当前的一些状况,做出一个选择,重点发展。

而再往更高阶走的同学,通常就会出现一种新的角色,就是成为团队leader,做为一个技术团队的leader,无论是业务的还是基础技术的,在技术能力上还是不能差的,尤其是判断力上,另外,作为一个团队leader,就意味着承担了团队方向的判断的职责,一个团队的方向基本会直接影响到团队所有成员的未来,以及所支持的业务的发展状况,所以对于一个团队leader,我觉得最重要的能力就在方向的判断上,然后是根据方向的判断的组织建设(团队搭建,人才识别、培养、招募等)能力。

如果不是往leader方向呢,那基本就是往架构师方向为多,架构师的话,在至少一两个领域的深度外,对广度的要求非常高,还有同样就是判断能力,无论是业务架构师,还是基础方向的架构师,领域的知识宽度是非常重要的,意味着能做多大范围的事,判断能力会体现出一个架构师在做一个架构设计时重点是怎么判断的,在有限的资源和时间情况下取舍是怎么做的,对未来是怎么做铺垫的,以及TA对事情的技术控制能力,一个好的架构师在技术风险的控制能力上必须是非常强的,例如一个强大的基础领域的架构师,应该是可以很好的控制跨多个专业技术领域的技术演进。

还有一种是往专业技术深度领域方向走,例如内核、JVM等,这些领域是真正的需要非常深的技术功底才能hold的住的。

还会有其他例如转型往业务产品方向等发展的就不在这说了。

总而言之,言而总之,我觉得在整个成长过程中,兴趣是最为关键的,所以follow your heart非常重要,只有在有足够的兴趣或梦想的情况下才能产生很强的自驱,没有足够的自驱我觉得在技术领域基本上是不可能走到高阶的,除了兴趣外,自己的优势也要判断清楚,每个不同的方向,我自己认为还是需要一定的天分的,而所谓的天分我觉得就是对个人优势的判断。

=============================
欢迎关注微信公众号:hellojavacases

公众号上发布的消息都存放在http://hellojava.info上。

技术人员的情结

每个技术人员都会有技术情结,或多或少而已,语言情结,框架情结等,这篇文章就来说说自己的技术情结和看到的一些人的技术情结的事。

我自己对OSGi算是有情结的吧,很多年前在上海工作的时候,偶尔会去参加一些meetup,看着讲topic的人都觉得好牛,好想认识下,但相对还是会比较困难,直到我接触OSGi,并且写了一些普及的文档后,很快就认识了不少业界的人,这些交际很大程度还影响到了我之后的职业生涯。

在07年加入阿里后,所做的工作其实和OSGi没有任何关系,自己甚至也觉得不会再和OSGi有任何关系了,但所谓的情结必须说就是深入骨髓的,到09年自己所负责的产品出现class不隔离导致的一些问题后,就立刻想着引入OSGi,这个决定可以说和情结有很大的关系,把自己最熟悉、最喜欢的一个东西放到商业级的产品中,这我想是很多情结最后最好的输出吧,当时为了给自己找到充分的理由,就把动态化也写为了需求的重点,class隔离+动态化,那绝对是OSGi的完美场景,于是整个团队在这件事上扑腾了好几个月,OSGi是引入了,动态化最后放弃了(实在太复杂,对于有状态的class要做到动态化实在太麻烦,而且在集群化的背景下其实意义不大),团队成员为了熟悉OSGi的开发模式花费了巨大的精力,并且以后加入团队的人也都受到不小的困扰,在那次折腾后,尽管看似情结输出了,但从此以后几乎所有来问我做插件化、class隔离等方案的选择时,我基本都会告诉他们不要用OSGi。

从OSGi情结这件事后,我就再也没有把情结和工作严格绑定了,情结能输出到工作最好,不能输出也OK。

在工作的历程中,也还看到其他很多类似的case,例如框架情结的同学,有些时候很容易做出决定是在自己所做的东西中要使用某框架,而也许公司内其实有类似的产品,并且有专职团队的维护和支持,说到这个必须说说以前经历的一个case是有一个同学对MongoDB非常有情结,于是在自己的一个产品中就引入了MongoDB,但其实自己对MongoDB的细节并不算非常清楚,结果后来运行过程中出问题了无法处理,而且其实后来review方案会发现在该场景中MySQL完全就可以满足;又例如语言情结的同学,有时候很容易做出决定是在自己所做的东西中使用某语言,而完全不顾及整个公司可能没太有这方面的人才,以后这东西还能不能维护得下去,说到这个可以说说火热的node.js,情况也类似,在运行过程中出现问题,没人能处理,只能临时Google等,搞得非常被动。

其实有技术情结不是坏事,反而多数是对技术有热情的人才会有技术情结吧,但技术情结是否要落到工作中,这个就必须深思熟虑了,工作其实是工程化的东西,工程化要考虑的因素非常的多,例如框架是否有专职团队支撑,未来的可维护性和持续发展性,甚至是业界的人才状况等都要考虑,所以很多时候语言的争论什么的其实意义不大,当然纯技术层面的讨论OK。

你会有什么技术情结呢,会不会有无论如何都得把情结输出到工作中的想法,或者你看到过什么现象,经历过什么故事,来回复说说看。

=============================
欢迎关注微信公众号:hellojavacases

关于此微信号:
分享Java问题排查的Case、Java业界的动态和新技术、Java的一些小知识点Test,以及和大家一起讨论一些Java问题或场景,这里只有Java细节的分享,没有大道理、大架构和大框架。

公众号上发布的消息都存放在http://hellojava.info上。