
在整个项目流程中,首先是业务,我们做DevOps的时候一定要从业务目标出发,业务人员先去确定业务目标,然后进行产品的规划,规划完成之后进行产品的设计。设计拆分成具体的功能,功能对应我们的需求。在需求出来之后,我们进行敏捷开发。开发完成后进行集成测试验证,最终发布运维上线。我们DevOps其实主要是致力于为产品设计到发布运维这一过程提供支持,完成服务目标。整个过程也是我们项目管理的过程。
这个目标和方法我借鉴了百度工程能力的定义:工程能力是使用系统化的方法,在保证质量的前提下,更高效率地为客户/用户持续交付有价值的软件和服务的能力。其中有几个关键词,首先它是系统化的方法,对应去哪儿我们这么拆解系统化的方法。首先要有流程规范,因为有了流程规范,具体的一些落地才有章可循,而不是做各种单独的一些场景化支持。有了流程规范,我们去落地,先落地到我们的工具平台,这一层落地工具平台都是先做一些普适性的工具。但普适性的工具虽然对所有的场景都支持,但也存在对真正具体的一个场景化支持不流畅的问题,因此我们拆分出具体的场景化实践。遵循这一闭环,我们来建立我们DevOps的生态。有了方法之后,我们的目标是什么呢?当然是提升交付速度。但是在提升交付速度的过程中,我们又必须保障质量,所以我们的两大核心目标就是提升交付速度和保证交付质量。基于以上的目标和方法,我们落地了DevOps生态。
这几个数字是基于月均的数字统计。我们现在每月平均有3000+项目发布,15万次+部署,涉及到2000+应用,1000+开发测试运维。由此来看,我们的体量还是相当庞大的。值得一提的是,在这3000+的项目发布中,有很大一部分是开发自测自发,即完全没有测试人员的参与。这完全依赖于我们
DevOps生态建设对开发测试进行赋能,也因此,我们的开发同学自测自发不仅保证了质量,同时也保证了我们的交付速度。
在我们公司,可能其他公司也相同,在开发项目过程中一个核心资源就是开发资源,我们的理想状态就是要实现开发资源利用最大化,理想状态就是开发人员只需专心投入写代码即可。但是现实情况是开发同学被各种角色干扰。主要有以下几个问题。对开发来说,频繁的被打扰导致其时间碎片化,在各种任务之间切换导致效率无法保证。对项目经理来说,无法得知项目的实时进度,项目是在开发过程中,还是在测试过程中。因此只能去跟开发进行去人为沟通,这不仅导致了开发被打断,也使项目经理无法掌控整个项目过程。对QA来说,
QA最终要为质量负责,但是QA不知道项目的这次需求变更了什么内容,这就会导致变更靠人为的梳理很容易被遗漏,从而导致上线出故障。我们有很多血淋淋的教训,因为没有更新DB,或者是一个配置忘记更新了,上线出现过很多次故障。对PMO来说,PMO要收集整个项目过程的数据,通过数据去确定我们的改进优化分析,分析优化改进。但现在我们项目的所有数据全都依赖人工去填写,很难保证数据的准确性,从而给改进优化带来困难。通过上述分析,我们可以发现,我们对于整个过程的跟踪是基于项目去跟踪的,但是这个项目变更的内容又是应用维度的,所以导致我们没有办法被跟踪,人为操作多。核心问题就是我们的应用跟项目没有建立关联关系,所以我们要去建立这一关系,从而解决这个过程中的问题。
① 分支命名规范化我们对分支进行了命名规范的要求,分支名必须包含一个PMO标识。这样当分支被创建、被push的时候,就自动将其关联到项目上面,建立了应用跟项目的关联关系。② 质量检查可视化知道了项目变更了哪些内容,变更的时候每次提交都可以去自动的触发一些相应的检查,相应的检查结果报告就可以展示在这个项目上面。对于QA人员来说,可以直观的了解项目当前的质量状况;对于项目经理来说,可以比较直观地了解这个项目的状况,从而去控制风险。③ 数据回填自动化对于PMO来说,之前很多数据难以收集,有了关联关系之后,我们会把这一次项目的发布数据,包括发布的次数,以及变更的行数等都自动回填,相当于获取了这个项目整体的变更数据。④ 状态流转智能化因为我的代码已经跟它关联起来了,在开发中如果是提交到代码,可以自动从项目已排期状态变成开发状态。当我做了一些Beta验证的时候,就可以自动地流转到我现在是要提测了或是要发布了,所以这个状态的流转实现了智能化。结合完整的方案,我们就解决了各种开发被打断,自动化手动操作过多的问题。这个是我们的架构。
相当于开发与应用关联的工具,我们内部把它叫做Qodin,底层是DB,Cache,其次是我们的数据存储,然后各个工具平台会把自己执行的一些结果通过发送消息推送到我们的消息平台。Qodin通过消费这些消息,通过外部的HTTP接口触发各种工具平台去执行。上层是我们通过js一些页面给用户提供一些查看入口、操作入口等等。
上图是我们的一个项目,我们可以看到这个项目中到底变更了哪些内容,首先是变更的一些质量的情况,以及它的发布情况。其次是我们自动回填的数据,可以看到包括研发阶段的市场自动计算,项目总市场等,线上发布的次数,代码变更的一些信息,同时我们在一些项目的关键节点,根据时间计算关键节点的状态流转以及是否delay,这些都会有一个及时的项目提醒,这样保证了开发和项目经理等都可以及时地关注到整个项目过程,一旦有任何风险也可以及时地暴露出来。总结这一实践,主要是通过规范化确定一个分支的命名规范来实现我们的应用跟项目的关联,然后保证了我们项目整个流程的自动化与高效。
我们先看一下理想,理想的状态是开发修改完代码之后,通过测试,提交给QA,然后QA同学集成测试,最后愉快地上线。但实际中常常会出现开发跟测试同学的相互抱怨。开发人员表示我测了。QA人员却说你这提交的是什么,你自己测了没有?QA人员常说为什么我测试了,到上线还是会遇到问题,其实总结起来主要是以下问题:对开发人员来说,首先测试条件是难保障的。开发人员做测试的时候,其实有环境的依赖,也有数据的依赖,有一些前提条件的准备。但是这些常常会特别耗时间,准备也非常困难,导致测试不足的问题。其次修复成本高,因为开发人员在前期的测试不足,提交给QA人员之后,通过QA人员发现了问题,然后再反馈给开发人员,反馈的周期就拉长了。开发人员这时可能已经进入到其他项目了,从而又有一个切换成本。对QA人员来说,没有办法让开发保证提测的质量,更多的是依赖于自己的测试,对其来说非常不友好。还有上线的质量也难以保证,很多其实我测到了,但是可能依旧带着问题上线了。
① 多种手段保证效果首先我们采用的第一个方法是先用多种手段保证效果。我们的手段包含以下几种:
在CodeReview方面,我们是基于开源工具phabricator实现的,我们会做到分支创建后自动同步仓库,同时代码push的时候自动去创建更新diff,这样就避免了人工去创建以及后续操作。同时我们支持两次提交diff的变更,这是为了解决发现问题并修改重复提交后的全量diff问题。不需要全量的再次diff,只需要看这两侧的一个变更。当然如果影响范围较大的话,还是建议全量的再diff一次。静态代码检查方面,我们使用业界通用的sonarqube,但我们的特色点是代码push的时候它会自动执行,然后消息反馈。同时我们有增量跟全量的报告。我们有很多历史在的基础上,如果你要求它去全量的解决问题,这在业务非常繁忙的时候是不现实的,所以我们做了增量,只去检查当前这次变更引入的问题,只要解决了这些问题并能够保证不新增,后续再去慢慢地解决全量问题。接口自动化方面,接口自动化这里我讲的是灭霸即接口回归问题,接口自动化大家最头疼的就是要自己去写case,业务变动又比较频繁。我们的时间点是怎么做的?我们会基于检查点的case自动生成补全清理。例如航司,航空公司是有很多公司的,比如说南航、国航、川航等,相当于每一个航空公司对应一个业务,我可能就要对这一个类型去进行验证,所以我们需要用户先定义一个检查点维度,然后业务在线上执行的时候,会去生成日志,我们通过日志去采集这些具体的case,再生成补全。当过了一段时间,如果检查点没有这种业务的case请求了,我们就可以自动清理,这就解决了我们人工维护case的一个痛点。代码覆盖率是基于Jacoco实现的,也是增量跟全量的一个报告,可以看这次变更的一个覆盖率情况。上述是多种手段,下面看一下我们的测试环境。
我们对环境的定义是什么?这个环境肯定不是单应用的环境,这种单应用的环境是对于整个业务的测试,它起到的作用是非常薄弱的。所以我们对环境的定义是支持一种业务测试,能支持一种业务测试的应用去依赖以及它所用的资源的一个组合。所以我们环境的组成就包括AppCode、数据存储、中间件、网络配置、环境变量等。环境有了,但是不可能每次进行一个业务测试或项目测试的时候,都去重新搭建一套环境,这样成本是非常高的。我们之前去做项目复盘时,对于delay项目大家吐槽最多的是为什么delay?是因为环境问题。所以我们把环境的这些信息做成了模板可配置,这样就实现了资源与信息的积累沉淀。其次是业务巡检。开发同学、测试同学只是去使用提供的环境,服务提供方要保证可用性,让开发同学只是去用它,而不是再去为它的可靠性分担精力,所以我们有业务巡检。我们之前创建一套环境后就实现了完全的资源隔离,相当于有一套环境给全部的应用分配资源,这是对于资源的极大浪费,同时创建速度也很低,所以我们又做了一个软路由环境,基准环境跟项目环境。下面我们通过下图来详细解说。
首先是环境创建的流程,上图中我们可以看到我们包含了环境,即应用及其依赖,所以我们会先锁定资源,包括Kvm、
DB这些东西,然后再进行采集编排,然后去触发任务执行,调度执行。其次是业务巡检,我们会定期去调用业务线提供的一些全链路测试case,定期去执行,验证这个环境的可靠性。同时我们也会去消费一些变更消息,包括配置变更、代码变更、数据变更,去同步这个环境,这样就保证了我们基础环境的自运维。然后是软路由,我们会有一套基准环境,是全链路的,包含了全部的应用,但是对于项目来说,只需要建环境值,包含自己变更的这些应用以及它的一些DB依赖。在真正业务测试的时候,从网关进来,如果在软路由,即自己这个项目环境里边有,我就会走到自己项目环境,如果没有就会请求到基准环境。从这个层面来看,项目对应的环境它只包含自己本次变革的应用,对资源的节约是非常大的。同时因为应用少了,我们创建的速度也提升了,这样就会保证在我们的测试过程跟开发过程中,环境不会成为瓶颈了。下面看如何解决带着问题上线这一问题。
我们的质量文件叫Cable,它会消费各种自动检查手段、自动化工具执行的一些结果,把他们推送的一些消息推送到
IC中,然后我们的质量文件在消费这些消息的同时提供接口给Qodin、发布系统进行拦截跟结果展示。自动化工具我刚才介绍了4种,我们内部还会有一些项目流程、慢查询等自动化工具。这些工具并不全部都是我们来提供的,有很多是业务线来提供的。这是因为我们在实现Cable的时候,采用了一个通用的方式,即定义了一个通用的接入标准——业务线各种检查手段,你只要把你的结果推送IC消息即可,这样的话如果你某个业务线有自己的一些检查工具,你只要按照这个标准去推送消息,我就可以快速地接入,在你的业务线去落地,这样能极大的发挥整个业务对自己质量负责的积极性,同时也会更有利于我们整个公司的质量保证。
① 环境效果这个是基于之前环境不隔离即完全资源独立的情况下做的方案,可以看到我们有应用83个,数据库23个,中间件7个,我们能保证10分钟之内交付,每一次变更都会有一些变更记录。这是基于资源完全隔离的情况,基于上述新方案,我们应用精简后,环境交通速度就更快了。② 质量门禁效果这是质量门禁现在的状况。
我们上述说到,业务线也可以提供各种各样的检查手段。我们现在有丰富的检查手段,业务线根据自己的配置去选择需要的一些手段。这是我们组织维度暂时的质量情况,最终我们做的各发布系统集成的发布拦截。总结这一部分的话就是质量,我们通过多种手段加发布门禁,确保了我们的质量。有了流程,保证了质量,我们现在要去发布上线了。
理想是测试完了,直接一键点击发布按钮上线。但是现实往往不是如此。QA人员发布时,先要去OPS那边申请机器,再去配置发布步骤,即发布的一些相关的信息,配置非常复杂,前期需要许多准备工作。对于开发人员来说,开始运维,如果线上出现了一个问题,要先找到它这个机器的资源,然后再去找应用,找代码,这是非常割裂的。还有一个问题,一旦遇到问题的网络,还要去各个地方找这些信息,定位也十分困难。所以总结起来是什么问题?我们会各种工具平台,虽然大家现在强调一站式的,但是在背后的话,各种资源服务还是不同的Team提供。因为不同的Team提供的时候只关注自己管理的领域,所以它的管理维度是不一样的,这样就会导致管理维度不一样,这些数据信息无法串联起来。
基本属性是身份,Appcode就是它的唯一标识。这里强调一下等级,之前也有人问我等级有什么用,等级是非常有用的,我举个例子,有了等级,你才知道你这个服务的重要程度,你在运维的时候你才能知道优先把资源倾斜给哪些应用,先去运维哪些。
首先是应用确定了自己的应用画像,然后使应用画像存在一个配置系统中,然后调度系统去从配置系统拿到一些配置,完了出发到我们Jenkins,部署到各种的调度资源中。这里要强调的是我们这个地方有一些自定义的阶段,通过这些自定义我们可以把那些非标准的过程纳入进来,业务线就可以在这里去做自己的适配。③ 运维流程运维也是基于一个应用的,当一个应用的某些指标报警,我就可以去快速地找到应用对应的Trace链路、日志、事件系统。
根据这三板斧,我就可以去定位到我的问题,最后对应我们的运维系统去做对应的运维操作。
这是我们的应用画像效果。其中有应用形式配置,包括它的一些服务依赖属性,服务调用属性。上述是我们发布的过程,可以看到在发布过程中我们可以知道当前的发布进度,还会对接我们的异常日志,以及报警信息。还有我们的监控,变更的事件,Trace链路,这三板斧实现了我们对应用的可运维。

