软件开发架构师

新浪微博自动化运维平台实践

运维 56 2019-03-11 10:41

在传统的软件行业,运维和开发应该是完全不同的工作理念以及团队,两者之间会有很深的壁垒。而产品运维和传统运维有一定的区别:产品运维是在基础运维和开发之间的团队,主要工作是运用运维技术来解决产品在快速迭代过程中引发的稳定性相关的问题。我们和传统运维根本上的区别,就是我们要拥抱快速的变化,我们所有的成绩收益都是来自于产品,而不是单独来自于稳定性。这点可能跟传统运维人员不太一样,我们光稳其不行,还一定要快。

接下来我会从四个方向跟大家分享微博平台是如何做稳定性相关的自动化平台。

  • 业务背景。只有了解我们才会明白我们为什么要这么做,我们是怎么做的。

  • 我们的痛点。我在 2011 年加入微博,当时微博的月活量还非常低,现在微博用户量爆增,我们是怎么在持续的过程中扩展运维平台以及遇到的一些问题。

  • 第三个就是分享我们在自动化平台建设的时候的一些想法,和最终实践落地的成果。

  • 最后是我们对后续运维发展的思考,以及一些初步的尝试。

业务结构

这个图很简单,主要给大家介绍一下微博平台在微博当中到底处于什么地位。最早微博是没有微博平台的,当时微博做了一版 Web 类似于交互式的互联网产品。12 年左右开始发展 Open API,做周边生态。

从 Open API 慢慢做成微博平台,相当于是在给 Web 主站,也就是 Web 页的微博,以及手机客户端,还有一些第三方 App 提供所有微博数据的接口。

这些数据包括:

  1. 微博数据,用户数据,以及一些聚合关系,比如我们的 Feed,一些聚合流是在我们这层做的。底层也会依赖一些其他的兄弟部门,比如我们会收到成形的广告,加到 Feed 里。

  2. 反垃圾,也就是一些鉴黄、反政府,还有一些政府部门介入的手段。

  3. 大数据。一些数据分析的成果,会放到微博平台作为 Feed 流集成的参考。

  4. 通行证认证,以及一些推荐的算法。

  5. 最后是其他一些底层和基础组件。

服务类型

只有了解了我们有哪些类型的对外服务,我们才能针对性的加一些监控、代码发布,以及后续维护当中的一些针对性的监控工具。

目前我们的服务类型有:

  1. 基于 http 的 Web 服务,这是比较经典的互联网产品路线,对外提供一些接口,包括设计的技术栈、DNS、负载均衡等。

  2. 我们开源了 motan 框架,做了一个基于 motan 协议的 rpc 服务,这块服务目前占了微博平台一半以上的任务量,都是通过这种 rpc 服务调用实现的。这种实现的好处在于它的并发量上,请求的复杂程度上会比 http 要轻一些。难点主要在于,因为是自研的框架,可能在周边中间件的支持上,没有基于 http 的方便。

  3. 队列处理服务,因为微博有很多的任务,比如说发微博这种微博同步都是异步做的。

我们所有的服务就是这三种类型。我们会根据这三种类型制订不同的运维协议,让不同的开发可以快速接入,减少我们对于特定性业务的运维开发成本。

基本业务数据

具体数值大家可以参考微博历年的财报。目前微博的 DAU 是两亿,MAU 四亿,RPC 达到了万亿,接口是六百多亿,设备已经达到了一万家。

这里主要介绍一下我们现在运维相关的数据。

  1. Docker 的覆盖率。微博使用 Docker 应该算是业界比较久的,而且是属于前几名大规模使用的场景。在 15 年的时候已经达到了两三千个实例的规模。弹性扩缩容方面也做了很多的工作。

  2. 变更次数大概是每周 30 次。这里讲的是重大变更,不是指细节代码发布这种,而是说要涉及到上下结构的这种变更。细节的变更每天有上百次左右。

  3. KPI 是四个 9,平均耗时是五十毫秒。

  4. 我们的故障分很低,主要是因为互联网产品,前期快速发展的时候,对稳定性需求没有那么高。而微博已经经历了很长时间,作为一个互联网产品,它也算是一个中老年产品了,对稳定性的要求目前已经越来越苛刻了。

