APMCon 2017|搜狐研发中心架构师陈伟:搜狐服务架构优化实践
中国应用性能管理行业盛宴—2017中国应用性能管理大会(简称APMCon 2017)于8月10日至11日在北京新云南皇冠假日酒店隆重召开。本届APMCon是由听云、极客邦和InfoQ联合主办,作为国内APM领域最具影响力的技术大会,本次大会以“驱动应用架构优化与创新”为主题,致力于推动APM在国内的成长与发展。
搜狐研发中心架构师陈伟于大规模网络架构优化专场发表了题为《搜狐服务架构优化实践》的演讲,现场解读了搜狐过去几年在后台架构优化,微服务体系,用户端连接优化,监控体系建设等方面的经验和教训
以下为演讲实录:
陈伟:大家下午好,非常高兴能在这样一个大会里,在位于中心环节的专场里第一个上台给大家做展示。也希望我今天讲的这些东西能给大家带来收获,所以一会儿有什么问题,欢迎大家随便来提问。
先自我介绍一下,我是2013年毕业,毕业后一直在搜狐工作。做的事情比较多、比较杂,也可以叫做全链工程师,除了这两方面的以外也做过前端、App的开发,比较主要的项目都是集中在分布式后台服务的领域。做过一些分布式存储、分布式数据库相关的工作。最近也还在继续开发分布式对象存储的系统,因为我们做很多开源的工作,未来也有可能有机会跟大家继续介绍。在工作的这几年中间做过比较长时间的图片和多媒体处理的工作,这是我今天后面会讲到的优化里面很重要的一环。因为在图片领域,我们发现很多公司或者说业界的很知名的公司做的也都并没有那么深入。我们在这上面做了很多的工作,发现可以取得非常好的效果的。最近工作两年主要集中在Docker相关的领域,我们自己开源了一套Docker的管理系统,后面也会有一些详细的介绍。
一.目标—效率
下面我们进入今天的主要环节。我在搜狐这几年其实也是在慢慢的摸索我们做工作的思路。最终总结下来,除了完成我们的基本工作之外,作为偏基础架构和服务端领域的方向上,比较核心的是四个目标。我们所有优化的工作,或者说我们额外的开发工作,其实都是围绕这四个目标来做的。稳定性、效率、成本、安全。我在后面讲的每个工作也都会围绕这四个方面来说,每个工作都各有侧重点。
首先看一下我们在效率上做的额外的工作。效率主要指的是用户访问的效率,当然这本身也包括开发效率等等。对于用户访问来讲,我们最直观的感受就是快。今天上午所有的议题,老师们讲的都是怎么能够让服务变得更快,或者说怎么发现它变慢了。对于搜狐来讲,是因为搜狐有马上20年了。所以经历了很多代的技术的演化。在早期技术上,是没有各种云的技术情况。所以搜狐自己在全国有20多家的数据中心,自己有全国的光纤网络等等。在接入层这块可能会跟其他很多公司做的不一样,因为当你公司有云技术的时候,可以来解决问题,但量达到一定程度的时候,还是要关心很多这方面的工作。接下来我们会重点介绍一下最近几年如何让用户的访问变得更快。最核心的就是接入层这块的优化。
对接入层这方面来讲没什么太多的秘密,最核心的一点就是离用户越近越好。就像你追女朋友一样,如果说一个单位的,天天见是最容易搞定的。如果是一个城市机会也是蛮大。但假设是异地,难度就要大很多。换做是异国的话很可能就要分手了。所以说我们的服务也是这样的。你如果不能时时刻刻离用户更近,用户就把你抛弃了。这也是我们优化的一个总体思路。
在我们全国有很多的IDC机房的情况下,最重要的一点就是怎么样准确的来发现让哪个用户该访问哪个节点。所以在自有节点的流量调度方面我们做了特别多的工作,里面比较难的是发现用户真实的位置。因为在传统上大家的做法通常就是根据整个DNS的体系来做调度,里面比较麻烦的问题就是用户设置的DNS,或者说运营商的DNS并不一定能真实的反映用户实际所处的网络情况。而且很多运营商的DNS会有各种各样的问题。在最近,DNS的协议会帮我们把流量调度做得更加精准。因此我们做了很多的升级,我们自己的DNS系统,以及第三方的DNS系统会更多的采用这样的方式,准确发现用户的IP,做更准确的调度。包括采用一些更精准的IP库。因为一些开放的IP库可能效果并没有那么好,而这点根据我们的实际检验发现,当你把IP库做得更精准之后,这个效果的提升是非常明显的。除了国内之外我们还有世界范围内调度的方案。
搜狐在过去的十几年里面一直都是采用自己的IDC的方案。但是最近几年大家也能看到公有的CDN发展的非常快,确实这种公有的CDN在某些领域有非常大的优势,尤其是标准化的图片访问,或者流媒体的访问上面有很多的优势。所以我们也是结合了自建的CDN和第三方CDN混合的方式。这里面最主要的核心是调度问题。因为在用多家CDN的时候调度问题更麻烦。比如说你同时有几个女朋友分布在几个城市里,这时候你去哪个城市的时候,就可以和哪个女朋友在一起。如果去了A城市联系B城市的女朋友,可能就会出现一些问题。这就是说当你用多家CDN的时候,可能会导致的不好的情况。在这种架构下我们做的很重要的工作就是跟第三方CDN结合的更紧密。我们能拿到他们原始的节点的位置,以及我们通过自己客户端的方案。包括第三方,像听云这样的方案,来发现每一个位置或者说每一种网络环境下,哪个CDN的效果更好,还是说我们自己的CDN效果更好,来做这样的一种调度。当然这个调度本身是非常复杂的,因为它不光是要根据效果来看,也要根据一些CDN容量规划等等。来做这样的一些策略。总体上我们目前已经形成了一个比较完善的、融合的CDN方案。
这套方案本身还是基于DNS的方案,依然不够精准。那我们接下来需要做得更加精确。在App的应用里面自主性比Web应用强的多。当一个域名可以解析很多不同的CDN厂商的服务器上,你可以自主的探测速度,再结合服务器给的策略,综合的选择一个你认为最优的策略来访问。这是一个非常有意思的一种做法。但是局限性比较大,除了在App里面都不好用,在Web环境下比较难以做到这点。另外这个调度还是比较复杂的,因为多家CDN的情况下,包括你的容量的规划,你的价格因素等等,考虑在内,就会非常麻烦。所以这还是局限在一些量比较大,然后比较核心的App图片或者说视频这种标准的CDN访问的情况下,我们会采用一些这样的策略。
上面所有的策略都离不开一点,就是首先要对整个全网的环境和真实的数据有所了解。我们花了比较大的精力做这样一监控系统,数据源并不源自于我们自己,也包括了第三方的监测机构提供的原始数据。这些数据不只用来做这个,后面的很多工作都是依赖于这些原始数据。我们利用这些原始数据制作出来这样的全网的品质监控图,是我们后面做流量调度最核心的依据。
像这样的一些流量调度之外,还有一些要注意的,我们会做很多服务分层的一些工作。包括你的机房的品质,带宽的质量不同。不可能视频的加载全部都用最贵的方式来解决,这样成本太高。所以我们会针对每个服务不同的特性。比如说你DNS节点,需要访问的足够高效。对于动态请求,通常来说量不大,带宽不大,请求更频繁。大多数公司的方案是经过一些路由的选择,或者说直接就来访问你全国的一个或者两个节点。这种情况是方案来服务的。实际上之前我们也一直是这样做的。但是因为都在请求,本身确实比较麻烦。所以在我们后面使用Docker的方案之后,我们开始逐渐的把一些动态请求尽量的推进用户。这个思路还是刚才说的离用户越近越好。动态请求没有办法完全利用CDN的能力,就只能在自建的核心节点上尽量的把一些用户的动态请求就地解决掉。但这个工作相对来说难度比较大,因为涉及到服务的部署,你的数据库的同步,或者缓存的同步。所以目前的应用时间还不能做到完全把动态请求推到离用户更近的地方。而是采用一些,比如说能在缓存层解决掉的,我们就分布在几个比较主要的机房解决,无法解决掉的还是在核心机房做处理。所以我们做这些工作是完全跟业务部门来探讨这个方案,定制化出来的。
除了前面说的离用户越近越好之外,当然也有别的手段能够去优化。因为不同的人跟女朋友用不同的方式去交流的时候,自然效果也不一样,你们之间是写信还是发微信,这自然也不一样。
所以在协议层可做的优化空间也是比较多的。近几年最核心的优化比较大的就是SPDY协议和HTTP2协议的工作。从我们的监控数据来发现,整个的响应,大概的数据来讲,响应延迟能做到原来普通延迟的几分之一,这是采样的数据。有了这样一个性能的提升之后。当然这个性能提升并不是说我直接用上这个方案就OK,它依赖于很多你的页面里面自主做一些适应协议的工作。之前做Web的很多工作,是把域名打散。因为浏览器有并发的限制这样子,所以会把很多的图片放在很多的域名下,但这样的页面布局方式是在HTTP2的协议里面的,我们非常不推荐。所以我们会改进这个工作,之后会把域名的分布方式改进。效果就会非常明显。HTTPS的兼容性整体上不错,但是在Web端依然有很多老牌的浏览器不能很好的兼容。
接下来其实是一些比较小的工作,像HTTPS证书选择就是隐藏的坑。大部分人不会注意到不同。但我发现不同的HTTPS证书也会有差距,其中有的多一层中间CA的时候,握手时间能差到20毫秒的水平上。所以当你对性能有更高要求的时候要舍得在这些东西上面花钱。
影响再小一点的就是底层的优化工作,像TCP参数的优化,网上已经有大量的推荐的参数配置,目前已经比较成熟了。不过在线上应用里没有办法拿到那么好的数据,但确实是有提升的。我们尝试在跨数据中心的数据同步里面,我们会尝试用UDP的方式做这样的工作。所以大家正常的开发接触的主要都是TCP。另外也应该关注一下更底层的协议优化,可能会带来意想不到的效果。
这块不能叫接入层的优化,但是在我们的架构里面,图片最终对外的访问不是由业务的提供端给出的,而是我们本身的图片平台或者多媒体平台提供服务的,也能看做接入层。这个影响是非常巨大的,而且改起来是非常容易的。很多网站慢的原因就是图片太大了。在格式压缩上,JPG压缩的图能再减少30%、40%,依然对用户的感官上没有任何变化。
这三张图看不出区别来,但是经过我们压缩之后的图片的效果能小到30%左右。还有Webp格式,我觉得目前已经有很多的公司在使用这个方式了。尤其在App端,webp做得比较好的。令我们头疼的是既符合PNG的图,又会加载慢、耗费用户流量的大户。稍微比一下,一个差不多质量的PNG要比JPG大很多,而传统上的这两种压缩,对图片的效果都不明显。我们是自己在很底层的PNG库里做很多的工作,包括GIF的压缩也是因为在多帧的时候没有做相关性的关系。这是相对比较底层的优化。在最早的时候我们GIF做这样的工作,把GIF图转成MP4或者WebM都比GIF要小。但当我们做过这样的工作之后,其实GIF图也可以流畅的在互联网上使用。
视频的压缩指的不是搜狐视频,因为我们跟他们的技术体系相对来说不是完全在一起的。但是大家会发现像新闻客户端,包括各种新闻网站等等,里面的视频已经非常多了。信息流视频通常来说比较短,在业务线不付出额外努力的情况下,我们做很多多码率自动的转化,以及这种选择,帮助业务线使用更少的带宽和更流畅的速度获得这样的效果。
二.目标—稳定
效率这部分讲完了,然后讲一下我们在提升整个的后台服务稳定性上面做的工作。平台化是我们这一段时间来说优化平台服务的一个思路。搜狐跟其他很多公司不一样,很多公司其实是由一个业务起家,所有的工作围绕这样一个业务来展开。比如说摩拜单车,肯定所有的业务都是跟单车业务相关的,慢慢的往外延伸。不管是发红包还是做活动、会员卡,都是这个相关的业务,所以是非常集中式的。而搜狐已经有十几年的历史的情况下,做了大量的,各种各样的工作。可能你见到过的互联网的业务,搜狐都做过。不管是电商、社交、视频、搜索,所有的都做过。而且每一次做都是处于不同的历史时期。技术发展确实比较快,每隔几年可能技术栈就完全过时了。一些工作实际上采用了不同的技术栈开发,导致我们后面很多的优化工作无法展开。同时也是因为这样的一些体系,实际上在内部每一个业务部门都相对比较独立,没有全公司的集中式的应用运维的管理,运维体系更多的是做基础运维。在这样的历史项目的前提下,整个的技术栈或者说我们在优化性能方面要做的工作非常多,而且不容易做好。
平台化就把基础工作抽离开,除了写代码,很多的工作都浪费在持续集成、队列、做分析、日收集、做报表、监控,其实后台服务这些工作基本都要做。确实每个业务会有自己独特的特点,但是大同小异的。所以我们用平台化的方式来尽量降低业务线的负担。之前很多公司也都提过,把中间层的业务做得更厚,业务线可以更轻量级的开发。能几个星期上线一个业务,更多的赶上浪潮。所以这也是我们必然需要做的工作。我们在最近几年里把数据库、redis集群、对象存储、图片处理、视频处理、抓取服务、大数据服务、队列服务、监控报警等等,把这些业务做成云化的方式,在公司内提供的私有云的方式,然后业务线能够比较简单的用起来。
由于跟其他很多公司不一样,很多公司做单一业务是比较容易做到这点的,因为第一个业务来把这个redis,把大数据的组件,或者说把队列都建好了,其他围绕它的业务就一起来用就好了。搜狐的不同点是在于他本身有很多的项目是相互独立开的,我们花了很多的精力让这些组件适应这些语言的开发,各种各样的模式,能够兼容它们,所以会做得更像云一点。
简单讲几点,对象存储实际上是之前比较花大精力的工作,是从我入职开始重点做的工作。我们从底层系统开始是自己搭建的,目前也已经有数百亿的文件级别,能存储在这个平台上来提供访问十几PB的小图片。这和传统的KV不太一样,我们这套系统更多的是能够直接和CDN厂商,包括前面说的多CDN的选择,和图片处理以及视频处理完美的融合在一起。这也是所有的业务线用的最爽的平台,当业务线要做一个社交系统的时候,让用户上传一张照片,然后要分发给各种平台下的用户,涉及到的工作其实用这个平台完全自动都解决了。你上传图片的时候设定一个URL把这张图片传上来,你可以用不同的格式来取,自动的帮你转化好,用户用的是什么网络,用哪家CDN,都由中间的平台层处理掉的。如果用户上传的是个视频,比如说有些iPhone拍的视频在Android上播放会有问题,可以做转码,转成不同的分辨率。甚至原来是一个MOV或者MP4的视频,可以转成HRS的方式,通过流媒体的方式播放出去。所以已经不完全是一个对象存储平台,它实际上是以对象存储为支撑的多媒体加图片,加分发的综合的处理平台。这样的平台对业务线的开发速度帮助是非常大的。其实现在也有很多的公有云提供类似的服务。
像Redis集群,Redis基本上在一半的业务里面都会用到Redis缓存。所以我们在公司内通过Docker资源的分配方式,并且自助化的申请平台,直接在页面上自动申请,自动分配。把这种访问方式包括密钥,包括IP的限制下发给用户,用户就可以使用了。之前我们通常用的方式是工单,并不是云化的平台,用工单会有很多的问题,包括时效性等等。当我们用云平台的时候,我们发现业务现在开发效率提高了很多,整个的稳定性也会好很多。
另外大数据平台服务,我们把很多的数据标准化之后,当业务线需要一些数据的时候,甚至是非技术人员,不知道什么叫表的一些人,也能够顺利的在里面去查数。大数据部门通常干的最多的事情就是查数。这样的话就能够方便大家一起来查数。像监控报警就是刚才说的,我们提供了一套完整的,当业务部署上去能够更容易的进行这种监控报警的准备。
三.目标—成本
后面的一块工作,这就是我们自己研发的DomeOS的系统,欢迎大家提问题。这套系统是基于开源的部署系统。这个平台下面我们能够完整的完成业务的上线,回滚,服务的配置,跨机房的应用,以及持续集成,监控报警,把刚才说的很多的工作在这个平台下都可以自动完成。当代码提交之后,剩下的事情都可以标准化来完成。这项工作的主要作用可能不仅仅体现在对于我们线上环境的变化,很大程度的规范了整个公司开发的行为,以及解决的很多历史遗留问题。在我们使用Docker的部署方式之后所有的应用都是动态部署,资源利用率大大提高。资源利用率的程度非常高,会更容易拓展我们的业务。
我们最近万年不变的搜狐主页已经改版了,包括手机搜狐网的改版,或者说焦点的改版。
这几次改版主要的工作都是依赖于这套系统,所有的应用都已经跑在Docker上面了。这个流程里面业务线要做的只是把开发测试完成好,发布就是在界面上,测试环节正式发布。运维监控我们也做了很多的自动工作,基础的数据收集就不用说了,业务的内存泄露等等不需要用户配置,都可以简单的提醒用户。作为这样的一套系统覆盖了包括集群管理的工作。同时还有日志分析,很多的业务自然都会把一些问题打到日志里面来。我们直接会把所有的业务日志,不管是控台的还是写到文件里,收集到ELK里面去,你要搜索日志都可以。还可以进行关键词匹配报警。这些业务之前都是要单独做的,或者因为没有做这些工作都会导致线上的故障。在DomeOS这个系统里可以轻松的完成,也是延续我们平台的思路,我们把整个公司能通用起来的业务做成智能组件,来避免业务线乱搞,就是这个意思。
大概来说一下几个核心的模块,日志收集加分析的工作实际上大概就是这样的流程。首先App因为运行在Docker里面,它的控制台日志我们非常容易收集,打到文件里的日志会要求它在上线之前做配置,你要写哪个文件,我们会把这个文件放到本地的磁盘里。然后收集走所有对套的路线。Kafka是个万金油插件,所有的处理都没有问题。我们的界限有到这一层,从Kafka出来之后业务线想做更多的工作也有足够的能力。而且刚才也说我们有大数据平台,我们可以很容易的把这些数据自动导到大数据平台。
负载均衡和服务发现,是大家用Docker里面容易遇到的一些问题,因为Docker之所以说没有简单的用起来,很多时候都是因为负载均衡服务发现不是特别好做,我们做了很多的工作。七层的代理我们全部用Nginx来完成,因为动态部署的,所以每个容器所在的位置随时会变,当它变了之后新的IP信息会通过Nginx指导。同时我们在Nginx上可以做很多的服务分析,比如说你的响应时间长,用Nginx做是最合适的。如果是微服务架构的,在容器内要做很多访问交互的时候,我们也可以部署注册中心,可以点对点直接来访问。
监控报警不多说了,主要都是利用外部插件做的组合。我们之前这个方案也变过很多次。(英)这部分工作没有必要完全自己开发,有很多不错的开源项目可供选择,难点是如何和业务结合的更好,以及扩展性和易用性的平衡
这些是我们实际做的工作,用Docker不是说把原来的业务迁移到Docker里面跑起来就行,我们不追求覆盖的速度。我们更希望在这个过程中帮助业务线梳理他们的工作。在未来规范化是我们最关心的,当把整个体系规范化之后,未来的工作会好做很多。同时我们在做一些基于GRPC更好的服务发现体系,如果未来这块有更好的进展可以再跟大家分享。
四·目标--安全
最后简单说一下我们最近面临的一些问题。劫持相关的一些工作,这对我们的困扰是比较大的。原理就不多说了,有DNS劫持,也有小区宽带接入层的劫持,主要影响的就是插广告,插的都是很low的广告,用户会以为是搜狐家的,其实并不是。整个的服务的可控性也不行,比如说我们改版升级等等,因为它的劫持导致我们的改版不能很顺利的确保用户能看到。我们的解决方案就两个,一个是监控,更好更快的利用全国的布点发现监控问题,比如说解析结果不对了,不是我们自己的IP,或者说访问的页面里面内嵌了我们不认识的JS。解决方案就没什么太多的,最有用的还是投诉和协调,去跟运营商扯皮,能解决大部分的问题。
像小区宽带这种插广告的时候是通过HTTPS来解决,不能大规模迁移过来,但也解决的比较好。像HTTPDNS可以很好的解决用户的DNS劫持的问题,当然这也有很大的局限性。我们前面的用户主动选择节点的方案就是使用HTTPDNS为基础来做,比较大的问题就是只能在App里面用。同时也还是有一些对业务开发的侵入性等的工作。反劫持这块不说太多了,HTTPDNS大家有兴趣可以参考业界比较好的框架。
今天讲的主要就是这几个方向,谢谢大家。
Q&A 问答
提问:您刚才说动态的接口是通过在用户就近部署Docker来优化它的网络吧?
陈伟:对,主要是用docker可以比较好的快速部署和升级服务。
提问:有没有考虑过动态这边接口用动态CDN优化呢?用户首先连接到最近的一个CDN节点,然后用CDN每次都回到自己的原栈。
陈伟:我们绝大多数的方式都是这么做的,我刚才说的优化是在这个基础上,如果说这个性能还不能满足需要,并且你的业务能够拆的比较好,能分离出一小部分的,比如虽然是动态请求,但其中有70%到80%能缓存住的,这种接口可以接近的部署到离用户更近的节点上,比动态CDN再更快一点,这只是一个补充。动态CDN是基本的用法。
提问:是比用户的IP连到原栈更快一点吧?
陈伟:对,也是因为中国的网络环境比较恶劣,每天晚上八点到十点跨网访问基本不可用了。所以说是比较需要动态CDN这个东西,但其实在网络不繁忙的时候差别并不是很严重。
提问:怎么定义关键词报警的?
陈伟:业务线自己定义,他觉得哪个关键词出现多少次之后要报警,可以自己配置。因为每个业务打的日志他自己知道,但是不需要自己去开发这个过程,他只需要配置这个关键词是他关心的频率,和报警的人就行了。
提问:在搜狐做跨区域的容灾的情况下DNS解析会有延迟,快点的话是几小时,慢一点的话是24小时,解析时差你怎么控制?
陈伟:这个不太能依赖靠DNS做跨机房的事。容灾时间差,如果说整个机房完全宕掉的情况,这个机房对外的出口跟着一起宕掉,没有太好的方案。我们有动态的CDN,所以实际上用户的访问并不是直接打到源站的。如果说源站的出口挂了,但是有备用的机房做这种处理,我们可以瞬间把回源的地址切换到新的机房。但是因为某些原因访问的用户直接接触到IP的变化了,这只能依赖DNS的选择了,所以我们会尽量避免这个情况。正常的用户所访问的域名一定是解析到动态CDN上的,而不是直接解析到机房的IP。即使某个机房接入点出了问题,也是影响到小部分用户。我们设置的DNS过期时间比较短,运营商不受我们控制。如果不能在很短的时间恢复,我们也会把服务迁走之后,会去跟运营商协调,让他帮我们快速的做切换。这就比较依赖人工了,还是尽量的避免这些情况。