因为工作安排,一些原APP后端的前辈们转移到了其他业务部门,2015年底开始接手客户端后端工作,初入圣地,可谓如进炼狱。
当时因手里还有很多业务开发工作需要小伙伴们继续支持,只能自己先单枪匹马闯入了APP后端开发。
从原来得心应手的内容业务开发,转变到APP后端接口开发,有很多APP方面的专业领域知识还不了解,只能一点点和端上的同学进行请教学习,同时也感谢端上的同学进行的帮助。虽然面临各种困难,但是业务还要继续前进,版本迭代还在紧张进行中。
就这样一天天一边Coding 一边修BUG 一边 和十几位漂亮的产品妹子的各种需求进行周旋。
老API为12年初开发,至15年底,将近4年时间共经手了4拨人马,里面有多少坑可想而知,半夜爬起修复线上BUG已为常事。
同时老API性能问题也不容乐观,接口响应时间以秒计算,当时业务规模还小,原开发前辈们对服务架构及优化也没有进行特别的重视。随着用户规模快速增长,PUSH一发,服务必挂,无奈只能肉扛。就这样一面支持紧张版本迭代,一面踩坑,一面填坑,当然也默默的挖坑,持续了一月有余。
后对整个旧API代码完全摸清后,发现4年时间内,APP发型了版本几十个,原本老大神前辈们写的优秀代码,经过四年时间内,被几波人改的已经面目全非,严重违背了设计初衷,API代码中全是版本代码兼容,各版本之间完全没有分离,单个文件 IF ELSE就十余个,已无法进行扩展,可谓牵一发而动全身,随便调整几行代码就可能导致所有版本整体服务不可用,如果继续维持,也只能将就个一年半载甚至更短,但是时间越长业务代码越乱,到时候会面临更加被动的状态。
如不改变,必不可长久!只能痛下决心,完全重构!
但是业务发展和版本迭代不能停滞,只能从原有内容业务开发调来两位同学一起继续支持老API开发,同时我开始对新接口架构设计进行调研。
因对APP开发经验不足、水平有限,接口重构开始发现无从下手一片空白,连续两周反反复复熬夜写了几套框架,白天和同学们讨论,发现各种问题,一一推翻。
无奈只能查询各种资料,借鉴各大互联网应用经验,同时遍访名师 【感谢:@青哥,@徐大夫,@晶晶,@强哥 @涛哥 及APP端和WAP端小伙伴们的指导】,通过大量学习,慢慢对整个新接口架构搭建思路有了整体的规划,感觉见到曙光。
通过一周的日夜赶工,我把整体框架结构初步搭建完毕,马不停蹄,不敢停歇,那就开始带领小伙伴们开干吧!
虽然对整体设计有了大概思路,但是接口重构也面临着很大的问题,需要APP端及产品、统计同学的鼎力支持才能进行下去。
新接口与老接口无论是从调用方式还是数据输出结构完全不同,导致APP端代码需要大量修改【感谢 @辉辉 @明明 支持配合】
当然统计也面临同样的问题,所有的接口都变了,也就是 原来所有的统计规则都需要修改,同时也感谢【@嵘姑娘 @统计部门 @产品 同学】的大力配合。没有两端及产品,统计的支持,接口重构工作进展就无从谈起,同时也感谢各位领导的大力支持,保障重构工作如期进行。
新接口主要从下面几个方面进行了着重设计:
1,安全性,
1>, 接口请求增加签名验证,建立接口加密请求机制,每个请求地址生成唯一ID,服务端客户端 双向加密,有效避免恶意刷接口。
2>,所有业务参数注册制,统一安全管理
2,可扩展性
高内聚低耦合,强制版本分离,APP版本扁平化发展,同时提高代码复用性,小版本走继承制。
3,资源管理
服务注册制,统一入口出口,所有接口需向系统注册,保障可持续发展。为后续监控调度降级提 供保障。
4,统一缓存调度分配系统
新接口随着5.0发版如期上线了,以为万事大吉,可谁知,大坑在前面一直在默默的等着我。
APP有一个PUSH特性,每次发PUSH会瞬间召回大量用户访问APP。
新接口每次发完PUSH,服务器必挂,悲剧了。
故障表现:
1,php-fpm 堵死,服务器整体状况无异常,
2,nginx 倒是没有挂,服务正常。
3,重启 php-fpm 短暂服务正常,几秒钟后又会死掉。
4,接口响应慢,或超时,app刷新无内容
故障排查猜测
一开始怀疑下面几个问题,
1,MC有问题
2,MYSQL慢
3,请求量大
4,部分请求是代理的老接口,会导致请求翻倍
5,网络问题
6,一些依赖接口慢,把服务拖死
但是因为缺少日志记录,上面都没有追查到任何依据。
问题追查:
发push时服务器压力瞬间上升,短时间内PHP-FPM会阻塞挂掉
PHP是顺序执行,只要有一个后端接口慢,就会造成排队等待,高并发情况下,吞吐量直线下降,直到PHP 完全被拖死。
1,push时会大量召回APP用户,同时打开客户端 是平时的 3-5 倍如图(早晚高峰会叠加)
2,客户端 打开PUSH时会,是冷启动拉起用户,会调用很多接口资源,并且新API上线之初没有与 APP端同学进行充分沟通,导致瞬间请求巨量接口,其中包含很多实时兴趣、广告 等不能缓存 的后端接口大量裸奔,及MYSQL 等资源,导致大量等待。
3,接口请求后端资源超时时间设置过长,未及时释放慢接口请求,造成大量接口请求排队等待
4,用户规模增长,APP用户规模已经和年初相比翻了一倍,工作重心一直放到了代码重构,但是服 务器方面的资源一直被忽视,一直没有任何新增机器,也是本次故障的一个原因。【注:硬件投 入其实是成本最低的投入】
然后,然后 就挂了。。。
问题解决:
1,优化NGINX层缓存,可以缓存的内容【如正文】,在NGINX层做CACHE,减少后端压力
2,停用不必要的接口处理【如统计】,NGINX直接返回,不走PHP,减少PHP-FPM压力
3,重新梳理请求的后端接口资源,根据业务重要性排优先级, 严格控制超时时间。
4,新增设备,重新根据用户规模计算及配置服务器资源
5,记录资源调用日志,监控依赖资源,一旦资源出现问题,及时找提供方解决
6,调整MC缓存结构,提升缓存利用率
7,与端充分沟通仔细梳理APP对接口请求的次序及频次,提升有效接口利用率。
通过这一系列改进措施,效果还是比较明显,新API的性能优势与老API相比如下:
旧:小于100ms的请求占比55%
旧 API 响应时间
新:93%以上响应时间小于100ms
新 API 响应时间
问题总结:
究其根本原因主要有以下几点,1,应对不足,2,缺少重复沟通,3,健壮性不足,4,PUSH特性
1>,应对不足
用户规模从年初至当时增加了一倍有余,未能引起足够注意,接口重构进度还是慢了一拍,没有留下充分的优化、思考时间,直接上场征战,且没有及时新增服务器设备资源,导致踩大坑。
2>,缺少沟通
没有与APP端同学及运维部门保持充分沟通,只关心了自己脚下一摊。一定要和端上,及运维 同学保持足够充分的沟通,融为一体。根据现有资源条件【硬件,软件,依赖资源等】,详细约定各种资源请求时机、频次等,适当延迟非主应用接口请求,保障主业务可用,充分利用服务资源。
注:特别是要和端上同学保持好沟通,端上同学开发是根据APP端的业务逻辑需要来请求接口,如果请求接口过量,就相当与自己的APP对自己的服务器发起了大量 Ddos攻击,非常可怕。。
3>,健壮性不足
过度依赖信任第三方接口,对依赖接口超时设置不合理,缓存利用不充分,无灾难备份,依赖资源出问题,只能眼睁睁的等死。
注:不信任原则,对任何依赖资源都不要信任,做好依赖接口随时挂掉的准备,一定要有容灾措施,严格设置超时时间,该放弃的就放弃。做好服务降级策略。【参考:1,业务降级,加缓存降低更新频次,2,保障主业务,干掉非必要业务,3,用户降级,舍弃部分用户,保障优质用户】。记录日志,日志是系统的眼睛,即使记录日志会消耗部分系统性能,也要记录日志,一旦系统出现问题,可以通过日志迅速定位解决问题。
4>,突发大流量
PUSH和第三方拉起瞬间带来巨额流量,系统无法承受,缺少有效的熔断限流及降级自我保护措施。
小结:通过此次问题我也学到了很多,对整体系统架构有了更深入的了解。同时也领悟了一些道理,有些事情并不是那么想当然、水到渠成的,凡事做之前要做好充分的细致的准备。重构不是单纯对代码进行重写,需要对整个上下游系统资源有充分的了解和认知,及做好万全的准备,如否踩坑将成必然。
盼望着,盼望着,流量来了,奥运临近!
BOSS 涛哥放话:如果奥运不出故障,请同学们吃大餐!如果奥运出故障,请涛哥吃大餐!所以为了大餐坚决不能出任何问题!
奥运前我们一直处于备战状态,进行了大量优化工作,确保完美度过奥运流量高峰。
1,对所有依赖的资源进行了仔细梳理,重点业务接口进行细致监控
2,在APP端部署日志上报模块,实时上报异常日志,进行监控
3,对MC集群进行升级扩容及对系统缓存统一优化管理
4,上线多级业务熔断降级策略
但奥运真的来了,系统还是遭受了很大考验,奥运开始,为确保系统各项指标正常运行不出任何问题,我们安排工程师轮班 24小时在公司值班,奥运首金PUSH不负众望,瞬间带来平时5倍以上的流量,各项资源吃紧,服务器开始满负荷运行。我们之前的准备工作在此刻发挥了作用,值班工程师时刻关注监控大屏,随时根据监控数据及服务器负载状态调整系统参数,同时对各项数据进行提前预热,平稳度过了奥运首金!首金过后,根据观察奥运期间发现其他各项夺金事件带来的流量和首金相比不算太大,我天真的以为整个奥运会流量高峰已经安然度过。【首金异常监控图如下】
可,【天公作美。。】宝宝事件突然来袭,和奥运叠加!宝宝事件首日PUSH带来的流量远远超出了首金流量高峰,在众多八卦用户的大力支持下,我们的系统终于遭受了有生以来最大考验,服务器满负荷运行,PUSH瞬间APP端访问开始出现响应慢的情况,实时监控时间显示错误率也开始上升。
宝宝事件PUSH与奥运叠加流量
我们马上启用应急方案,对系统进行过载保护,业务根据重要性依次进行降级【一般包含:降低更新频率,延长缓存时间,停用】,保护系统整体可用性不受影响,确保系统平稳度过流量高峰。手动开启降级后,系统开始迅速释放大量资源,系统负载开始平稳下降,用户端响应时间恢复到正常水平。等PUSH过后【一般高峰持续3分钟左右】,人工取消降级。
虽然奥运期间突然闯入宝宝事件,我们还算是平稳度过,整体服务没有出现问题,APP整体业务数据随着这两个事件也有了极大提升。
BOSS也请同学们一起吃大餐HAPPY了一把!
小结:1,监控系统还需更细致,需要加入资源监控,因为通过事后分析发现,看到的有些问题并不流量导致,可能会是因为依赖资源问题,导致系统拥堵,放大影响。2,完善报警系统,因突发事件的发生不可预知,不可能有人一直24小时值班。3,自动降级机制服务治理系统嗑待建立,遇到突发流量,或依赖资源突发异常,无人值守自动降级。
飞速发展的业务对我们的系统各项指标也有了更高的要求,首先是服务器端响应时间。
APP两大核心功能模块,Feed流及正文的响应速度对整体的用户体验是有很大影响的,根据领导的要求,首先我们有了前期目标,Feed流平均响应时长 100ms,当时Feed整体响应时间大约为 500-700ms左右,可谓任重而道远 !
Feed流业务复杂,依赖很多数据资源,如 实时广告,个性化,评论,图床转图,焦点图,固定位置投放等,有一些资源不能进行缓存,对于实时计算数据,不能依赖于缓存,我们只能另辟蹊径,通过其他途径解决。
首先我们和运维一起对服务器软件系统环境进行了整体升级,把Nginx升级到了Tengine,然后把PHP进行了版本升级,升级玩效果还算比较明显,整体响应时间减少了 20%左右,到了300-400ms,虽然性能有了提升但是离目标还有很远。优化继续,我们对Feed整个业务环节进行打点记录日志分析,找出最消耗性能的地方,各个击破。
原有服务器结构如下:
分为:负载均衡层,代理层,web层 ,用户端访问首先经过 Nginx代理层代理转发至 Nginx+PHP-FPM web机,甚至存在跨机房代理,代理层与 Web机不在同一台设备、甚至不在同一个机房,可能存在严重的性能损耗,我通过大量的日志分析发现,果不其然,代理层Nginx日志记录的响应时间比web层日志记录响应时间多几十甚至上百毫秒,并且原Cache层存在单点瓶颈风险,问题找到了,我们就对服务器结构进行了调整如下:下线原有Cache层,下沉至web前端机,减少单点瓶颈,同时断绝单点故障对整体服务可用性受到影响的风险。
服务器结构调整完毕,Feed响应时间也有了很大下降,性能提升明显,到了200-350ms左右。离设定目标接近,但仍没有达成设定目标。
一天我们的工程师在调试代码时偶然发现一个问题,PHP-CURL设置的毫秒级超时时间无效,我们通过大量测试验证PHP默认自带的CURL库果然不支持毫秒,通过查询PHP官方文档发现旧版本的PHP libcurl库存在这个问题 【后来发现公司内绝大部分业务的PHP版本环境都存在这个问题】这就意味着我们在系统中做的大量依赖接口超时时间精确控制都没有生效,也是造成系统性能迟迟上不去的一个重要原因,把这个问题解决,对整体性能提升势必会带来很大提升,马上我们和运维同学一起开始进行线上灰度验证测试,通过几天的线上测试,没有发现其他问题,并且性能果真有很大提升,我们就逐步扩大范围,直至上线到所有服务器,通过数据表明 libcurl 版本库升级后,没有做其他任何优化的情况下服务器Feed响应时间直接到了 100-150ms左右,非常明显。
服务器结构层,软件系统环境层能做的都做了,但是还没有达成设定的Feed平均响应时间100ms的要求,只能从业务代码入手了,当时线上Feed流请求依赖资源是顺序执行,一个资源发生拥堵,会导致后面请求排队,造成整体响应时间增加。我们就开始尝试把PHP CURL 改成多线程并发请求,把串行改为并行,同时请求多个依赖的资源接口,无需等待,通过小伙伴的技术攻关,把CURL类库进行了重写,为避免发生问题,我们有进行了长时间大量灰度测试验证,测试通过,发布到线上生产环境,同时小伙伴们的努力也得到了回报,服务器Feed流响应时间直接下降到了 100ms以下,同时正文接口的平均响应时间控制到了 15ms以内。
正文平均响应时间
后续我们又对服务器进行了各机房分布式部署,重新分配VIP网络访问节点,优化网络调用资源,避免用户跨运营商、跨南北访问可能对用户体验造成的不良影响。
通过上面的大量优化调整,我们的整个系统承载能力也得到了很大提升。
目前峰值QPS达13.4万,日最高请求HIT数达8亿左右,量级别已非常可观。
单机的QPS承载量也有了很大提升,原来单机 500-800QPS 系统就已满载,到现在单机 2.5K系统依旧坚如磐石、微丝不动。
感谢团队内小伙伴持续不懈的努力,同时也感谢运维同学对我们的大力协助,让新闻APP接口系统的性能及抗负载能力得到了很大提升。
运筹帷幄方能决胜千里。
新闻APP接口目前依赖第三方接口及资源上百个,一旦某个或多个接口及资源发生问题,容易对系统可用性造成影响。
基于这种情况我们设计开发了本系统,主要系统模块如下:
服务自我保护,服务降级,错误分析及调用链监控,监控与报警。自建离线数据中心,依赖资源生命探测系统,接口访问调度开关,离线数据中心实时收集关键业务数据,生命探测系统实时检测资源健康度及可用性,接口访问调度开关控制对接口的请求,一旦生命探测系统检测到某个资源有问题,就会自动通过接口访问控制开关进行降级降频次访问,同时自动延长数据缓存时间,生命探测系统持续检测资源健康度,一旦资源完全不可用,控制开关就会完全关闭接口请求访问进行自动服务降级,同时启用本地数据中心,把数据提供给用户。等生命探针检测到资源可用后,恢复调用。本系统多次成功避免了重度依赖资源 【如CMS,评论系统,广告等】故障 对新闻客户端服务可用性的影响,依赖资源发生故障,业务反应到用户端基本无感知。同时我们建立了完善的异常监控 错误分析及调用链监控 体系,保障在第一时间预知、发现、并解决问题 【在第7服务端高可用有详述】。
同时客户端业务在持续飞速发展,各功能模块更新迭代也很快,为了满足快速迭代同时又不能出现任何严重代码问题,我们也增加了代码灰度与发布流程。新功能上线首先进行灰度验证,验证通过之后上线至全量,同时预留新旧切换模块,新功能一旦出现问题,随时切换到旧版,保障服务正常。
服务治理平台技术实现
服务治理平台搭建完毕之后,我们的系统服务架构大概如下:
高可用性,目前高并发大流量WEB服务系统中最受关注的问题之一。高可用性设计是个系统工程,其内容涉及(网络、服务器硬件、Web服务、缓存、数据库、依赖上游资源,日志,监控,报警 ,自我保护,容灾,快速处理恢复)等多方面问题。
高可用性的定义:
系统可用性(Availability)的定义公式为:Availability = MTBF / ( MTBF + MTTR ) × 100%
MTBF(Mean Time Between Failure),即平均无故障时间,是描述整个系统可靠性(reliability)的指标。对于一个大型Web系统来说,MTBF是指整个系统的各业务不间断无故障连续运行的平均时间。
MTTR(Mean Time to Repair),即系统平均恢复时间,是描述整个系统容错能力(fault-tolerant capability)的指标。
对于一个大型Web系统来说,MTTR是指当系统中的组件出现故障时,系统从故障状态恢复到正常状态所需的平均时间。
从公式可看出,提高MTBF或降低MTTR都能提高系统可用性。
那么问题就来了,怎么通过这两个指标来提升系统可用性呢?
通过上面的定义我们可以看到,高可用的一个重要因素: MTBF 是系统可靠性【平均无故障时间】。
那我们就列一下都哪些问题会影响MTBF,可能的因素有:1,服务器硬件,2,网络,3,数据库,4、缓存,5,依赖资源,6,代码错误,7,突发大流量高并发 只要解决好这些问题,就可以避免发生故障从而提升 MTBF。
根据这几个问题,那新闻客户端目前是怎么做的呢?
第一个服务器硬件故障:如果一台服务器硬件故障会造成这台服务器上服务不可用,如下图结构,目前系统是LVS+HA上挂多台MEM服务器,LVS+HA上有生命探测系统,如果检测到异常,会从负载均衡及时摘除,避免用户访问到问题服务器造成故障。
第二个内部网络问题:如果发生大规模内部网络故障,一系列的问题,如会造成读取依赖资源失败,访问数据库失败,读写Cache集群失败等,影响范围比较大,后果比较严重。那我们就在此次多做一些文章,一般网络问题,主要发生在跨机房访问拥堵,或者不通。同机房网络不通的情况极其少见。因为有些依赖接口分布在不同的机房,跨机房网络问题主要会影响依赖接口响应慢或超时,这种问题我们采取多级缓存策略,一旦依赖的跨机房接口异常,优先取实时本地化缓存,如果本地化缓存穿透,立刻去拿本机房Cache集群实时缓存,如果集群实时缓存穿透,就取本机房持久化防御缓存,极端恶劣条件下,持久缓存无命中,那备用数据源返回给用户,同时预热备用数据源只持久缓存,让用户无感知,避免大范围故障发生。针对数据库因网络问题导致延迟的问题,我们主要采取异步队列写入,增加蓄水池,防止数据库写入发生拥堵,影响系统稳定性。
第六条代码错误:以前也发生过因代码错误造成线上故障血淋淋的案例,而且很多问题都是低级错误导致,所以我们也重点在这方面做了大量工作。
首先要规范化代码开发、发布流程,随着业务增长,系统稳定性可靠性要求也日益增高,开发团队人员也在增加,已经不能像那种刀耕火种、单打独斗的原始社会状态,所有操作都需做到标准化、流程化。
我们完善了:开发环境,测试环境,仿真环境 , 线上环境 及上线流程。工程师在开发环境自测完毕,提到测试环境,测试部门来进行测试,测试通过之后,提至仿真环境,进行仿真测试,测试通过提至上线系统,上线系统需经过管理员审批通过之后方可以上线,上线完毕进行线上回归验证,验证通过,代码上线流程关闭,如验证失败,通过上线系统一键回滚至上线前环境。
代码开发及发布流程
那针对第七条:突发大流量高并发我们是怎么处理的呢?
突发大流量一般我们的定义为,短时间内 热点及突发事件瞬间带来大量访问请求,远超出系统软硬件预期负荷范围,如果不做处理可能会对整体服务造成影响。这种情况持续时间比较短,如果临时新增上线机器已经来不及,等机器上线完毕,流量高峰已过,就变的毫无意义了。如果随时在线上准备大量备机,那么平时 99%的时间这些机器都会处于空闲状态,会浪费大量财力物力资源。
遇到这么情况我们就需要一个完善的流量调度系统及服务熔断限流措施。如果突发大流量来自于某些特定区域,或都集中在某个或多个IDC机房,可以把负载较高的机房流量切分一部分至流量空闲机房,一起来分担压力。但是如果切分流量不足以解决问题,或所有机房流量负载都比较高,那我们只能通过熔断限流来保护整体系统服务,首先按照业务模块优先级进行排序,按照低优先级的业务进行依次降级,如果业务降级仍不能解决问题,那就开始依次停用低优先级业务,保住重要功能模块继续对外服务,极端情况下业务降级不能挺过流量高峰,那我们就采取限流保护措施,暂时舍弃少部分用户,来保住大部分高价值用户的可用性。
高可用还有一个重要指标,MTTR 系统平均恢复时间,就是服务出了故障之后多久能够恢复。
解决这个问题主要有以下几点:1,发现故障,2,定位故障原因,3,解决故障
这个三点同等重要,首先要及时发现故障,其实出现问题了并不可怕,可怕的是我们很久都没有发现问题,造成大量用户流失这才是最严重的。那么怎么来及时发现故障呢?
监控系统是整个系统环节,乃至整个产品生命周期中最重要的一环,事前及时预警发现故障,事后提供详细的数据用于追查定位问题。
首先要有完善的监控机制,监控是我们的眼睛,但是有监控还不够,还需要及时发出报警,出了问随时通知相关人员及时处理。在这方面,我们在运维部门的支持下建立了配套监控报警体系。
一般而言一个完善的监控系统主要有这五个方面:1.系统资源,2.服务器, 3.服务状态,4.应用异常,5.应用性能,6,异常追踪系统
1,系统资源监控
监控各种网络参数和各服务器相关资源(cpu,内存,磁盘,网络,访问请求等),保证服务器系统的安全运营;并提供异常通知机制以让系统管理员快速定位/解决存在的各种问题。
2,服务器监控
服务器的监控,主要是监控各个服务器,网络节点,网关,等网络设备,的请求响应是否正常。通过定时服务,定时去ping各个网络节点设备,以确认各网络设备是否正常,,如果哪个网络设备出现异常,则发出消息提醒。
3,服务监控
服务监控,指的是各个web服务等平台系统的各项服务是否正常运行,可以通过定时服务,每隔一段时间,就去请求相关的服务,确保平台的各项服务正常运行。
4,应用异常监控
主要有异常超时日志,数据格式错误,等
5,应用性能监控
监控主要业务的响应时间指标是否正常,展示主要业务性能曲线走势,及时发现及预测可能出现的问题。
6,异常追踪系统
异常追踪系统主要来监控整个系统上下游依赖的资源,通过监控依赖资源的健康状况如:响应时间变化,超时率变化等,来对整个系统可能出现的风险做出提前评判及提前处理。还可以对已经发生的故障做到快速定位,是否为某个依赖资源问题导致,来迅速解决故障。
我们目前线上使用的主要监控系统如下:
dashbord
依赖资源超时监控
依赖资源平均响应时间监控
API错误监控
注:【引用、学习】评判一个监控系统的好坏主要有以下两点:1,细致入微,2,一目了然 。这两个看似互相冲突,既然细致入微肯定会有很多很多的监控项目,肯定做不到一目了然,其实不然。一目了然主要是能及时发现是否有问题,因为不可能有那么多时间和精力一直盯着几百个监控图表来看。那么就需要一个完善的 dashbord 汇总各项指标是否正常,列出异常指标一目了然发现问题。而细致入微主要是出现问题后为排除问题点做准备,可以检查各项监控数据点是否正常,来快速定位问题。
【2017年重要目标,用户端高可用】
最近互联网媒体谈论 HTTPS 的文章很多,其原因之一是运营商作恶底线越来越低,动不动就插播广告, 前些天几家互联网公司联合发文 关于抵制流量劫持等违法行为的联合声明 痛斥某些运营商。 另一方面也是苹果 ATS 政策的大力推动,逼迫大家在 APP 中全部使用 HTTPS 通信。 上 HTTPS 的好处很多:保护用户的数据不外泄,避免中间人篡改数据, 对企业信息进行鉴权。
尽管使用了 HTTPS 技术,部分邪恶的运营商,会在HTTPS之前拦一刀,使用 DNS 污染技术,让域名指向的他们自己服务器 ,进行DNS劫持。
这个问题不解决,即使HTTPS 的话也不能从根本上解决问题,仍然会有很多用户的访问出现问题。轻则对产品不信任,重则直接导致用户无法使用产品,导致用户流失。
那么根据第三方数据,对于鹅厂这样的互联网公司来讲,域名解析异常的情况到底有多严重呢?每天鹅厂的分布式域名解析监测系统在不停地对全国所有的重点LocalDNS进行探测,鹅厂域名在全国各地的日解析异常量是已经超过了80万条。这给业务带来了巨大的损失。
运营商为了赚广告钱、省网间结算是不择手段的。 他们普遍使用劫持手段是通过 ISP提供 DNS 伪造域名。
『其实我们也面临同样严峻的问题』
通过新闻APP端的日志监控分析发现:有 1%-2%的用户存在DNS解析异常及接口访问不通的情况。
DNS异常,及无法访问接口
无形中造成大量用户流失,特别是在业务飞速发展的时期对业务的体验造成了非常大的损害。
那么有没有一种技术上的方案,能从根源上解决域名解析异常及用户访问跨网的问题和 DNS 劫持呢?
业界有套解决这类场景的方案,即HTTP DNS。
HttpDNS基于Http协议向DNS服务器发送域名解析请求,替代了基于DNS协议向运营商LocalDNS发起解析请求的传统方式,可以避免LocalDNS造成的域名劫持和跨网访问问题,解决移动互联网服务中域名解析异常带来的困扰。
HttpDNS主要解决三类问题:解决移动互联网中DNS解析异常、LocalDNS域名劫持,平均响应 时间升高,用户连接失败率居高不下
1、DNS解析异常及LocalDNS劫持:
移动DNS的现状:运营商LocalDNS出口根据权威DNS目标IP地址进行NAT,或将解析请求转发到其他DNS服务器,导致权威DNS无法正确识别运营商的LocalDNS IP,引发域名解析错误、流量跨网。
域名被劫持的后果:网站无法访问(无法连接服务器)、弹出广告、访问到钓鱼网站等。
解析结果跨域、跨省、跨运营商、国家的后果:网站访问缓慢甚至无法访问。
由于HttpDNS是通过ip直接请求http获取服务器A记录地址,不存在向本地运营商询问domain解析过程,所以从根本避免了劫持问题。
2、平均访问响应时间升高: 由于是ip直接访问省掉了一次domain解析过程,通过智能算法排序后找到最快节点进行访问。
3、用户连接失败率下降: 通过算法降低以往失败率过高的服务器排序,通过时间近期访问过的数据提高服务器排序,通过历史访问成功记录提高服务器排序。如果ip(a)访问错误,在下一次返回ip(b)或者ip(c) 排序后的记录。(LocalDNS很可能在一个ttl时间内(或多个ttl)都是返回记录
HTTPS能最大限度的防止运营商对流量劫持,包含内容安全不被篡改。
HTTP-DNS能解决用户端DNS的问题,保证用户请求直达,且自动直达响应最快的服务器直达。
HTTP DNS 的原理很简单,将 DNS 这种容易被劫持的协议,转为使用 HTTP 协议请求
DomainIP 映射。 获得正确 IP 之后,Client 自己组装 HTTP 协议,从而避免 ISP 篡改数据。
客户端直接访问HTTPDNS接口,获取域名的最优IP。(基于容灾考虑,保留使用运营商LocalDNS解析域名的方式作为备选。)
客户端获取到业务IP后,就向直接往此IP发送业务协议请求。以Http请求为例,通过在header中指定host字段,向HTTPDNS返回的IP发送标准的Http请求即可。
要想做到用户端高可用,首先要解决这个问题。我们已经开始与APP端开发同学及运维同学一起开始准备,争取以最快的速度上线HTTPDNS,实现APP用户端高可用,为业务飞速发展提供可靠保障!
通过一年的努力,整个APP后端系统基本从蛮荒时代走到了目前的趋于完善,自己也从一点点摸索中学到了很多知识,自认为也获得了很大成长,但是同时我们面临着很多很多问题,随着业务飞速发展,对后端服务的要求也越来越高,后续还有很多问题需要我们解决,我们也将会以更高标准来要求自己,为亿级用户规模做好准备。
以上就是新闻APP后端系统架构成长之路 - 高可用架构设计图文详解的内容,更多相关内容请关注PHP中文网(www.php1.cn)!