互联网开发模式三:持续集成与DevOps

持续集成的意义和实践

不管是敏捷开发的快速迭代,还是重构系统,我们都将频繁的编译代码、部署、测试,也就是所谓的集成。如果我们的系统集成效率太低,那么快速的迭代可能变成慢速的迭代,重构系统的频率也会大大降低。有一些项目,每一次集成,都要最少经历两三个小时,如果不顺利的话,搞一个通宵都未必能完成。

“发版本”是很多程序员和运维管理人员的常见加班原因。对于这个问题,很多小型公司开始的时候,并没有给与足够的重视,认为这些事情不过是程序员或者运维的本分工作之一,也是最日常的工作。真正得到出问题了,才发现重要性。

在任何一个互联网应用业务中,我们都会需要“发版”:出新功能、修改BUG、启动运营活动、甚至是机房搬迁。所有的这些,如果没有一套合适的工具来保障,每次发版都会是一场噩梦。所以持续集成(CI),很自然的成为互联网企业中最流行的、研究最广泛的技术之一。

所有资产纳入版本管理

持续集成的所有东西,都应该来源于版本管理系统(SVN/Git)。除此之外,软件资产不应该存放在任何其他地方。版本管理系统应该是开发团队的保险箱和金库,除了代码以外,所有的数据文件,配置,脚本,文档,都应该放入这个保险库。由于版本管理系统可以追溯到任何一个是时间点,这可以让故障恢复,问题回溯有良好的支持。

关于源代码使用版本管理系统,已经有很长历史了。但是互联网服务中,除了代码,还有很多其他的资源,比如图片、数据、脚本等等。除了产品项目外,我们的很多额外系统,比如运维工具、产品文档等等,都是需要妥善保管的,这些也都应该存放到版本管理系统中。

一般现在的版本管理系统,都有“分支”的功能,简单来说就是类似于“拷贝”了一份新的资源出来,在这之上的修改,可以由我们选择合并到其他分支或者放弃。所以SVN的常用方案,是启动三个类型的分支:trunk/branch/tag,专门针对“测试”、“开发”、“运营”。如果我们按预定的分支模型来设计版本管理系统的使用,那么我们的持续集成就可以很细致的选择集成哪一个版本的内容。

而在Git里面,每个使用者,都可以拥有自己的资源库,这对于开发测试可以更加的灵活,但是对于使用者的要求更高一些:在不同的资源库合并的过程中,需要更好的版本管理策略。持续集成系统可以自己拥有一个或者多个Git资源库,这样他们可以完全脱离版本管理服务器来独立运行。

自动化部署

我们曾经无数次的登录服务器,无数次的拷贝文件,无数次的修改配置,无数次的导入数据到数据库,无数次的……如果我们对这些重复,而且容易出错的工作熟视无睹,我们将永远的被这些本该机器去做的事情困住。

自动化部署,是整个持续集成工作中最重要的步骤。当我们每次发版都要很仔细的修改很多文件的时候,我们是无法避免在某次倒霉的事故后被挨批的。只有我们能把部署工作,也用我们的开发能力去解决,编写自动部署工具之后,我们才真正的能提升部署这个事情到一个新的台阶——我们终于可不再担心发版。

和自动化测试一样,自动部署脚本,也是把一系列的技术需求,从纸面文档+人手处理,改成用代码实体化,并且可积累改善的方法。自动化部署工具在开源界也非常热门,比如jekins,还有chef等等,都是为了解决部署问题而发明的软件工具。也许对于你来说,自己用bash开发一套脚本才是合乎你的品味,但是不管怎样,一定要有这样的工具。

就算要花费较长的开发时间,调动项目开发的程序员,一起来认真的开发一段时间自动部署功能,都是非常值得的。因为从今以后,你就可以拥有一个自己的部署系统,这个系统不但可以积累你的运营部署经验,还能加入很多错误、故障的自动检查,让你不再需要导出找“永远不出错的”运维人员。

自动化部署系统中,最核心的部分就是配置管理。拥有一个对现有环境资源集中管理的数据仓库是非常重要的。如果每个你的脚本可以识别自己所在的环境,以主动的方式去“申请”自己的配置文件和安装任务,是非常好的一个模式。因为从一个节点主动去分发程序,比不上多个节点向中心集群请求部署任务,来的更容易稳定。因为在节点上的部署代理程序,能更准确的知道自己环境的情况,也可以做本地的测试。

自动化集成测试

前面曾经说过,敏捷开发非常依赖于自动化的单元测试。实际上持续集成,也非常依赖于自动化的集成测试。集成测试可以把自动化部署的结果进行检验,避免手工进行反复验证。

