Citymobil-创业公司在增长中提高稳定性的指南。 第一部分



在这篇文章中,我将简短介绍两篇文章,其中将详细描述我们如何在几个月内多次提高Citymobil服务的稳定性。 本文以关于我们的业务,任务,出现稳定性提高问题的原因以及局限性的故事开头。 Citymobil是一个快速发展的出租车聚合商。 在2018年,其成功旅行次数增长了15倍以上。 在某些月份中,与上个月相比增长超过50%。

业务突飞猛进(并且仍在增长):服务器的负载,团队的规模以及部署的频率都在增加。 随之而来的是对服务稳定性的新威胁。 该公司面临最重要的任务-不停止业务增长以提高稳定性。 在本文中,我将告诉您我们如何在短时间内实现此任务。

1.问题陈述:我们到底要改进什么


在改进某项之前,您需要学习如何衡量它,以便清楚地了解是否有改进。 测得的值越接近业务友好术语,越好。 因为我们改善业务真正需要的可能性更大。 从成功的角度来看,对我们来说最重要的参数是成功完成行程的次数(以下简称为行程次数)。 正是通过该参数,投资者在做出投资决定时会评估我们。 旅行次数越多,公司的成本就越高。

有些旅行可以赚钱,有些则可以赚钱。 但是,所有旅行对我们来说同样重要,甚至无利可图,因为它们可以让您增加市场份额(实际上,旅行损失是增加市场份额的报酬)。 因此,收到的每一次额外旅行都是好的,每一次丢失的旅行都是不好的。 在业务成功方面,所有旅行都是平等的。

从这里我们得到了一个衡量稳定性的可理解的标准:损失的行程数是由于技术问题而明显损失的行程。 技术问题意味着,例如,代码中的错误,第500个错误,基础架构崩溃,与合作伙伴服务的集成中断(例如Google Maps)。

2.如何计算旅行损失?


行程损失有时很容易计算,有时很难计算。 例如,在完全拒绝服务的情况下,如果根本不起作用(pah-pah-pah),则很容易计算丢失的行程。 我们知道了跌倒前出行次数的趋势图,看到了跌倒后该图的趋势,我们完成了从简单开始的点到结束的点之间的线。 在此完成的线下的行程数图形区域是丢失的行程。

在下图中,黑线显示了某天的行程,绿线显示了一周前的行程。 X轴是时间。 在Y轴上,在一定时间间隔内围绕点X的行程数。以锐角三角形的形式向下看到一个清晰的峰值。 该三角形的面积是旅行次数的损失。 当然,这是一个大概的数量,因为 该图是波动的,但我们知道,即使10-20%的准确度也足以让我们估算企业的事故规模。



如果简单不是完整的,而是部分的(也是pah-pah-pah),则计算会稍微复杂一些。 例如,如果有一个错误导致10%的订单从未被汽车分配,那么我们会发现旅行计划失败,然后反弹(修复错误之后)。 在类似的情况下,旅行损失是趋势线上方的区域; 从底部开始-行程的实际时间表,向左-停机时间开始的垂直线,向右-停机时间结束的垂直线。

下图显示峰值下降不是那么明显,但是前一周没有峰值下降的出行有助于理解峰值下降是一种损失。 此外,将当天和一周中同一天的行程与上一周的行程进行比较,可以清楚地看到,最右边的高峰期不是丢失的行程,而是一天中该时间的常见故障,因为 它与前一周相关。



通常很难建立趋势线,因为 锯齿图。 在这种情况下,每周比较可以帮助我们。 如果您在同一张图表上绘制两条线-上周和当前一周-事实证明正负曲线的形状相似,但不同之处仅在于一条曲线位于另一条曲线之上(本周通常的周数高于上周,尽管有例外)。 每周之间的比较很重要,因为由于不同的情况,一周中的每一天都有不同的计划表。 查看每周的图表,您可以了解当今旅行的趋势线可能在哪里。

显然,一次旅行本身比一个旅行本身要大得多。 想要以一种或另一种方式离开的客户会离开,例如,使用一项竞争性服务,随后可能不会返回我们,或者仅在竞争对手感到失望时才返回,这不太可能,因为 竞争对手非常强大。 而且,即使竞争对手使客户失望,客户也不是他会回来的事实,因为一切都会在他的脑海中出现,因此每个人的服务都会很差,跳过竞争对手也没有意义。

也就是说,由于技术问题而造成的一次旅行损失实际上意味着几次旅行。