流水线的好处我想大家应该都知道,我这边总结两点:
在一般情况下交付到了发布就完成,其实我们在发布完成之后还可以做一些服务治理健康保障,例如我们有触发的压测,以及强弱依赖等。这就是我们具体的实践。我再总结一下,具体实践第一是规范化,保证我们整个流程的顺畅与自动化。第二是多种手段保证质量,质量门禁保证问题的蔓延。第三是拆分应用画像,使画像确定我们的运维最小单元,实现可发布可运维。第四是通过流水线使我们整个流程更顺畅。
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
我认为我的问题最好用一个例子来描述。假设我有一个名为“Thing”的简单模型,它有一些简单数据类型的属性。像...Thing-foo:string-goo:string-bar:int这并不难。数据库表将包含具有这三个属性的三列,我可以使用@thing.foo或@thing.bar之类的东西访问它们。但我要解决的问题是当“foo”或“goo”不再包含在简单数据类型中时会发生什么?假设foo和goo代表相同类型的对象。也就是说,它们都是“Whazit”的实例,只是数据不同。所以现在事情可能看起来像这样......Thing-bar:int但是现在有一个新的模型叫做“Whazit”,看起来
我有一个要在我的Rails3项目中使用的数组扩展方法。它应该住在哪里?我有一个应用程序/类,我最初把它放在(array_extensions.rb)中,在我的config/application.rb中我加载路径:config.autoload_paths+=%W(#{Rails.root}/应用程序/类)。但是,当我转到railsconsole时,未加载扩展。是否有一个预定义的位置可以放置我的Rails3扩展方法?或者,一种预先定义的方式来添加它们?我知道Rails有自己的数组扩展方法。我应该将我的添加到active_support/core_ext/array/conversion
参见下面的示例,我想最好使用第二种方法,但第一种也可以。哪种方法最好,使用另一种的后果是什么?classTestdefstartp"started"endtest=Test.newtest.startendclassTest2defstartp"started"endendtest2=Test2.newtest2.start 最佳答案 我肯定会说第二种变体更有意义。第一个不会导致错误,但对象实例化完全过时且毫无意义。外部变量在类的范围内不可见:var="string"classAvar=A.newendputsvar#=>strin
如果我构建了一个应用程序来访问来自Gmail、Twitter和Facebook的一些数据,并且我希望用户只需输入一次他们的身份验证信息,并且在几天或几周后重置,那会怎样是在Ruby中动态执行此操作的最佳方法吗?我看到很多人只是拥有他们客户/用户凭证的配置文件,如下所示:gmail_account:username:myClientpassword:myClientsPassword这看起来a)非常不安全,b)如果我想为成千上万的用户存储此类信息,它就无法工作。推荐的方法是什么?我希望能够在这些服务之上构建一个界面,因此每次用户进行交易时都必须输入凭据是不可行的。
我正在使用Devise在Rails应用程序中,并希望通过API公开一些模型数据,但应该像应用程序一样限制对API的访问。$curlhttp://myapp.com/api/v1/sales/7.json{"error":"Youneedtosigninorsignupbeforecontinuing."}很明显。在这种情况下是否有访问API的最佳实践?我更喜欢一步验证+获取数据,但这只是为了让客户的工作更轻松。他们将使用JQuery在客户端提取数据。感谢您提供任何信息!凡妮莎 最佳答案 我建议您按照以下帖子中的选项2:使用APIke
我正在开发一个Rails2.3.1网站。在整个网站中,我需要一个用于在各种页面(主页、创建帖子页面、帖子列表页面、评论列表页面等)上创建帖子的表单——只要说这个表单需要在由各种Controller)。这些页面中的每一个都显示在相应的Controller/操作中检索到的各种其他信息。例如,主页列出了最新的10篇文章、从数据库中提取的内容等。因此,我已将帖子创建表单移动到它自己的部分中,并将该部分包含在所有必要的页面中。请注意,部分POST中的表单到/questions(路由到PostsController::create——这是默认的Rails行为)。我遇到的问题是当Posts表单没有正
我是Ruby分析的新手,看起来像ruby-prof是一个受欢迎的选择。我刚刚安装了gem并调用了我的程序:ruby-prof./my-prog.rb但是,输出非常冗长,因为包含所有Ruby核心和标准库方法以及其他gem的分析数据。例如,前三行是:8.790.0110.0100.0000.0013343*String#%7.280.0780.0090.0000.0692068*Array#each4.930.0380.0060.0000.0321098*Array#map这对我来说不是什么有用的信息,因为我已经知道我的程序经常处理字符串和数组,并且大概已经对这些类进行了优化。我只关心我代
我正在按照我一直在研究的研讨会实现“服务对象”,我正在构建一个redditAPI应用程序。我需要对象返回一些东西,所以我不能只执行初始化程序中的所有内容。我有这两个选择:选项1:类需要实例化classSubListFromUserdefuser_subscribed_subs(client)@client=client@subreddits=sort_subs_by_name(user_subs_from_reddit)endprivatedefsort_subs_by_name(subreddits)subreddits.sort_by{|sr|sr[:name].downcase}