导读:高可用架构 7 月 30 日在上海举办了『互联网架构的基石』专题沙龙,进行了闭门私董会研讨及对外开放的四个专题的演讲,期望能促进业界对互联网基础架构的建设及发展,本文是兰建刚分享饿了么服务治理经验。

兰建刚,饿了么框架部门技术总监,前爱立信首席软件工程师,10 年以上高可用性,高并发系统架构设计经验。现饿了么框架工具部负责人,负责饿了么中间件的设计及实施,通过中间件以及研发工具的辅助提升研发人员的工作效率,提升网站的稳定性及性能。

今天我想站在一个大的角度上,看一下饿了么最近一年多的时间,经历的技术上一些痛苦的问题与改进的过程。

为什么讲比较痛苦的事情?昨天和一位专家聊天受益很大,他说人在什么时候能够自我驱动?就是痛苦的时候。 只有感到痛苦,才会有改变。 当然改变有两种结果,一种是彻底放弃沉沦,另外就是一想办法自动化、智能化,把自己变成一个高手。

MVP 原则

我现在也很痛苦,但是还没有放弃。先讲一下 MVP 原则,MVP(Minimum Viable Product) 现在比较火, 一个产品是做大而全,还是可用就行? 我从去年 3 月份加入饿了么,开始组建框架和工具的团队。中间件里面很多东西都可以去做,但是我真的需要把所有的东西都做全吗还是 MVP 原则就好?这是我们思考的一个问题。

MVP 的意思就是做一个最小可用的就可以,大家以前很流行说,“世界那么大,我想去看看”,其实框架很多东西看看就好,做全做好是需要长时间积累的,我们缺的恰恰是时间。我们要做的就是立足现状,解决痛点问题。现在饿了么的现状说白了比百废待兴好一点。 当有太多事情可以去做的情况下,更需要抓住重点,不死人的尽量不要去踏。

服务治理的现状

服务治理是一个很大的话题,它涵盖了很多内容,比如前面晓波老师介绍的 Redis 治理、姚捷老师讲的链路监控系统(参看文末文章),都可以涵盖在里面。

编程语言

先介绍语言,刚才会场一些人说他们是异构的语言,但可能还是没有饿了么这么复杂。饿了么语言主要有两种,Python 及 Java,原来整个公司语言都是以 Python 为主,可以说是上海最大的 Python 大厂。为什么不坚持用 Python?不是说 Python 语言不好,而是招不到人。在业务急速发展的时候怎么办?换 Java 语言就成了自然的选择。

在我进公司的时候,其实不仅仅是这两种语言,还有 PHP,C 语言等。基于这些现状,框架的选择点就比较少。因此做了一些妥协,SOA 的框架有两套,主要是为 Python 和 Java 做的,Python 的叫 Vespense,Java 版本的叫 Pylon,Vespense 和 Pylon 都是星际争霸里面的两种最基本的东西,没有这两种东西游戏根本打不下去。

SOA 框架

SOA 框架里面需要包含什么? 首先必须包含 RPC ,我们的 RPC 有两种:Thrift 和 JSON。Python 使用 Thrift,Java 使用 JSON。为什么 Java 框架重新选择一套 RPC 协议? 主要是觉得 Thrift 对 Java 不太友好。举个例子,用 Thrift 生成的 Java 代码在接口比较多的时候,它的一个文件就超过 20M ,连 IDE 都拒绝分析这个文件。另外 JSON 是纯文本的,因为当初也没有日志系统,也没有链路跟踪系统,排查问题的时候,一种好的办法就是抓包,如果是一个二进制的协议的话那就痛苦。所以最终 Java 选择了 JSON。当然 RPC 都是对业务透明的,SOA 框架会屏蔽 RPC 细节,业务就像使用本地调用一样使用远程服务。