如果只有自动化部署,而没有自动化测试,那么集成工作,其实还是非常浪费人力的。更重要的是,我们在每次“发版本”之后,总会担心新的修改,导致一些旧的功能失效。这种问题实际上是很常见的,如果无法自动化的做这种回归性的测试,那么我们每次发版还是要忍受漫长的测试工作进度。

自动化集成测试也有很多开源的工具可供选择,特别是基于B/S模式开发的WEB程序,但如果是手机APP的项目,或者客户端C/S程序(比如网络游戏),对于这类服务器系统的集成测试,往往需要我们自己根据业务来编写测试程序。

对于服务器系统来说,一般我们针对其通信协议编写测试程序即可,而对于客户端系统,如果是GUI系统的,我们还可以根据GUI的内部调度命令(安卓就有这样的套件)来测试,但如果是类似游戏这类业务,就只能用图形识别技术了。

在持续集成的流程中,集成测试往往是最后一步的检验关口。如果集成测试失败,应该给所有关注集成的人员发送警报(实际上,如果成功也应该报告)。现在企业往往会用邮件、IM、微信、短信或者别的一些东西接收这种消息。

DevOps的意义和实践

在互联网企业初始的阶段,运维工作往往是服务器端开发人员兼任的。当我在承担这种既是开发又是运维的工作时,往往非常羡慕那些“开发、运维分离”的公司。因为作为开发人员,没有三班倒的值班备份人力,往往是7X24小时的待命状态,工作压力非常大。

然而,当我自己参与到一些真正开发、运维分离的项目的时候,却发现,项目运营事故中,最少有70%的事故,是由运维的原因造成的。除了常见的硬件、网络故障,操作系统配置出错,日志清理出问题,部署配置搞错,进程不小心杀掉等等都出现过。

看来服务器端开发和运维还真是难解难分,而DevOps的思想,就是为了努力解决这种矛盾。我们不应该再把开发和运维对立起来,而应该认识到,运维是开发的一种延续,运维的需求也是服务器端系统的功能需求;运维是开发的目地,便利的、通用的运维工具,本身是能提高开发效率的一种专业产品。

运维与开发的一体性:运维、运营、QA

可以把DevOps看作开发(软件工程)、技术运营和质量保障(QA)三者的交集

一个互联网软件的上线运营,往往是由开发人员编写出来,然后经过QA人员测试,最后放在运营环境里进行运营。这个过程并非是单向的过程,基于前文说的,互联网服务都是在反复修改迭代中完善的,所以项目本身,一定是由多个版本,反复在开发、QA、运维之间循环交接。

举例来说,一个网络游戏,在第一次开发出来后,都会经过比较仔细的QA测试,然后通过运维人员进行上线部署,最后由运营推广人员进行宣传,同时也要配合这些宣传开启游戏内部的一些功能,客服人员也会在开始运营后参与进来,除了提供客户咨询外,抓作弊玩家和封帐号也会持续进行。

而作为开发人员的游戏策划,立刻会关注游戏系统的各种统计数据,以期在下一个版本中改善游戏设计。这个过程,可以看到在产品开发出来之后,整个团队几乎都还是需要以各种方式“使用”此服务器端系统的。所以我们在开发互联网服务的时候,不能仅仅面向互联网上的一般用户,同时也需要考虑整个开发团队的使用需求。

现代的互联网软件系统往往都带有服务器端部分。而这些服务器程序需要7X24运行,因此产生了两类非常明显的需求:

  • 运维需求:这类需求往往表现为非功能性需求,它要求服务器程序能够适应大规模用户访问和持续稳定运行。
  • 运营需求:这里需求通常是功能性需求,因为产品上线后,产品和运营、客服、测试人员,还需要持续不断的使用这个系统,和互联网的海量用户进行互动。

运营:客服、活动

在互联网服务中,运营是一个非常重要的环节。客户除了直接使用互联网软件的功能外,背后其实往往还有大量的从业人员在通过这个软件提供服务。

其中最常见的就是客服服务。客服往往最需要的是查询功能————能够查到系统中特定用户的使用数据,从而协助客户解决问题。

客服的另外一个主要工作,是封帐号和封IP。现在互联网黑色产业链非常庞大,互联网企业保护自己的手段其实不多,而客服是其中一个重要的环节,避免黑色产业侵袭自己的利益,就需要互联网服务系统有人工干预其数据的能力。

运营互联网服务另外一个常见的行为就是“活动”,也就是开放一些限时的服务。就和超市一样,互联网服务也要定时或不定时的加入或关闭一些特别的服务。这些工作非常细致和琐碎,需要服务器系统能够提供人工参与或者机器定时启动的一些功能。