遇到的问题

接下来就跟大家分析一下我们具体的工作当中遇到了哪些问题。

  1. 峰值挑战。微博的业务形态跟其他的产品不太相同。从日常峰值到热点发生之后的峰值,这个时间大概也就十分钟左右,但是峰值可能比日常峰值涨了三倍,这是非常夸张的数据。我们的峰值来的快,而且上限也非常高,如果全部用服务器扛最高的峰值,这样利用率太低了,而且成本非常高。这种情况一年可能也没有几次,但是我们还得要扛的住,这个就是一个很大的问题。

  1. 周边产品多。虽然大家使用的场景基本就是发微博,看 Feed,但微博的周边产品是非常多的。比如直播答题,段视频,群聊等。微博在周边产品的研发也非常多,这样我们的需求就非常多,因为这种业务类型对于技术的场景是不一样的。比如直播,要求长链接服务非常健壮。这跟微博就不太一样了,微博基本大部分都是短链服务。而长链服务从代码发布到监控,体系维护都是完全不一样的。

    我们现在目前所有的变更,大概每日是四百多次,光 2018 年我们增加的服务池数量就一百多个,而且我们还要支撑 7×24 代码发布的需求。我们这个团队大概有十几个人,但是我们没有人是全职做 7×24 的,这也是一个很大的挑战。

  1. 还有一个很大的问题就是稳定性的需求非常高。可能大家觉得只有微博用户在意稳定性,其实并不一定,我们还有很多的稳定性相关需求。

    • 来自于政府的稳定性需求,大家不要小看微博挂了会影响用户多少,其实政府对我们的投诉也很严重,在热点事情发生时我们不能挂。
    • 群众的需求。
    • 来自客户的需求。很多依赖我们的一些第三方服务,会去拿微博的数据,做他们自己的产品和宣传,很多都是付费的。这些客户对稳定性要求也比较高。
    • 最后就是产品对稳定性的需求。产品对稳定性的要求也是非常高的,一般是出了问题之后,产品赶紧就会在群里喊,各种技术赶紧出来查问题,我设计的产品又挂了,我们对稳定性的要求也是来自于这些方面。
  2. 技术上的挑战。作为运维来讲,我们这些年经历过的技术栈是非常多的。不管是从语言上,工具上,还是从传统的设计理念上都已经发生了改变。

举个最简单的例子,Nagios、Zabbix 是传统运维经常用到的一些监控报警相关的开源组件,比较好用,能收集一些基础数据。但是这些年又开始出现了 ELK,还有 Graphite 这种分布式的,它不能算是一种监控体系,它是一种数据分析体系。而现在越来越多的监控是基于大量数据分析而得出结论,这种体系又开始变得开始火爆起来。还有容器化的配管变化也很大,最早 Puppet,就已经被运维同学称为运维神器,解决了我们很多问题,但是现在越来越灵活。所以看运维而言,近十年的技术变化就已经是非常大的了,技术挑战也是非常大的。

自动化运维实践

接下来跟大家分享我们在自动化方向的实践。刚刚也跟大家讲了我们的背景,我们是做什么的,我们的环境是什么样的,别人对我们的需求是什么样,以及一些我们遇到的一些难点,那我们具体是怎么去做这个东西的呢?

运维职责

我们把运维体系基本整合了一下,我们要对外提供哪些服务?比较简单,首先就是监控,我们要知道业务现在到底是什么情况。

其次就是一些变更的需求,包括:

  1. 系统变更,这些就是由运维人员自己发起的,调整系统参数和架构等的一些变更。

  2. 开发人员提供给我们的代码变更,产品的迭代。

  3. 环境的搭建,比如说一些新项目上线了,它需要一些测试环境,AB 环境,或者一些线上环境的调优、搭建等等的,这些都是一种变更。

