豆瓣私有云DAE平台的发展历程

个人简介 彭宇,@胖胖的大头鱼,python dev @douban,目前负责DAE平台。

豆瓣是以技术和产品为核心、生活和文化为内容的创新网络服务。豆瓣以书影音起家,一直致力于帮助都市人群发现生活中有用的事物,通过桌面和移动产品来服务都市日常生活的各个方面。

   

1. DAE团队在去年主要做的工作都包括哪些?

彭宇:去年的工作主要是把DAE从一个可用的状态转变到一个用起来比较舒服的状态,把一些核心的应用迁移到这个里边来,也让迁移过来的这些开发者知道迁移过来也是OK的,只会比以前更好,不会比之前更糟。

做的相关事情一方面是说把DAE和公司的其他系统打通了,包括测试、集成系统是全部关联在一起的,你在DAE上面的commit也好,PR也好,上线前的测试也好,直接都自动做了。DAE的上线系统里面会检测每个Commit是UT有问题,还是Web test有问题,还是Self test有问题。

另外一方面是做了很多监控方面的事情,一个是说有一些基本的监控了,比如说最简单的UT,Web test,但是如果你只在本地测过,你可能一个页面都打不开,所以我们有一个特别简单的Self test,就是我先在一台服务器上面安装启动,跑起来之后去拿一个Status code,做一个简单的检查。如果这几个检查都不过,那肯定系统还有挺严重的问题,直接就上面Roll back。

还有别的一些监控,比如说你的错误率太高了,或者是你的MQ跑疯了,塞住了,这种Nagios的监控。因为之前这些都是内置的一些模板,直接模板交给Nagios报警,开发人员可以自定义,自己去在他的里面去配需要去做哪些监控,然后我们的监控脚本是什么,我需要一个可能有三四个参数,和Nagios可以一一对应的,我们会根据他写的自动生成安装模板,然后到Nagios去跑,这样他就不用再去找SA,完全是他自己控制。

另外一方面做了很多把豆瓣已有的应用迁移过去的事情,主要是去年前年比较大的三个,一个是移动版豆瓣,一个是豆瓣电台,还有豆瓣电影,这三个都是流量相当大的。他们之前都是SA在手工维护的,需要开多少机器,多少内存,都是SA在手工维护的;迁过来之后,我们一开始也做了一段手工维护,基本上到现在已经脱离了手工维护的阶段,作为一个普通的DAE应用在跑。我可能都有一两个星期都没有收到SA的报警了。

   

2. DAE现在这个架构设计在历史上经历过哪些阶段?其设计理念和技术选择的理念是怎样的?

彭宇:DAE最早一次代码提交是2011年的6月份,其实从那个时候到现在,就大的结构上来说其实是没有特别明显的变化的,还是一个两层的nginx,前面有一层nginx,到中间Load balance,然后就到了节点层面的应用服务器了。应用服务器上面我们基于Gunicorn跑,Gunicorn按进程来管理。基本上还是这个结构。

我们有一些指导原则,就是整个DAE系统的核心尽量的小——他在runtime的时候足够用的,能够支持那些DAE提供的API,nginx需要的那些东西,就足够了,别的服务就尽可能的采用在DAE上面建APP的方式,相当于用自己把自己支撑起来。比如说PS,就是我们的静态文件系统,它就是一个独立的应用。它干什么事情?它其实是管理每个应用自己的静态文件,比如CSS、JS,包括压缩打包什么的,都丢给它了。因为这个本来是个很独立的事情,我们也不希望把它算到DAE的核心里边去。然后包括DAE的Cron,也是在外面的,你在那个APP的Yaml里面配好的Cron,最后就丢给了一个叫DAE Cron的APP,那个APP来负责调度这些Cron。包括你看DAE的Log其实是有一个应用。用DAE Log有一个方便的地方,就是有时候公司会有些权限上面的问题,比如说Intern他不能看到某些应用,比如他只能看到Code,或者是只能看到他开发的那些应用,但是他有时候需要去看这线上的Log,那我把DAE Log开放给他就好了,不用把各个应用都去开放给他。

另外我们今年做了一个像Portal一样的东西,每个应用一个,他上面有这个应用现在的,比如说资源占用情况,部署在哪些节点上面,一共部署了多少个Worker,每台节点上多少,qps是多少,现在的平均返回时间是多少,出错率是什么样的情况,它的最近出错的数据是什么。我们的出错系统叫Onimaru,基于Sentry搭的。比如说你是某个应用的开发人员,那个web界面上就有个shell,你可以连上去看一下数据,也可以在里面做部署,基本上开发人员需要的东西他都有,包括你的Cron最近的情况,也可以比较详细的跳到每个Cron去看,是出错还是正常,以及他们的输出。