路由我们是基于集群做的,没有进一步细化到机器级别,因为觉得这个就足够了。此外也做了客户端的 SLB,还有熔断、降级、限流,这是保护服务的几大法宝,充分证明了这些东西拯救了我们很多次。经常看到监控群里面说,我们把什么什么服务限流了吧,把它降级了吧,那是因为这个服务可能写的不太好,把它降掉了,保住我们的主要业务。还有一些埋点,全链路跟踪等等,全部都内嵌在框架里面。这样的好处就是, 增加特性只要升级一个框架就可以了 。

服务发现与配置中心

我们的服务发现和配置中心叫 Huskar,这是 DOTA 里面的一个英雄人物的名字,它是基于 ZooKeeper。

负载均衡

负载均衡有好几种, 首先有嵌在 SDK 里的软负载 ,拿到一个服务全部的列表,做一个轮循就可以了。这种策略有一些不足,比如一个 IDC 里面机器型号性能可能会稍微不一样,如果单纯用轮循会产生负载不均的问题。但这个问题当前还不是最紧迫的,我们可以绕过去,只要保证同一个集群里机器型号都是相同的就好。

此外也用中间层的方式,以前我们的 haproxy 用起来比较麻烦,配置复杂,而且它不能进行热加载,一个配置上去了之后需要重启一遍,因此工程师就用 Go 语言写了一个 GoProxy,基于四层,它会从服务中心把你需要的列表全部抓下来,做四层的负载均衡。他可以代理一些没有 SOA 框架支持的语言写的服务,也可以代理其他的基础组件,比如说像 Redis,数据库,它都会代理。

CI / CD 灰度发布

我们有 CI、CD 灰度发布的系统,叫 eless,虽然我们做了 CD 但是百废待兴,目前只有一些基本的单元测试,因为这个太耗工夫了。灰度发布也是基于发布系统做的,我们会在发布系统里面定义集群,每个集群里面的机器又分成不同的组,发布的时候按这些组来发布的,你可以先发一个组,观察没有问题后,然后再发其他的组。

监控与报警

我们有自己的监控和报警系统。 监控现在做的比较简单,是 statsd + graphite + grafana 的组合 。现在最大的问题是监控系统不支持 tags,所有的指标汇聚到一起,一个服务的指标是汇聚在一起的,一个机器或者集群慢了,它会把这些指标分摊到其他机器或者集群上去的,所以查的时候比较困难,所以我们现在准备切成我们自己的系统。

报警系统也是自己写的。 报警系统的需要是快、全、准 。我们现在做的是全,逼着大家去把报警系统用起来,只看监控系统是看不过来。如果线上发生了一个故障,比如交换机发生故障,影响到某个业务,但是业务报警没有报出来,那业务要承担连带责任,因为你没有报警出来。

报警最常见的基于阈值,阈值这件事情比较痛苦,我们有很多指标,但这个阈值怎么去配,需要很有经验的人才能配好,阈值配小了,你会经常收到报警,配太大有可能出问题收不到报警,这个非常痛苦。所以一个同事提出 基于趋势 来配置来判断,我们在一段时间发现趋势在偏离了,就做报警。

我们也在做 trace,前两天终于把拓扑图给画出来,把一个业务所有的调用展示成一个调用树,这样就可以很好的分析业务。我们现在是一个近千人公司,业务系统极度复杂,很少有工程师能清晰说出一个业务到底调用了哪些服务,通过这种 trace 方式来做辅助分析就很有用了。

光展示,我们觉得它的价值还没有利用到极致,可以把所有的调用关系和报警结合在一起。大家分析问题的时候,会发现如果某个点上发生的错误一直往上报,从而导致整条链路失败,那这个点就是 root cause,把它修复就可以问题解决了。我们做 trace 的思路是一样的, 在调用链上进行着色,辅助找到问题的 root cause ,也就是最初发生问题的那个点。

服务治理的经验

我们最重要的经验是做好保护与自我保护。

“不能被烂用的框架不是好框架”,这个是我们 CTO 经常说的一句话。原因是什么?比如我们那个监控的 SDK 曾经被业务错误的使用,每发一次报警就启一个新线程,最后整个进程因为开了太多的线程挂掉了。峰哥(CTO)说你无法预测每个开发者会怎么使用你的框架,即使框架被滥用了,最坏的情况,也需要保证能够活的下去。