最后,就是资源协调,运维同学很多时候就是在把一部分服务器迁到另外一部分服务器,去协调服务器以及协调网络,协调机架等一些资源协调,以及跨部门之间的一些协调。

上图右边,就是我们的报警。报警要贯穿我们所有的运维体系,任何一步出了问题,都要收到报警。我们把监控和报警拆开了,单独做报警。

技术理念

接下来分析一下我们的技术理念。我基本把它总结成四种方向了。

第一种就是脚本驱动。这是传统运维同学非常熟悉的,作为一个合格的运维,Shell 脚本应该是必不可少的一个技能。Shell 脚本可以节省人力成本,而且学习成本比较低。但是它 Shell 本身并不是一种开发语言,而是一种脚本语言。它周围的开发框架,或者开发文化,并不能够让它去做一个大型项目。

第二种就是商业服务驱动。就是我们自己做不好的,那就花钱买,这在国外是非常流行的一种文化。短期而言它是一种比较省钱的模式,而且它提供的服务质量会非常高。

还有一种,就是目前互联网比较流行的,使用一些开源的组件满足日常需求。开源技术从成本角度而言非常适合互联网产品,因为互联网产品可能前期的资金流比较紧张,而且它需要的场景比较特定,可能一些开源的服务。

最后还有一种就是自研。但是自研和脚本驱动,我觉得还是有一定的区别。自研要组建自己的产品加研发的自研体系。如果没有对整套运维体系有一个产品的理念,作为一个类似于产品经理的角色去规划运维平台的话,可能在后续的扩展或改造过程当中会非常的痛苦。如果是想自研一种服务,能作为一种自研服务的驱动的话,它至少应该组件一个产品加研发的自研体系,通过这种自研的能力来提高我们团队的技术稳定性。

当然对于不同的驱动,对于技术的要求,对于产品的要求是不太一样的,也不能说哪个好,哪个不好,当然要看自己的实际需求和自己的能力。

新浪微博平台运维自研体系

然后讲一下我们现在自研的体系。

我们做了比较大的中控平台,叫 ECO。它主要负责接洽所有底层组件,以及上层的应用组件的中间层,以及调度层。左右是依赖于公司传统体系的系统,包括成本控制,服务器申请,采购等流程,是由公司的传统体系来搞定的,以及包括 IDC 的一些调整,网络调整一些工单等等的,是 IDC 的运维系统。

我们对每个产品定制的体系是通过中间这个体系来做的。这个体系的上层包括 DCP、Graphite、EVA,类似于微信小程序的这种功能。

  • DCP 是一个混合云产品,它有一个开源版。
  • Graphite 是主要的监控体系,当时没有选用 ELK,主要是因为 ELK 虽然强大,但是在灵活性方面可能比 Graphite 要稍微差一些。
  • EVA,就是我们基于手机做的移动端运维工具,我们把代码发布、变更降级等紧急的,需要实施操作的一些问题集成到一个手机 App 里面,做这种移动运维。
  • 底层我们目前只是依赖于实体机,一些公有云服务,以及我们自己搭建的私有云服务,来组成底层的基础环境。

ECO 主要模块

这个是我们 ECO 中控平台的几个比较重要的模块,包括我们的 CMDB 模块,它跟公司的 CMDB 可能有一些区别。公司的 CMDB 更倾向于服务器的硬件属性,我们的 CMDB 更倾向于公司的产品属性。包括它上面跑的是什么产品,它的服务参数,会存在这个 CMDB 里。

监控

我们的监控中心主要是做一些监控数据的指标的规划,具体底层实践是由其他组件去实现的。报警中心主要处理报警规则以及报警的聚合。

很多的服务,尤其规模体系庞大,结构复杂的时候,出现一个问题,如果报警太复杂,可能会收到 N 多条报警,这时候手机或者邮件会瞬间被报警轰炸。我们做了这个报警模块主要也是为了通过一定的规则聚合这些报警。如果报警加的太多,反而就没什么用了。

不同报警阈值的设定,我们会通过一个相对复杂的策略,在策略中心进行过滤,然后通过通知机器人的方式做一些域处理。