所以基本上,我们的原则还是说能尽量多的把这些功能都放到外边去,必要的才放到核心里。

   

3. 现在架构中用到的这些东西,比如gunicorn、thrift等,在使用和二次开发的过程中有什么最佳实践?

彭宇:因为我们整个那个APP server就是搭在gunicorn上面的,对gunicorn研究也蛮多的。一开始有一些弯路,大概是去年上半年的时候,因为你用开源的一个好处是,你能看到它所有的实现,所以我觉得这里有点不爽的,可能因为有哪个需求,就要去改一下,我就改了,也很好使,那我就改了;转天我可能有另外一个需求,我就又在里面开始改。可能改了一件时间之后,这个东西的问题就出来了:那些修改并不见得是那么的必要,也不见得一定要到gunicorn里面去修改,改的话你和社区就越走越远了,可能gunicorn再发一个新版本,你想用那个新版本,那个时候就非常抓狂,你需要把你之前那些Patch全部找回来,然后再去使用集成,真的就是一个体力活了,也未见得是好事。

所以现在对gunicorn,我们大多数的修改,我们觉得对可能是对社区也是有帮助的,一般会是直接到给他上面去提patch,然后我们自己也维护了一份gunicorn的fork,这个Fork目前的主要目的还是说,因为有些PR并不是那么快被和进去,同时我们也希望跟着一些比较稳定的发布,所以我们就暂时先在内部先用,等到外边的正式版本已经有这个Feature我们再去用外边的版本。包括gunicorn里面的Work也是,我们默认会用gunicorn里边的sync worker,和他基于gevent的async worker。还有一个Worker是我们自己写的,thrift worker,还有一个我们新做的叫PIDL worker,这两个都是在遵守gunicorn一套规范写出来的worker,我嵌到gunicorn里面去用。可以说我们最大程度的复用gunicorn已有的东西,同时也把自己需要的东西放进去。

我们提的PR里面有好多可能其他人没那么用过,比如说有一个PR,是用来拿参数的,内部去拿参数的时候,那个代码它只会去从命令行拿argv里面的参数,这样就导致我们很崩溃,因为我们是在sync worker外边套了一层,我们自己是不希望它再从命令行上面拿参数的,所以我们之前的一个hack办法是说,因为我在上面套了一层,直接把它那个sys.argv改了,就是我专门有一个函数去做参数转换,这个其实是没有必要的。最后我们去提了PR给他,只是让他能够多接收一个参数,把这些配置都传过去。

另外,有时候你跟他的发布跟的太近了也会有问题,我们现在也不敢跟着他太近了。比如说他今天发布了新版,你在Github看到,你下午就跑去升级,一般来说都会撞到坑,可能有时候你等半个月就OK了,一般可能会有一两个bugfix。你要是升级太早撞上了,你就只好再降下来,又反倒更麻烦了,万一新功能已经用上了,也会去帮他提bugfix。一定要忍住。有时候可能确实他有个feature我现在需要,但是反正已经等了几个月了,再等等吧。

   

4. DAE现在跟其他基础团队是什么样的合作关系?豆瓣的老项目和新项目加入到DAE上的流程是怎样的?

彭宇:我们跟好多团队都有挺密切的合作,在平台里面最密切的就是SA,因为DAE最初的想法就是把SA做的事情自动化,常常也说是解放SA。比如说监控类型的东西,我们会去跟SA一块去看,比如对于应用来说,常见的监控方式都有哪些,他们现在都是怎么做的,哪些是可以以比较一致的方式把它直接解决,不用每次都是人工。另外一方面,我在迁移老的应用到DAE上面来的时候,SA以前可能是手工配置一些东西,逐个的去捋,现在就反过来,SA对我们有一些推动。其实我们DAE团队的人对系统跟SA比可能还没有那么的了解,我把应用迁过来了,可能迁过来的头几天会有性能上的问题,可能参数上调的不是那么好,SA会过来和我们一块看,到底它迁过来之后问题出在哪,是分的机器不够,还是说分配方式有问题,不应该和某些应用跑在一起。

另外像洪教授他们那个PIDL,Python Interface Defined Language,他们希望做一个更方便用的Service,目前独立在DAE以外做,但是他希望更多人用,可能会是说通过DAE把它用起来,他们可能先在他们小组内开发的差不多了,找一个DAE的同事一起来把它集成到一起,基本上的工作方式是他们来推动DAE来做这个事情。他先会有一个自己的Demo应用,不可能一开始就正式用。他先把一个Demo在本地跑通了,然后他再说如何把我的Worker放到DAE里面来,可能需要给DAE提一些需求,先要某个应用支持这种新的feature,他需要在DAE里面有一些新的配置项,那有了这些项以后,DAE在部署这个应用的时候,就会生成一些新的使用脚本来配置一些东西。所以说这些相关的代码,可能他们那的人Ready,DAE和他们共同去做这些事情,接下来才是用这个Service的应用去牵其他应用。如果是新的东西,是这么一个流程。