所以后面写的东西都严格要求自我状态的检查,比如秒杀的时候,所有的监控系统,链路跟踪系统都是可以降级的,不能因为这些东西导致整个系统崩溃。

框架由于在底层,出了问题最容易被怀疑。比如一个 SDK,使用方说为什么占用了整个集群上 8% 的 CPU?跑过去一看,整个机器的 CPU 才 12%。某种程度做框架其实有无助的时候,容易被质疑及谴责,所以做好自我状态检查是很必要的。

定期线上扫描

为了避免滥用的问题,我们会定期线上扫描。比如一些日志本来就是可以降级可以丢的,但如果开发用了写文件的同步方式,那性能就会变慢,通过扫描发现这些问题,改成异步日志服务性能就会更好。

限流、熔断、降级

这个强调多少遍都不过分,因为确实很重要。服务不行的时候一定要熔断。限流是一个保护自己最大的利器,原来我们前端是用 PHP 做的,没有自我保护机制,不管有多少连接都会接收,如果后端处理不过来,前端流量又很大的时候肯定就挂了。所以我们做任何框架都会有限流措施。

有个小插曲,我们上 DAL (数据库中间件)第一版的时候,有次一个业务怎么指标突然降了 50%,然后大家去查,原来 DAL 做了限流,你不能做限流,你把它给我打开,听你们的我打开了,打开了然后数据库的 QPS 瞬间飙到两万,业务部门就慌了,赶紧邀请我们再给他限制住。这是我觉得 DAL 做的最好的一个功能。

连接复用

还有连接复用,有些工程师并不能特别理解,如果不用连接池,来一个请求就发一个连接怎么样?这样就会导致后端资源连接过多。对一些基础服务来说,比如 Redis,数据库,连接是个昂贵的消耗。所以我们一些中间件的服务都实现了连接复用的功能。

代码发布

上线发布是很危险的一件事情,绝大部分的事故都是由发布引起的,所以发布需要跟很多系统结合起来,所以我们做了整套流程。在每次发布的时候,一个发布事件开始,到我们这个监控系统以及调用链上,调用链就开始分析了, 发布后把它的所有指标比一比,到底哪些指标发生了改变,这些指标如果有异常,就发报警 ,所有发布都会打到监控的主屏上面去,如果出了什么问题,这些事情优先回滚,如果可以回滚,我们肯定第一时间就把问题解决掉了。

服务治理的痛点

配置复杂

超时配置:超时配多少是合适的?100ms?300ms?极端情况有些业务配到 3 秒的。阈值怎么配和超时怎么配其实是同一个概念,并不是所有的程序员都知道超时设成多少合适。那怎么办?峰哥(CTO)想了一个办法,你的监控系统,你的调用链分析系统,你的日志系统,基础监控系统每天产生多少数据?这些数据到底有没有用?是否可以从这些数据里面挖掘出一些东西,比如这种超时的配置,是可以基于它历史的超时配置、所有请求的响应时间去做的。

这件事情正在进行中,但落地有点麻烦,比如说我们请求大概每天有三千万的调用量,你只有很小的一个比例它会超时,但是绝对量是很大的,你设置一个超时值,它可能有三万个请求都失败了。现在一直在优化这个东西,希望下次大家来我们这里的时候,能给大家详细介绍一下这个超时到底怎么做。

线程池配置:刚才说最重要的是限流,你不可能无限制的接受请求,不可能一百个并发你就接收一百个并发,并发到底怎么配?又是很复杂的事情。我经常看我们线程池的配置,这个东西要经过严格的性能测试,做很多调整才能调出来。在做性能测试的时候,其实有条曲线的,有个最高点的,我们在想在实时的过程中计算出这个最高点,但发现这个东西其实挺难的。

