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上。