我们在处理异常问题的时候,是希望不会处理重复的问题,这样可以减少日常维护,这样才有精力去开发这样一个系统。

底层工具

很多业务的迭代过程当中,业务和业务之间会有一些小小的不同,这些不同有的可以通过配置去解决,有的只能通过编码来解决。这种情况下,我们会通过组件小的工具,通过配置管理把它组装起来。就类似于以前的插版模式,通过快速地把不同的插板,可能换一个小的插板,组建成另外一种模式的工具,来适应新的技术体系,通过配管工具把这些插板,把组装规则记录下来。新的业务上线,或者新的架构上线的时候,我们只需要改动某一个插板,添加一下它每个插板的组合和配置,就可以快速地适应一个新的业务体系。

底层就是我们做的一个通道,就是给服务器做的 agent server 的交互通道,这个也比较简单。接下来还有底层的一些外部系统,包括刚才说的 DCP 系统,也就是我们的混合云系统,做弹性扩缩容的。还有就是底层的网络组的,提供的 DNS 变更的一些系统,和一些公司其他系统,或者说我们在打通系统时,所有的这个口都是通过 ECO 来提供的。

ECO 系统页面

接下来展示一下我们做的这个页面,为什么说做工具体系的时候,需要产品的介入呢?在传统运维做工具的时候,很多细节很容易被忽略掉。而当系统工具体系不太好用的时候,操作起来就不方便,会给一线员工的操作带来困难和障碍。如果把这个产品做得好,或者说能够快速地有一个人去收集这些需求,然后把它提成一些开发的需求来去更新的话,可能会做得好一些,用起来会更爽一些,也可以促进你每开发一个运维系统的下推。

报警体系

这个是我们的报警体系。我们所有报警的配置,是基于 Graphite 体系的,但是报警的策略,就是我们要筛什么样的数据进行监控,是在这里做的。这里是一些具体规则的配置,也是可以快速变更、添加、修改等等的。

这个是我们的一个发布体系,我们做这个的时候,也是有很多比较细节的东西大家可以参考一下。

比如步长这块。很多互联网产品为了在发布过程中不影响线上服务的使用,会做步长这个概念。但是我们在做步长的过程当中发现,同样发微博的池子,可能在 ABC,三个 IDC 机器数是不一样的。但发布过程中,比如两百台机器的池子,每次的步长如果按绝对值来算,可能第三个 IDC 它就直接挂掉了。我们就采用绝对值和百分比相结合的方式,以保证我们迭代的步长,就是大的服务池可以快点做,比如说台数多一些,小的服务池可以慢点做,这个是我们在使用过程当中提的一些具体的需求。也包括下面这个,每台服务器实时变更的情况,比如说它是成功、失败,具体的信息,以及可以重做等等的一些具体的需求,这个也是在我们的核心体系开发完之后,逐渐增加的适用性功能。

Graphite 体系结构

Graphite 是一个开源监控数据收集体系,它虽然很灵活,但是它面对比较大的数据量收集的时候,可能会有一些架构上的问题。我们做了一些架构上的调整,比如说本机数据收集的 Logtailor,它本身就启动一个进程,后面加一些参数的简单的 Shell 进程启动的方式,我们通过把里面的代码重构,和配置文件结合,形成了这些 Logtailor 都是无状态的,在任何一台服务器上启动,都会收集该台服务器所在的应用,所需要收集的数据,以及它的收集方式,都是自适应的。

后面的 statsd-proxy 这块,就是我们收集上来数据之后,要做什么处理?因为我们的监控体系是以 Graphit 为这个层,我们上层不只有 Graphite 自己原生的监控展示,也会有手机端,也会有 UI 展示,所以它在数据缓存的方面是不一样的。我们会根据不同的展示需求,又把集群做成 10 秒集群、60 秒集群和 30 秒集群,他们会对不同的数据做缓存,这样当你拿不同的定制数据的时候会快速地拿到,这样比读 DB 要快很多。