我们便用了另外一种方法, 每个线程池用一个排列队列 ,当我发现它在涨的时候我就适当把那个线程池扩大一点,同时我们监测其他指标。如果发现在我扩大并发量的时候这些指标产生了报警,那我就把这个线程调整的操作直接拒绝掉,就保持原来那个大小。如果这些指标证明是没有问题的,那我就把它再扩大一点。

Cache,DB,Queue 的手工配置问题。还有一个是服务治理,Redis、数据库等配置还都是手工的,我们也不知道我们线上有 Redis,怎么办?我们正在做基础服务的服务化,业务其实不需要关心到底连到哪个 Redis,你上线的时候你告诉我你需要多大的容量,填个工单过来,运维帮你配好了,然后通过一些自动化的方式你把这些拿到初始化 SDK 就可以了。

故障定位

还有一个比较痛的问题就是排查问题很难。首先故障定位困难,每次我们出了事情之后,大家各自查各自的,比较低效。问题排查其实是有方法可以做,需要把它自动化,我们现在还缺这个东西,调用链分析是需要考虑去做。

性能退化

我们现在的业务增长量非常恐怖,去年我们是以 5 倍的速度增长了,但其实这个 5 – 10 倍要看你的基数,当基数很大,扩一倍量也是非常多,评估线上到底要布多少台机器是一件很复杂的事情。

我们成立一支性能测试团队,做全链路的压测。基于全链路压测的结果来评估整个系统的容量。这个全链路只能在线上做,也不能在白天压,只能在晚上低峰期的时候做。所以性能测试也是一个比较挑战的工作,不仅仅是智力上,也是身体上的一种考验。

全链路压测试一些服务有时候出现性能下降,比如 QPS 从 500 下降到了 400,但大家并不知道最直接的原因。上次毕洪宇老师也帮我们出了主意,比如把全链路指标拉出来做一下对比,看看哪些指标有变化,可能就是罪魁祸首。

容量评估的方法

容量评估方面容易出现温水煮青蛙的事情,今天流量增长一点没问题,明天再增长一点也没有问题,连续几天然后服务就挂了。这个时候怎么办?只能用最苦逼的方法,找个性能测试团队进行压测。有没有更智能化的方法?我们也正在探寻这条道路。

资源利用率低

资源利用率低的问题。很多团队一碰到性能下降,就希望扩容,这会导致很多时候机器利用率只有 10%(更新一下数据,其实很多服务器的利用率不足1%)。我们正在积极准备上容器化方案来解决这个问题。

服务依赖不清晰

大的系统中,服务依赖的调用链相当复杂,一个业务下去到底调用了哪些服务比较难说清。我们已经在做一个泳道规划。泳道这件事情有多种说法,有的人喜欢所有的服务都做一个大池子,只要保证它的足够容量就可以了,但是我更倾向小集群的思路,因为隔离起来就会更安全。

我们现在还没有做到按用户来区分泳道,目前只是按流量来切,50% 随机,部署的东西都一样。我们想通过泳道把这些流量隔离,VIP 客户可以把他放最重要的泳道里面,一些不那么重要的城市,可以放到另一个集群,如果不得已降级,只能牺牲这些次重要的用户。

服务治理的方向

有痛点就要努力,要么放弃,要么努力,这是我们努力的方向,前面讲了一下智能流控系统,超时推荐我们也做,大数据和智能化才是将来。有些监控数据只是落在磁盘上不用那就是浪费,是不是能把它利用起来?

然后我们也在做 Cache、数据库、Queue 等服务化。

Trace 系统我们也在做,拓扑图画出来,帮助大家了解是怎么回事,我们可以做链路染色,帮你了解问题的根源在哪里,我们也可以做依赖度的分析。我们说依赖分两种,强依赖和弱依赖。弱依赖要处理它,有一个异常出来的时候要把它干掉,不能把这个异常跑到最上面去,那整个服务就都挂掉了,但是大家并不知道到底它是弱依赖还是强依赖,这需要分析,我们去统计一下,它是一个强依赖还是弱依赖。然后弱依赖就可以做一些改进,比如做一些异步调用,节省整个服务的调用时间,优化用户体验。