为了避免混淆,我们将因技术问题直接损失的旅程主要损失的旅程以及因离开竞争对手而损失的旅程称为次要损失旅程

理想情况下,要计算一次主要损失旅行对企业造成的总损失,您需要了解它造成了第二次损失旅行的多少。 即 必须将初始旅行损失次数乘以某个系数K ,该系数可以根据使用该服务的平均频率和离开竞争对手后返回用户的平均时间来计算。

K系数不随时间变化的假设下,为了了解旅行损失的趋势,考虑主要旅行次数并尝试减少其数量就足够了,因为主要旅行次数与期间的比率将与次要旅行期间与期间的比率相同期间。 示例:如果上个月我们损失了1000次主要旅行,那么次要旅行就损失了1000 * K ,总共我们损失了1000 *(1+ K )。 此外,如果在当月我们损失了500次主要旅行,那么次要旅行则损失了500 * K ,而我们总共损失了500 *(1+ K )。 同时,无论K系数的值如何,我们开始损失的行程减少1000 *(1+ K )/(500 *(1+ K ))= 2倍。

即使系数K随时间变化,即 是时间K(t)的函数,那么我们仍然对减少一次主要旅行次数感兴趣。 因为如果K(t)随时间增长,那么我们更有义务去减少较少的一次旅行,因为 失去每一个人造成的损害越来越大。 另一方面,如果K(t)随着时间的推移而降低,则意味着由于某种原因,尽管服务质量不佳,用户也越来越忠于我们,这意味着我们必须满足他们的期望!

总计:我们正在努力争取减少主要旅行次数。

3.好的,我们考虑了丢失的旅行。 接下来是什么?


配备了用于衡量损失行程的易于理解的工具,我们转向最有趣的部分-如何减少损失? 虽然不会减慢当前的增长速度! 从主观上看,由于丢失旅行而导致的技术问题中绝大部分与后端有关,因此我们决定首先关注后端开发过程。 展望未来,我会说结果就是这样-后端已成为丢失行程的主要战场。

4.流程如何进行


问题通常是由于代码滚动和其他手动操作引起的。 永不更改且永不接触的服务有时也会失败,但是此例外只是确认规则。

根据我的经验,最有趣的例外是以下服务。 当我2006年在RBC工作时(上帝,我几岁!),然后在RBC的一个邮件服务上有一个网关,所有流量都通过该网关通过,并检查IP地址是否被列入黑名单。 该服务在FreeBSD上可以正常使用。 但是有一天,他停止了工作。 猜猜为什么? 磁盘在本机上碎裂(坏块堆积,堆积和堆积)。 在拒绝服务之前的3年中崩溃了(!)。 一切都散布在磁盘上。 然后,出于Phryakh动机未知的任何原因,“ frach”决定突然变成一块破损的磁盘,最终冻结。 我确信Linux不会那样做。 但这是一个独立的霍利瓦尔。

综上所述,这些问题是由于手动干预造成的。 在我10到12岁的童年时期,一次去森林旅行时,我曾听过父亲一句话,这是我一生都记得的一句话:“这样,篝火就不会熄灭,只需要抚摸它就可以了。” 我想我们很多人都记得当我们把柴火扔进已经燃烧的大火而由于某种未知原因而熄灭的那一刻。

最重要的是:问题是由人的手动操作造成的,例如,将木柴扔进已经燃烧良好的火中,从而切断氧气并扑灭大火,或者在生产中发布带有错误的代码。 因此,为了了解服务中出现问题的原因,您需要准确了解部署的发生方式以及开发过程的工作方式。

该过程完全专注于快速发展,并组织如下:

  • 每天20-30个发布;
  • 开发人员自己推出;
  • 开发人员在测试环境中进行快速测试;
  • 最少的自动化/单元测试,最少的评论。

实际上,处于最困难条件下的开发人员面对QA时并没有掩盖后方的区域,他们有大量对企业来说很重要的生产任务和实验,需要集中精力并进行协调,以简单的方式解决了复杂的问题,不允许代码“增长”,无法理解业务问题,非常负责任地进行更改,迅速将空闲状态回滚。 Citymobil在这里不是唯一的。 8年前,在Mail.ru Mail中,当我来到那里工作时,发生了类似的情况。 而且,我们也迅速而简单地启动了Mail.ru Cloud,而没有礼貌。 并且随后已经更改了过程以实现更大的稳定性。

