因为工作安排,一些原APP后端的前辈们转移到了其他业务部门,2015年底开始接手客户端后端工作,初入圣地,可谓如进炼狱。
当时因手里还有很多业务开发工作需要小伙伴们继续支持,只能自己先单枪匹马闯入了APP后端开发。
从原来得心应手的内容业务开发,转变到APP后端接口开发,有很多APP方面的专业领域知识还不了解,只能一点点和端上的同学进行请教学习,同时也感谢端上的同学进行的帮助。虽然面临各种困难,但是业务还要继续前进,版本迭代还在紧张进行中。
就这样一天天一边Coding一边修BUG一边和十几位漂亮的产品妹子的各种需求进行周旋。
但是业务发展和版本迭代不能停滞,只能从原有内容业务开发调来两位同学一起继续支持老API开发,同时我开始对新接口架构设计进行调研。
因对APP开发经验不足、水平有限,接口重构开始发现无从下手一片空白,连续两周反反复复熬夜写了几套框架,白天和同学们讨论,发现各种问题,一一推翻。
无奈只能查询各种资料,借鉴各大互联网应用经验,同时遍访名师【感谢:@青哥,@徐大夫,@晶晶,@强哥@涛哥及APP端和WAP端小伙伴们的指导】,通过大量学习,慢慢对整个新接口架构搭建思路有了整体的规划,感觉见到曙光。
通过一周的日夜赶工,我把整体框架结构初步搭建完毕,马不停蹄,不敢停歇,那就开始带领小伙伴们开干吧!
虽然对整体设计有了大概思路,但是接口重构也面临着很大的问题,需要APP端及产品、统计同学的鼎力支持才能进行下去。
新接口与老接口无论是从调用方式还是数据输出结构完全不同,导致APP端代码需要大量修改【感谢@辉辉@明明支持配合】
当然统计也面临同样的问题,所有的接口都变了,也就是原来所有的统计规则都需要修改,同时也感谢【@嵘姑娘@统计部门@产品同学】的大力配合。没有两端及产品,统计的支持,接口重构工作进展就无从谈起,同时也感谢各位领导的大力支持,保障重构工作如期进行。
新接口主要从下面几个方面进行了着重设计:
1,安全性,
1>,接口请求增加签名验证,建立接口加密请求机制,每个请求地址生成唯一ID,服务端客户端双向加密,有效避免恶意刷接口。
2>,所有业务参数注册制,统一安全管理
2,可扩展性
高内聚低耦合,强制版本分离,APP版本扁平化发展,同时提高代码复用性,小版本走继承制。
3,资源管理
服务注册制,统一入口出口,所有接口需向系统注册,保障可持续发展。为后续监控调度降级提供保障。
4,统一缓存调度分配系统
APP有一个PUSH特性,每次发PUSH会瞬间召回大量用户访问APP。
新接口每次发完PUSH,服务器必挂,悲剧了。
故障表现:
1,php-fpm堵死,服务器整体状况无异常,
2,nginx倒是没有挂,服务正常。
3,重启php-fpm短暂服务正常,几秒钟后又会死掉。
4,接口响应慢,或超时,app刷新无内容
故障排查猜测
一开始怀疑下面几个问题,
1,MC有问题
2,MYSQL慢
3,请求量大
4,部分请求是代理的老接口,会导致请求翻倍
5,网络问题
6,一些依赖接口慢,把服务拖死
但是因为缺少日志记录,上面都没有追查到任何依据。
问题追查:
PHP是顺序执行,只要有一个后端接口慢,就会造成排队等待,高并发情况下,吞吐量直线下降,直到PHP完全被拖死。
1,push时会大量召回APP用户,同时打开客户端是平时的3-5倍如图(早晚高峰会叠加)
4,用户规模增长,APP用户规模已经和年初相比翻了一倍,工作重心一直放到了代码重构,但是服务器方面的资源一直被忽视,一直没有任何新增机器,也是本次故障的一个原因。【注:硬件投入其实是成本最低的投入】
然后,然后就挂了。。。
问题解决:
1,优化NGINX层缓存,可以缓存的内容【如正文】,在NGINX层做CACHE,减少后端压力
2,停用不必要的接口处理【如统计】,NGINX直接返回,不走PHP,减少PHP-FPM压力
4,新增设备,重新根据用户规模计算及配置服务器资源
5,记录资源调用日志,监控依赖资源,一旦资源出现问题,及时找提供方解决
6,调整MC缓存结构,提升缓存利用率
7,与端充分沟通仔细梳理APP对接口请求的次序及频次,提升有效接口利用率。
通过这一系列改进措施,效果还是比较明显,新API的性能优势与老API相比如下:
旧:小于100ms的请求占比55%
问题总结:
1>,应对不足
2>,缺少沟通
没有与APP端同学及运维部门保持充分沟通,只关心了自己脚下一摊。一定要和端上,及运维同学保持足够充分的沟通,融为一体。根据现有资源条件【硬件,软件,依赖资源等】,详细约定各种资源请求时机、频次等,适当延迟非主应用接口请求,保障主业务可用,充分利用服务资源。
注:特别是要和端上同学保持好沟通,端上同学开发是根据APP端的业务逻辑需要来请求接口,如果请求接口过量,就相当与自己的APP对自己的服务器发起了大量Ddos攻击,非常可怕。。
3>,健壮性不足
过度依赖信任第三方接口,对依赖接口超时设置不合理,缓存利用不充分,无灾难备份,依赖资源出问题,只能眼睁睁的等死。
4>,突发大流量
PUSH和第三方拉起瞬间带来巨额流量,系统无法承受,缺少有效的熔断限流及降级自我保护措施。
盼望着,盼望着,流量来了,奥运临近!
BOSS涛哥放话:如果奥运不出故障,请同学们吃大餐!如果奥运出故障,请涛哥吃大餐!所以为了大餐坚决不能出任何问题!
奥运前我们一直处于备战状态,进行了大量优化工作,确保完美度过奥运流量高峰。
1,对所有依赖的资源进行了仔细梳理,重点业务接口进行细致监控
2,在APP端部署日志上报模块,实时上报异常日志,进行监控
3,对MC集群进行升级扩容及对系统缓存统一优化管理
4,上线多级业务熔断降级策略
虽然奥运期间突然闯入宝宝事件,我们还算是平稳度过,整体服务没有出现问题,APP整体业务数据随着这两个事件也有了极大提升。
BOSS也请同学们一起吃大餐HAPPY了一把!
原有服务器结构如下:
后续我们又对服务器进行了各机房分布式部署,重新分配VIP网络访问节点,优化网络调用资源,避免用户跨运营商、跨南北访问可能对用户体验造成的不良影响。
通过上面的大量优化调整,我们的整个系统承载能力也得到了很大提升。
目前峰值QPS达13.4万,日最高请求HIT数达8亿左右,量级别已非常可观。
单机的QPS承载量也有了很大提升,原来单机500-800QPS系统就已满载,到现在单机2.5K系统依旧坚如磐石、微丝不动。
新闻APP接口目前依赖第三方接口及资源上百个,一旦某个或多个接口及资源发生问题,容易对系统可用性造成影响。
基于这种情况我们设计开发了本系统,主要系统模块如下:
同时客户端业务在持续飞速发展,各功能模块更新迭代也很快,为了满足快速迭代同时又不能出现任何严重代码问题,我们也增加了代码灰度与发布流程。新功能上线首先进行灰度验证,验证通过之后上线至全量,同时预留新旧切换模块,新功能一旦出现问题,随时切换到旧版,保障服务正常。
服务治理平台搭建完毕之后,我们的系统服务架构大概如下:
高可用性的定义:
系统可用性(Availability)的定义公式为:Availability=MTBF/(MTBF+MTTR)×100%
从公式可看出,提高MTBF或降低MTTR都能提高系统可用性。
那么问题就来了,怎么通过这两个指标来提升系统可用性呢?
那我们就列一下都哪些问题会影响MTBF,可能的因素有:1,服务器硬件,2,网络,3,数据库,4、缓存,5,依赖资源,6,代码错误,7,突发大流量高并发只要解决好这些问题,就可以避免发生故障从而提升MTBF。
根据这几个问题,那新闻客户端目前是怎么做的呢?
第一个服务器硬件故障:如果一台服务器硬件故障会造成这台服务器上服务不可用,如下图结构,目前系统是LVS+HA上挂多台MEM服务器,LVS+HA上有生命探测系统,如果检测到异常,会从负载均衡及时摘除,避免用户访问到问题服务器造成故障。
第六条代码错误:以前也发生过因代码错误造成线上故障血淋淋的案例,而且很多问题都是低级错误导致,所以我们也重点在这方面做了大量工作。
首先要规范化代码开发、发布流程,随着业务增长,系统稳定性可靠性要求也日益增高,开发团队人员也在增加,已经不能像那种刀耕火种、单打独斗的原始社会状态,所有操作都需做到标准化、流程化。
我们完善了:开发环境,测试环境,仿真环境,线上环境及上线流程。工程师在开发环境自测完毕,提到测试环境,测试部门来进行测试,测试通过之后,提至仿真环境,进行仿真测试,测试通过提至上线系统,上线系统需经过管理员审批通过之后方可以上线,上线完毕进行线上回归验证,验证通过,代码上线流程关闭,如验证失败,通过上线系统一键回滚至上线前环境。
那针对第七条:突发大流量高并发我们是怎么处理的呢?
遇到这么情况我们就需要一个完善的流量调度系统及服务熔断限流措施。如果突发大流量来自于某些特定区域,或都集中在某个或多个IDC机房,可以把负载较高的机房流量切分一部分至流量空闲机房,一起来分担压力。但是如果切分流量不足以解决问题,或所有机房流量负载都比较高,那我们只能通过熔断限流来保护整体系统服务,首先按照业务模块优先级进行排序,按照低优先级的业务进行依次降级,如果业务降级仍不能解决问题,那就开始依次停用低优先级业务,保住重要功能模块继续对外服务,极端情况下业务降级不能挺过流量高峰,那我们就采取限流保护措施,暂时舍弃少部分用户,来保住大部分高价值用户的可用性。
解决这个问题主要有以下几点:1,发现故障,2,定位故障原因,3,解决故障
这个三点同等重要,首先要及时发现故障,其实出现问题了并不可怕,可怕的是我们很久都没有发现问题,造成大量用户流失这才是最严重的。那么怎么来及时发现故障呢?
监控系统是整个系统环节,乃至整个产品生命周期中最重要的一环,事前及时预警发现故障,事后提供详细的数据用于追查定位问题。
一般而言一个完善的监控系统主要有这五个方面:1.系统资源,2.服务器,3.服务状态,4.应用异常,5.应用性能,6,异常追踪系统
1,系统资源监控
2,服务器监控
服务器的监控,主要是监控各个服务器,网络节点,网关,等网络设备,的请求响应是否正常。通过定时服务,定时去ping各个网络节点设备,以确认各网络设备是否正常,,如果哪个网络设备出现异常,则发出消息提醒。
3,服务监控
4,应用异常监控
主要有异常超时日志,数据格式错误,等
5,应用性能监控
6,异常追踪系统
我们目前线上使用的主要监控系统如下:
尽管使用了HTTPS技术,部分邪恶的运营商,会在HTTPS之前拦一刀,使用DNS污染技术,让域名指向的他们自己服务器,进行DNS劫持。
这个问题不解决,即使HTTPS的话也不能从根本上解决问题,仍然会有很多用户的访问出现问题。轻则对产品不信任,重则直接导致用户无法使用产品,导致用户流失。
那么根据第三方数据,对于鹅厂这样的互联网公司来讲,域名解析异常的情况到底有多严重呢?每天鹅厂的分布式域名解析监测系统在不停地对全国所有的重点LocalDNS进行探测,鹅厂域名在全国各地的日解析异常量是已经超过了80万条。这给业务带来了巨大的损失。
通过新闻APP端的日志监控分析发现:有1%-2%的用户存在DNS解析异常及接口访问不通的情况。
DNS异常,及无法访问接口
无形中造成大量用户流失,特别是在业务飞速发展的时期对业务的体验造成了非常大的损害。
那么有没有一种技术上的方案,能从根源上解决域名解析异常及用户访问跨网的问题和DNS劫持呢?
HttpDNS基于Http协议向DNS服务器发送域名解析请求,替代了基于DNS协议向运营商LocalDNS发起解析请求的传统方式,可以避免LocalDNS造成的域名劫持和跨网访问问题,解决移动互联网服务中域名解析异常带来的困扰。