底层的数据库我们也换了,换成了 OpenTSDB。在上下行的时候,我们也做了上下行分离,右边是做同步、并发的数据下发,这样可我们在获取数据的时候能够快一些。之前一些监控体系,如果大的话,大家应该也有这种痛点,就是想出图非常慢,这个底层数据库根本没法支持我们的需求,可能十几张图同时在那读数据,几百个池,如果我们把下行做了分离之后,它是通过这种方式来快速配合缓存,来实现我们的监控数据的。

这个就是我们其中一张 Dashboard,这个 Dashboard 涉及的数据 Key 大概有一百多个。大概的思路就是可以把一些监控的指标聚合,后续我们还会再聚合一些操作的指令,当然我们还在研发,目前还没法见人,大家先看看这个原生的,还有很多更好的界面。

混合云系统架构

接下来讲一下我们 DCP 混合云体系。这个混合云体系,应该也是在 Docker 技术刚刚盛行的时候就开始去尝试和推广,我们用过的调度层也非常多,目前可能就剩 K8S 比较强大了,当时我们做的时候并没有,也是调研了很多调度层。我们做了混合云当时就是想把它做成开源的状态,在调度层目前流行的调度都可以接入。

实现的主要功能包括服务池的管理,以及变更的扩缩容,还有日常的变更,以及降级封杀,代码发布。上层支持的语言也很多,Java、PHP 现在都已经支持,包括一些数据库、缓存都可以用它来做同步扩缩容。底层 Pluto 系统,也是一个子模块,主要做的是主机管理,它现在也包括支持私有云和公有云。这三层结构也是基于当时 Docker 比较火的三层结构,三驾马车来做的这个情况。左边的基础组件,这些是其他的一些模块,可以快速地接入进来,我们只是开放了一个接口,大家可以根据自己的情况自己去定制,看你自己实际用的是什么镜像中心了。

单元化扩容架构

普通的扩缩容大家应该是比较了解,就是申请虚拟机,挂负载均衡,获得请求。我们在做直播答题这种特殊业务场景的时候,采用的是这种单元化的扩容方式。

我们和阿里云当时是深度合作,我们用的负载均衡是它的 SLB,但是单 SLB 扩多 ECS 的时候,会频繁断连。也就是说,如果一百个用户已经进答题的场里面了,连接已经建起来了,但是如果想把这个 SLB 下面再挂一百台机器,你需要重启这个 SLB,已经进场的这些用户就相当于要重连,这个成本是非常高的。

可不可以用多 SLB?多 SLB 也有一个问题,就是每个 SLB 大概有 30 多个核,当然根据型号不同不一样,每个核会单独计算连接数,长连接服务的特点是,比如你有 50 个 SLB,每个 SLB 有 30 个核,这样就有 1500 个核,同时第一个请求都会发到第一台服务器上,导致第一台服务器上有 1500 个连接,而其他服务器没有连接,就会出现这种情况。足够多的时候可能第一台服务器扛不了 1500 个就挂掉了,而且长连接的连接迁移是比较痛苦的一件事情。

当时我们做的就是按这种单元化的模式进行扩容,基本理念就是把一个 SLB 跟十台 ECS 绑定,我们申请的时候,就申请一个 SLB 加十台 ECS,然后组成单元化的扩容,把它组成一个整体,全部初始化好,放到我们的调用方,也就是 endpoint。这样促发调用方,告诉它我这部分已经初始化好了。调用方来把这一组 SLB 加 ECS 扩容上去,采用这种单元化的扩容方式,来解决 SLB 挂长连,如果想规模比较大的扩容,可以采用的一种方式。

公有云实践

接下来讲一下我们的公有云。因为我们跟阿里云也算是深度的合作,我们在基本的网络设置上也是做过很多沟通的。因为春节扩容的话上千台服务器,带宽能达到几十真是上百 G,当用普通的网络肯定是扛不住了,我们在底层基础设施,包括两大核心机房,和阿里的 IDC,也专门拉了两条专线,现在这两条专线应该各是 150G 的专线做互备。