在《魔兽世界》这个网游中,大部分的活动都是自动的和定时的,可以从游戏里的一个日历功能查到。而在国产的互联网产品中,的很多是临时加入,需要人工维护的,如“双十一购物节”这种。这些对于服务器系统的版本更新,功能修改,都提出了更高的要求。

因此一般我们在设计互联网服务系统的时候,就应该一开始就把运营需求,也作为版本目标纳入开发计划中。一些比较好的团队,会抽象和总结同类互联网项目(比如游戏、电商类型)在客服、运营活动上的共性,形成一套标准的服务规范以及实现这个规范的接口。由互联网服务开发团队去实现这些规范的接口,提供功能上的支持,而另外一个运营开发小组,则负责根据这个接口,开发供运营团队人员使用的界面、内部管理系统等。

比如游戏的运营规范会要求游戏提供查询角色区服、帐号的名字、等级等数据,提供接口在游戏中发布任务;电商系统的运营规范会要求网店提供本店销售排行查询、优惠券折扣接口等等。

运维:部署(虚拟机)、监控、统计

作为非功能性的需求来说,部署需求是第一位的。频繁的部署是互联网服务快速演变的基础能力。另外,互联网用户的增加(和消退)也是非常迅速的,这导致了我们可能需要快速的进行服务器扩容,或者缩容。这种情况都需要涉及到部署。所以我们在开发服务器系统的时候,部署需求是第一个需要考虑。加上如果我们希望实行持续集成,那么就更加需要重视部署的能力。

作为服务器端系统,如果被设计成带有非常复杂的进程种类和进程通讯关系的话,要做好部署就会变得更加复杂。加上可能部署的环境还不统一,可能出现的问题就更复杂了。所以现在有大量的技术尝试改善这个方面。

首先被大家广泛接受的是虚拟机技术,也就是所谓云服务器(IaaS),这种技术能让你无需直接操作硬件,不用扛机器到机房来进行部署,是一种巨大的进步。而后现在我们有了Docker这种基于Linux容器技术的工具,这可以把服务器操作系统层的差异环境,都统一成一个个image文件,部署的时候只要运行image文件即可。

但是这些依然无法简化错综复杂的服务器进程关系,所以现在有了各种“队列服务”技术,比如Kafka,RabbitMQ, ActiveMQ等等,这些队列服务把进程间通讯简化成专门的服务,减少了部署的复杂性。而ZooKeeper的广泛使用,让我们在多进程间协调和监控有了更多的手段。在具体部署工具方面,Chef这一类软件做了各种有益的尝试,这些都是能让我们优化部署需求功能的工具。

互联网服务的24X7持续服务能力,实际上会收到各种挑战,除了版本发布可能导致的问题外,在大量机器硬件里面,硬件故障率是一个固定的比例。网络抖动,机房线路故障也常常会出现。更容易出现的是异常的用户访问波动:一大波用户汹涌而来,但是也有可能是DDOS攻击。不管怎样,你都需要随时掌握服务器系统的工作状态。

这时你就需要一个监控系统,但如果产品上线才发现要做,那往往已经很迟了。因为一个系统是否有问题,并不是简单的从内存、CPU、网卡流量就能看出端倪的,我们往往需要在服务开发之初,就定义好各种需要监控的指标,传统常见的指标有:每秒主循环的次数、每秒处理业务包的次数、服务器中缓存的会话数等等……一些做的好的系统,还会有很多业务层面的监控指标,比如某个特定服务的处理效率、处理成功率等等。

既然一个系统有大量的监控指标,就涉及如何生成和管理这些数据的问题。传统的做法是在系统中“埋入”这些监控程序,系统一边运行一边统计这些指标,然后定时生成日志或者通过网络上报给某个监控系统。但是这种做法的缺点是:如果你需要更多的指标,或者修改指标的统计方法,你就被迫要修改代码,重启服务,这样会影响正在运行的服务。

现在另外一个做法是,由系统把运行的原始信息记录成日志,然后把日志集中上报到一个监控系统中,这个监控系统一般都带有分布式的文件存储系统和分布式计算统计能力。在搜集到大量实时日志的同时,这个系统根据预设的指标统计方法,不停的进行日志统计,一旦发现统计结果有问题,就会报警。

这种统计由于是在大数据处理能力的平台上生成的,所以往往发现问题的时间差能缩小到分钟级甚至秒级。这种做法由于搜集的是原始日志记录,所以就可以灵活的在系统运行时定制很多统计和报警的策略,但完全不会增加服务系统的压力,也不需要修改服务系统的代码。