当然,您自己注意到了这一点:当没有人遮住您的背时,只有您一个人在生产时,当巨大的责任负担消灭时,您才能创造奇迹。 我本人也有这样的经历(甚至更顽固)。 曾几何时,早在上个世纪(猜想,互联网已经在上个世纪,当我记得时,我自己很惊讶),我是newmail.ru邮件服务的唯一开发人员,自己进行了部署,还亲自测试了生产通过if (!strcmp(username, “danikin”)) { … some new code… } :-)来给自己看,因此,这种情况很接近我。

如果我知道采用这样一种简单的方法“屈膝”,那么许多成功和失败的初创公司,无论是成功还是失败的,但出于同样的热情-专注于快速业务增长和市场占领,我并不感到惊讶。

为什么在Citymobil中专门进行此过程? 最初,开发人员很少。 他们在公司工作了很长时间,对代码和业务有很好的了解。 每天进行几次发布。 错误非常罕见。 在这些条件下,该过程运行完美。

5.为什么一个好的过程会威胁到稳定性?


随着项目投资的增加,我们使产品计划更加激进,并开始雇用许多开发人员。 生产的部署数量有所增加,但是由于新成员深入研究了战斗条件下的系统和业务本质,预计其质量会下降。 随着显影剂数量的增加,稳定性甚至开始呈线性下降,而不是呈线性下降(推出数量呈线性增长,平均推出质量也呈线性下降;“线性” *“线性” ==“二次”)。

显然,以这种形式离开流程是不可能的。 它根本没有在新条件下被监禁。 但是有必要在不影响上市时间的情况下进行更改,即每天保留20-30个发行版本(并且发行数量与团队规模成正比)。 确实,正是在大量发行中才说明了这一点。 我们发展迅速,建立了许多实验,迅速评估了结果并建立了新的实验。 我们快速测试了产品和业务假设,对其进行了研究,并提出了新的假设,我们再次对其进行了快速测试,等等。在任何情况下,我们都不想降低这一比率。 而且,他们想增加它,并提高雇用开发人员的速度。 即 我们针对业务增长的行动对稳定性构成了威胁,但我们不想以任何方式纠正这些行动。

6.好的,任务很清楚,过程很清楚。 接下来是什么?


拥有Mail.ru Mail和Mail.ru Cloud的经验,从某种程度上讲,稳定性一直被放在最重要的位置,每周进行一次首次发布,详细描述了详细的功能和测试用例,所有内容都包含在自动和单元测试中,我至少对代码进行了一次审核,有时甚至是三遍,我遇到了一个全新的情况。

看起来一切都很简单:在Citymobil中像在Mail或Cloud中一样重复该过程,并提高服务的稳定性。 但是,就像在那个淫秽的玩笑中一样,有一些细微差别:a)Mail / Cloud中的发布每周执行一次,而不是每天30次,在Citymobil中,我们不想牺牲发布频率,b)Mail / Cloud中的所有代码在自动/单元测试中涉及到的问题,在Citymobil中,我们没有时间和资源来进行这项工作,后端开发的所有力量都专用于测试假设和产品改进。 同时,后端开发人员甚至在高招聘速度上都缺乏身体(特别感谢HR Citymobil,这是世界上最好的HR!我认为将会有关于我们HR流程的另一篇文章),也就是说,没有办法密切参与测试和审查不放慢脚步

7.当您不知道该怎么做时,请从错误中学习


那么,我们在Citymobil中做了什么神奇的事情? 我们决定从错误中学习。 通过从错误中学习来改善服务的方法与世界一样古老。 如果系统运行良好,那就很好。 如果系统有错误,那么这也很好,因为您可以从这些错误中学习。 听起来很简单。 做...也很简单。 最主要的是设定目标。

我们如何学习? 我们从一开始就认真记录每次重大和次要事故的信息。 坦白说,起初我并不是很想这样做,因为我希望能创造奇迹,并认为事故会自行解决。 当然,一切都没有停止。 新现实无情地要求改变。

我们开始将所有事故记录在一个通用的Google表中。 对于每次事故,提供了以下简要信息:

  • 日期,时间,持续时间;
  • 根本原因
  • 他们为解决问题所做的工作;
  • 对业务的影响(旅行次数损失,其他影响);
  • 结论。

对于重大事故,我们创建了单独的大型文件,其中包含从事故开始到完成的每一分钟的详细描述:我们做了什么,做出了哪些决定(通常这样的描述称为事后分析)。 在总表中,我们添加了此类事后评估的链接。

该文件的目的是:得出结论,该结论的实施将减少旅行损失。 此外,准确表述什么是“根本原因”以及什么是“结论”非常重要。 这些词本身是可以理解的。 但是每个人都以自己的方式理解。