容量预警我们通过做一些大数据的分析,所有的指标跟订单量这些关联,做一个相似度的分析,当这些指标偏离的时候,我们是不是可以认为它的容量有问题,当然这是努力的方向。

容器方面我们也在做,系统叫 APPOS,有的服务 CPU 只用了10%,但是我们规定了一台服务器只能装一个服务怎么办,那就上容器吧。

Q&A

提问:想问一下报警阈值设定,上面提到的方法是根据趋势来设计报警,这个趋势其实您能做到多少准确?能控制在什么情况下?

兰建刚:准确度的确是个问题,我们用了一个算法叫 3-sigma,准确度还不是特别确定,因为这个东西真的是服务治理里面最大的难题,报警分级怎么分?这是很大的学问,我们现在整个报警系统里面报警通道每天上千个报警,很多都不看的,因为觉得这个报警没什么意义。这是一个实际当中要去调整的问题。

提问:报警存在误报的情况?

兰建刚:对,你要知道我们的业务有两个明显的尖峰,十二点和下午四五点的时候都是订餐的高峰,之后则所有的指标都会有下降趋势的时候,如果你曲线偏离的很厉害就会引发报警。

多指标聚合是我们正在做的,发生一个指标报警的时候可能是一个小问题,但是这个问题会触发一个 CEP 的流程,比如“是不是 CPU 飙高的同时响应时间会抖动?”,我们可以定义这样整个一套规则,去做报警来提高准确度。

提问:刚才您提到用 Go 写的一个东西,为什么选择使用 Go 因为 Go 是自己的垃圾回收机制?而且我想了解一下您认为 Go 它是比较适合什么样的系统?

兰建刚:当然是底层的基础服务了,我们不建议用 Go 写业务。为什么我们选 Go 做工具,是因为我前面提到,公司原来一些工具是搭在 Python 上,有一帮 Python 工程师,让他去写 Java 他是绝对不干的,但是让他去写 Go 语言是没有问题的,Python 其实不适合写底层框架,因为它是个动态语言,工程化方面也会差一点。

提问:刚刚看到您提到超时配置推荐,这块是和你们的应用场景有关系,还是说和你们遇到的故障?

兰建刚:就是因为遇到故障了,因为很多超时配得很乱,有的同学直接配 3 秒超时(这是配置模版里的一个例子,很多同学就拿去直接用了),那还不如不配,有些情况很多服务就是 10ms 就正常返回了。只要保证这件事情对绝大部分的服务来说,是有利可图的,那我们就去做这件事情。