最后说说统计,任何一个互联网系统,都是在用户的使用中不断优化的,这个优化的依据,最重要的客观依据,就是统计数据。而统计数据,一般由两部分构成:

1. 用户的行为数据。比如登录行为,就可以给系统留下用户的IP、登录时间、登出时间等数据;购买行为,就可以留下购买商品,购买价格,购买时间这些数据。

2. 根据用户的行为的关联,统计出来的数据。比如根据登录行为,我们可以统计出用户的在线时长,用户重复登录的次数,用户重复登录的间隔,还有什么次日存留、七天存留等等……;根据购买行为,我们更是可以整理出用户的购买商品倾向,ARPU值,甚至同类用户的购买共性,这些也是所谓大数据做商品统计的主要方向。

根据上面的分析,我们可以发现,实际上统计系统也是应该分两个部分设计,一个是尽量记录用户行为的基础数据,第二个是以复杂多变的统计条件,去挖掘这些用户行为数据中包含的规律。

对于第一部分,一个可以存放海量日志数据的分布式存储系统非常重要;对于第二部分,分布式的统计运算系统是必不可少的。对于这个体系,Google的Hadoop提供了业界的示范。但是如果你愿意,也可以使用这个思路自己来建设自己的统计系统,也许你的数据量无需要用到Hadoop那么复杂。

总结

互联网开发模式,是针对于互联网本质上是一个“服务”而发展起来的。因为是“服务”而不是产品,所以应对快速变化的能力是最高的技术标准。我们倾向采用更适合表达需求的软件开发技术、自动化程度更高的开发工具,来提高我们的开发效率,而不是靠单纯的“激励主观能动性”来做管理。

因此我们在基于自动化测试、自动化部署等持续集成工具的平台上,使用重视原型迭代的方法来开发项目,在反复以原型确认需求,以及适应需求变化的过程中,逐步的完善整个开发生产线。并且把开发和运营视为一个整体,在服务的运营过程中,不断的完善互联网服务的运营工具,让开发和运营在同一个生命周期里生长。

本系列文章至此已经全部结束,感谢大家的关注。

原文发布于微信公众号 - 韩大(handa1740168)

原文发表时间:2016-08-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Rainbond开源「容器云平台」

【干货下载】谷歌、亚马逊等十大公司精选微服务案例

1416
来自专栏通信云团队

即时通讯App怎样才能火?背后的技术原理,可以从这5个角度切入

通过短信和IM的结合,可以实现从APP内到APP外的沟通。若你的朋友没有安装应用,你也可以在应用内,导入通讯录好友,给其发消息,只是这个“消息”,会以短信的形式...

911
来自专栏北京马哥教育

30分钟带你揭开运维自动化的面纱-Ansible业务自动化之路

本文由马哥教育运维部落~Ansible部落分享整理而来,Ansible原创翻译团队共同努力而得.Ansible最新消息可关注 http://www.178lin...

29410
来自专栏大魏分享(微信公众号:david-share)

容器在企业中的应用---红帽全球技术峰会北京站分享

IT基础架构经历的三次大的变革是什么?容器如何在企业中落地?世界500强里中国企业使用容器的成功案例有哪些?请带着这三个问题,阅读笔者在红帽全球技术峰会北京站的...

3258
来自专栏IT技术精选文摘

小程序开发指南

3137
来自专栏云计算D1net

控制云访问的5个简单的步骤

企业IT管理人员要如何才能带来对于公共云服务的使用的秩序和问责制,同时又不影响进程的处理呢?每一种技术的成功故事也是一个后果意想不到的故事。例如,采取虚拟化技术...

33910
来自专栏云计算D1net

微软一切服务都有云烙印

TechEd是微软IT专业人士和开发者们的盛会。但是本周举行的TechEd北美2014大会的开幕主题演讲中,微软并没有推出一款新的产品。所有公布都是关于云,一直...

2604
来自专栏漫漫全栈路

R.I.P. :传统整体式架构 VS 微服务

我咨询了十几个微服务项目。有些人表示,微服务真棒(这是未来!),而有些人很沮丧(谁发明了这个废物?)

1232
来自专栏腾讯云培训认证中心

腾讯云认证云从业者考试攻略

大家等待已久的考试攻略来啦! ...

1.1K131
来自专栏从零开始理解云计算

从零开始理解云计算 Vol.2:云计算的分类

这一篇介绍云计算的分类。云计算可以按照层次分为四类:IaaS、PaaS、SaaS、DaaS;或者按照所有权分为三类:私有云、联合云和公共云。本文将着重解释前一种...

9901

扫码关注云+社区