这个当时也是踩过不同的雷,不同的扩容才导致目前这个情况。通过路由器的配置来调配流量,因为我们和阿里云之间的专线,断专线的情况也是非常的频繁,大概一个月就得有个一两次,我们基本一半的服务现在都在阿里云上做长备,这个专线一断就完了,我们在基础网络的保障也是下了不少的工夫。

私有云实践

私有云实践就是我们除了在和阿里云合作之外,我们也和公司内部的一些离线计算,尤其大数据的一些部门做合作。

我们现在采用两种方式,一种就是采用 Docker 加实体机的方式,利用离算计算集群,在他们不用的时候我们去用,或者临时我们扛不住了,我们去征调他们的服务器,可以快速地部署我们的服务,通过 Docker 这种调度来实现的。

还有一种方式就是最传统的,用 OpenStack 加 KVM 再加 Docker 的方式,做虚拟化的平台,就是我们微博平台内部也有核心业跟非核心业务,当这个心业务受到影响的时候,我们会通过这种方式快速地把非核心业务下掉,上核心业务,组建两种模式的私有云服务。

弹性扩容

我们弹性扩缩目前也获得了一些成果,目前我们的容器数大概是 5000+,晚高峰自动扩容就是五百左右,春晚的话十分钟可以扩容一千个节点。这个也是经过不停地磨炼。最早的阿里云,我们在 14 年、15 年使用的时候,可能 10 分钟就只能扩 50 台,当时也造成了很大的问题,我们要提前大概半天或者一天就开始扩过年的服务器了。然后我们 17 年春晚也创了新高,完成了 4700 台的阿里云 ECS 扩容,整个过程是比较平滑的。

未来展望

技术方面,我们第一个想继续深化自动化程度。在很多方向上,自动化还是不够优秀,我们还有很多东西是人在做。我们目前自动化程度还是不够,现在还在进一步地加深自动化的程度,以及优化我们已有的自动化流程,有些自动化流程不太合理。

第二个,就是增加弹性调度的自由度。容器技术虽然是新提出来的,但是底层依赖并不是新的东西。现在我们对容器的调度还没有达到随心所欲的境界,当然现在 K8S 做得已经非常好了,但是还有很多细节上的问题,包括网络上的,系统上的,以及具体实践上的,都需要进一步提升。

第三个就是人工智能,微博在这方面也是做了一定的尝试,我们通过普通机器学习或者深度机器学习做了一些异常检测的预测,但是目前最好的样子也就是百分之七八十的准确率,这个我们还是不太敢应用到线上的使用。现在报警大概已经从每天两三千条,削减到 150 条左右,我们还在致力于再往下削减。

团队方向,我们在引入和培养方面会更侧重成员的开发能力。我们的运维体系都是老员工了,都是从写 Shell,去机房搬机器开始的。我们对系统和硬件理解程度都比较深,但是自动化起来之后,需要我们进机房登服务器的需求越来越少,而需要我们通过开发来提升自动化程度的需求越来越多。

在引入成员的时候,会更侧重开发能力,因为我们现在开发的工作量,已经超过了传统运维的工作量。

其次就是进一步提升服务意识。传统运维是在稳定性方面要求比较高,宁可不变更,也不要破坏稳定性。所以我们在招运维的时候,尤其是社招,老运维他会把这种理念带过来,就是要稳。但是我们现在这个产品运维团队,不仅要稳还要快,要支持 7×24 的迭代的变更,通过各种手段,我们不希望把这种变更速度放下来,尤其现在微服务盛行,变更的次数会非常多。

最后,我们会注重运维平台的持续扩展能力。我们做过一段时间自动化运维开发,几年后,当技术体系已经不太适用了,如何追上时代的潮流,或者如何把系统变成可扩展的,是我们要考虑的。因为需求变化会越来越快,体系淘汰也会变快,所以对于运维平台持续扩展能力的要求会越来越高,我们并不是要做一个完美的运维平台,而是要做一个能够持续支持业务发展的业务平台。


作者简介

刘然,新浪微博产品运维工程师,目前负责偏产品运维的业务。

文章评论