饿了么分布式服务治理及优化经验相关推荐

  1. 美团分布式服务治理框架OCTO之一:服务治理

    写在前面 之前的文章介绍过美团的中间件leaf-code,今天介绍另一款非常强的中间件系统Octo,其实Octo算不上是中间件系统,应该是一整套分布式服务治理平台,美团的很多中间件能力都是通过Octo ...

  2. 分布式服务治理框架Dubbo的前世今生及应用实战

    Dubbo的出现背景# Dubbo从开源到现在,已经出现了接近10年时间,在国内各大企业被广泛应用. 它到底有什么魔力值得大家去追捧呢?本篇文章给大家做一个详细的说明. 大规模服务化对于服务治理的要求 ...

  3. 分布式服务治理框架Dubbo

    前言 Dubbo是一个被国内很多互联网公司广泛使用的开源分布式服务治理框架,是一个非常全面的SOA基础框架,当当网在Dubbo基础上新增了一些功能,并将其命名为Dubbox(Dubbo eXtensi ...

  4. 阿里云开发者学院电子书《Dubbo分布式服务治理实战》重磅来袭!

    简介:Dubbo 是阿里巴巴开源的高性能分布式 RPC 服务治理框架,已经捐献给 Apache 开源组织,最新的版本是 3.0.在阿里巴巴.工行.电信.银联.中国人寿.网易.滴滴.当当等互联网公司中大 ...

  5. 美团分布式服务治理框架OCTO之二:Mesh化

    写在前面 前面的文章主要介绍了美团Octo服务治理框架,随着云原生的崛起,大量服务治理体系普遍"云原生"化,而Mesh则是云原生中非常重要的一个流派,今天我们看下美团的Octo是如 ...

  6. 分布式服务治理zookeeper原理及使用大全

    文章目录 简介 中心化 事务 downlaod 单机安装 集群搭建 Cli连接 集群容错 Master选举 leader宕机重新选举 数据同步 特色功能 服务治理 配置管理 zkui安装使用 分布式锁 ...

  7. 基于nacos的分布式服务治理

    微服务是什么 微服务架构强调的一个重点是"业务需要彻底的组件化和服务化",原有的单个业务系统会拆分为多个可以独立开发.设计.运行的小应用.这些小应用之间通过服务完成交互和集成 微服 ...

  8. 谈谈分布式服务治理框架 Dubbo 重大升级

    为什么80%的码农都做不了架构师?>>>    前言 本文首发公众号 [一名打字员] Dubbo 今年重启维护,并且进行了重大的升级.在 JAVA 社区很多人都知道并且使用过 Dub ...

  9. 干货 | 携程微服务体系下的服务治理之道和优化实践

    作者简介 HongLiang,携程高级技术专家,专注系统性能.稳定性.承载能力和交易质量,在技术架构演进.高并发等领域有丰富的实践经验. 一.背景 微服务架构在中大型互联网公司中被广泛应用,随着业务的 ...

  10. 分布式服务框架Dubbo疯狂更新!阿里开源要搞大事情?

    最近,开源社区发生了一件大事--使用最广的开源服务框架之一Dubbo低调重启维护,并且3个月连续发布了3个维护版本.这3个维护版本不仅解决了社区关心的一系列问题和需求,还让整个社区的活跃度得到了大幅提 ...

最新文章

  1. 在CentOS 6.9上从源码安装Go 1.10
  2. WebServices应用集成框架ESB(Enterprise Service Bus 企业服务总线)
  3. 番石榴15 –新功能
  4. 90后女科学家,四年完成清华大学硕博连读,解决多个世界级难题
  5. Javascript实现简单的选项卡
  6. 什么是Github?
  7. junit.framework.AssertionFailedError: No tests found in错误解决办法
  8. 纯css控制-表格表头固定,内容多时滚动内容
  9. 利用计算机制作图表,利用Excel进行数据分组和制作统计图表.doc
  10. SQL数据库置疑数据怎么恢复
  11. Android webview监听网页对话框点击事件
  12. 用VC进行64位编程
  13. Python文件指针
  14. php 2010excel,Excel2010 工作薄文件扩展名是什么?
  15. FishEye Crucible分析
  16. android刷新时的圆形动画_Android 实现倒计时动画效果
  17. 微信小程序云开发教程-互联网软件产品开发流程和团队分工
  18. 2345浏览器卸载之后如何找回收藏夹中的内容?
  19. [project X] tiny210(s5pv210)上电启动流程(BL0-BL2)
  20. 保险知识一:续期收费与续保的区别

热门文章

  1. 2015级计算机科学与技术2班班级博客大全
  2. stata基本操作(一)
  3. navigate实现页面跳转及传参
  4. Python + 批量裁剪图片
  5. 【阿里巴巴矢量图库搭建一个属于自己的字体图标库iconfont】
  6. 【图像隐藏】基于matlab像素预测和位平面压缩的加密图像可逆数据隐藏【含Matlab源码 2218期】
  7. spamhaus反垃圾邮件联盟黑名单PBL申诉详细步骤
  8. 域名升级访问中拿笔记好_好记性也应做笔记,安利一款比onenote更好用的云笔记工具...
  9. Something‘s wrong--perhaps a missing \item. \begin{thebibliography}{1}
  10. 台式计算机如何升级,电脑硬件如何升级:PC硬件升级不盲目 对症下药最靠谱