是否用新的东西取决于产品开发那面的同事,因为不同的人还挺不一样的,有的同事可能特别愿意尝鲜,你这有一个Feature,他觉得我这可以用,可能他第一时间当个小白鼠;有的Team相对比较保守一点,觉得这个事情跟我们对待开源事情是一样的,不会第一个用,他先看那么一两个项目,可能也跑的不错了,然后他才来尝试。

我们一开始迁已有的项目,那几个大的Web应用过来,也是这样,是DAE的人去推着他走,因为一开始对于他们来说,我现在已经跑的好好的,也有SA做后盾,那为什么我要迁过来?我迁过来没什么好处。这个事情就很麻烦了,那我DAE团队就来承担这个责任好了,出问题算DAE的。DAE做好了,DAE会帮他们。基本上来说,DAE对应用代码的修改比较少,大多数只是把应用做一个配置,然后部署过来再看,每个应用不一样,可能会有些代码上的问题,再把这些问题理顺了以后,看性能上有问题,性能上没问题时候,产品开发也就不会有什么疑问了,他们觉得那挺好,那就跑过来,然后我们团队一般就会去打打广告。小项目想自己做部署,或者是做测试,很多需要去找SA,或者找到QA去帮你手动的填一些东西,做配置版本,现在有了DAE你自己都已经搞定了,所以这个事情就很方便了,就这样推动。

   

5. 现在基本上阻力小很多了?

彭宇:现在基本上新项目就没有阻力了,因为新项目——无论是移动项目也好,Web项目也好,他们其实大多数的开发人员很喜欢,就是很快做起来了。有的前端的同事来提过,希望及我们能支持Node.js,但我们现在还是主要想先把Python弄明白了。现在到这个月,豆瓣可能只有WWW里边的一部分还是用老的写的,只要不是WWW开头的,几乎都是DAE上的东西了。

   

6. DAE在当前的主要工作方向是什么?上次PyCon上提到后续的一些计划,包括cgroups隔离、新的服务系统等,进展情况如何?

彭宇:我们现在主要的就是autoscale这个问题。去年到今年迁移了那么多应用以后,逐渐暴露出来一些问题,因为之前豆瓣就是一个大的应用,所以SA能够用一个比较大的池子来管这些应用服务器,能够处理这些请求。但是现在的问题是,我把这一个应用,砍成若干个小的应用,每个小的应用需要是不一样的,需要的机器也是不一样的,内存限制也是不一样的,我们把那些应用迁过来,一开始还是蛮粗暴的,就手动来调优。

我们有一些小的脚本工具能够稍微帮我一下,我能够看到这个机群里面机器的负载情况,然后我知道一个应用在哪些机器上的进程数,它有没有出错,资源是不是不够,我应该在哪些机器上给它开多少,这些我们也还是在做,基本上就是以前SA在做的事情。只不过SA对一个应用做就够了,因为全站只有这一个应用,现在我们可能对五六个比较大型的应用都得关心,保证它每天不出问题。

这件事情持续了之后,觉得实在是有些疲于奔命了,所以推动来做这个Autoscale,希望这个应用能够自动满足既不会把机器压垮了,而且自己也能够跑,这样一个状态。

现在有一些简单的策略,一方面是说怎么去Scale应用,它是需要多加点Worker还是减点Worker,这个是从应用来说。我们需要保证在每个时刻,他都有足够的冗余度,机器宕掉了不会说这个应用一下子就被压垮了。另外一方面是从节点方面来考虑,这个节点现在是不是有点过载了,比如说我这个集群里面有十台机器,会不会有八台机器很忙,两台机器很闲,那我如果发现很忙的机器,可能我需要去踢掉一些,最后的目标能够比较省的用机器,又让这些应用自动根据请求来做自动的伸缩。

cgroups也是在计划中的,不过我们现在手头有一些比较山寨的解决方案,比如说每一个Web的机子上有个Service的集群,默认都会有一个内存限制,每个应用你可以自己去配一些限制,我在外面有监控会去看,如果发现有问题了,他会自动退出,包括你的Daemon那些都可以这样。但是这个方法目前来说只针对内存,如果是CPU层面就没办法,只能说监控到了之后人肉去解决的方式。

你可能感兴趣的:(豆瓣私有云DAE平台的发展历程)