8.他们学到的一个错误的例子


根本原因是消除这种情况将防止将来发生类似的事故。 结论是如何消除根本原因(或减少其发生的可能性)。

根本原因总是比看起来更深。 结论总是比看起来复杂。 为了不让局势平静下来,不谈到底是什么,必须始终对所谓的根本原因不满意,对所指称的结论也始终不满意。 这种不满创造了进一步分析的热情。

让我给你举个例子:推出代码-一切失败,退回-一切正常。 根本原因是什么? 您说,推出。 如果她不在,那就不会有意外。 那么结论是:不推出? 结论不正确(准确地说,对业务有害)。 也就是说,这很可能不是根本原因,您需要更深入地研究。 推出一个错误 。 根本原因? 比方说 如何解决? 通过测试,您说。 什么测试? 例如,所有功能的完全回归。 记住,这是一个很好的结论。 但是,在没有完全回归的情况下,必须时刻改善稳定性。 需要更深入地挖掘。 由于我们在数据库中的表中调试了打印,将其加载到无法测量的状态,并且数据库在负载下损坏,因此推出了发生了一个错误的错误 。 这已经更加有趣了。 显而易见,即使是完整的回归测试也无法使您摆脱这个问题。 毕竟,测试库的负载与生产负载不同。

如果您进行更深入的研究,此问题的根本原因是什么? 为了找到答案,我们与开发人员进行了交谈。 原来,他已经习惯了底座可以应付负载的事实。 但是在项目快速增长的情况下,该基地昨天进行了管理,但今天不再存在。 我们中很少有人从事过每月增长50%的项目。 例如,对我来说,这是第一个这样的项目。 投入这样的项目后,您便开始意识到新的现实。 直到您第一次遇到任何东西,您都不会知道会发生什么。

开发人员立即提出了解决掉落原因的正确解决方案:对文件进行调试打印,通过cron脱机将文件通过流单次写入数据库。 如果调试打印过多,则数据库将不会躺下,只是调试信息会不时出现在其中。 显然,该开发人员已经从他的错误中学到了,以后将不再重复。 但是其他开发人员也需要了解这一点。 怎么了 需要告诉他们。 如何让它听到? 从头到尾告诉他们整个故事,解释故事的根源,并立即建议如何做,以及倾听他们的问题并回答他们。

9.从这个错误中您还能学到什么,或者做与不做


因此,我们继续分析此事故。 公司发展迅速,新员工来了。 他们将如何从这个错误中学习? 告诉每个新员工? 显然,会有越来越多的错误-如何使每个人都从错误中学习? 答案几乎是显而易见的:得到一个“做与不做”的文件(读作“ doos and donts”)! 在免费翻译成俄语的过程中,成语的“做与不做”表示“什么是好,什么是坏”。 在这个文件中,我们写了关于开发主题的所有结论。 我们将文件显示给所有新员工,并在每次更新文件时在开发人员的常规聊天中显示该文件,并恳请大家再次阅读该文件(以便同时更新旧知识和新知识)。

您会说并不是每个人都会仔细阅读。 您会说许多人在阅读后会立即忘记。 而且您两次都是对的。 但是您不会否认某人的头脑会有些变化。 这已经很好。 根据Citymobil的经验,开发人员非常重视此文件,而忘记一些课程的情况非常少见。 顺便说一句,忘记课程的事实可以被认为是一个问题,可以从中得出结论,即了解细节并了解如何改变未来的过程。 很多时候,这种挖掘使“该做与不该做”中的措词更加准确和清晰。

从上述事故中得出的结论是:创建一个“做与不做”文件,将您学到的东西写进去,向整个团队展示该文件,并要求所有新来者进行研究。

根据我们在事故分析中理解的一般建议:不要使用“人为因素”这一短语。 您一说完,他们都立即了解了这一点,因此无需执行任何操作,不需要结论,人们错了,错了并且将是错误的。 因此,代替发音这个短语,有必要得出一个具体的结论 。 结论-这至少是一个很小的步骤,但是在更改流程,改进监控,改进自动化工具方面仅一步之遥。 从这么小的步骤,就可以缝制出稳定的服务!

10.代替结尾


第二部分中,我将根据Citymobil的经验向您介绍事故的类型,并深入探讨每种事故的细节,并告诉您我们从事故中得出了什么结论,如何改变流程以及引入了自动化技术。 第二部分最有趣! 敬请期待!

Source: https://habr.com/ru/post/zh-CN444818/


All Articles