谈谈请求,负载,以及优化

2020-12-27
过气架构师现在谈技术总是没什么底气,总觉得有些思路还是可以分享给初入行的年轻人。

图片来源摄图网

编者按:本文来自caoz的梦呓,作者caozsay,创业邦经授权转载。

过气架构师现在谈技术总是没什么底气,倚老卖老一些,总觉得有些思路还是可以分享给初入行的年轻人。

很多时候,线上服务会遭遇到负载压力,会导致崩溃。那么很多时候,技术人员会说,这是请求过多导致的,这个理由很合理,毕竟服务器资源有限,请求的响应能力也有限。

但关于请求,其实是可以继续拆解和细分的。

1、原始请求,也就是用户的真实请求,比如用户访问网页,点击下载,触发某个操作,服务器受到用户的操作请求,进行处理。

通常,当我们面临请求过多的问题,需要先明确,原始请求是多少,这是衡量负载支撑合理性的最核心指标。

那么似乎很多人会认为,原始请求是不可优化的,不可裁剪的,其实未必,比如合理设置客户端缓存,在特定场景里,可以让原始请求频次大幅度下降。

草根时期的hao123就把浏览器缓存设置的非常长,十五年前的新浪架构师杨建也是玩缓存的高手,连图文直播的客户端缓存都可以优化,从而极大减轻服务端的负载压力。

2、衍生请求,在执行原始请求的过程中,程序和系统所衍生出来的请求。

比如,你访问一个网站,执行这个html的时候,会衍生出很多内嵌文件的请求,比如css,比如js,比如图标和logo,这里其实也是有很多前端优化细节,当然,这是pc时代的传统技能,现在基本无人关心了,旧文我记得提过,我也就不做无谓的炫技了。

比如,用户请求一个网页的时候,后端代码触发了数据库请求,缓存请求,第三方接口请求等等,也都是衍生请求。

在面向对象编程风靡的时代,为了满足一些通用性和普适性的诉求,一些不合理的封装结构里经常有大量冗余的衍生请求,这会带来负载的不合理开销。而随着硬件性能的逐渐提升,传统面向过程锱铢必较的优化手艺人越来越不受待见,到很像年轻人对老一代超级节俭的消费观不以为然的那种感觉,这也是一种时代的进步吧。

如果不出问题,当然都不是问题,但如果频繁出问题,其实这里是有一些方法论的。

常见方法1,请求解耦

某些请求连接在处理完之后,没有及时关闭,而程序发生了另一种请求,那么这时候,后者请求的阻塞会连带前者请求的阻塞和崩溃。这是常见的一种请求的不当耦合。任何请求操作完成,及时关闭链接,是一种好习惯,可能说过一会还要请求这个链接,r如果中间过程简单可控当然也可以,但如果中间有较为复杂的诸多其他请求,我建议过一会重新开启请求都比持续链接要安全。

此外,如有可能,最好一次请求处理完所有与该请求目标有关的相关事务,不要拖拖拉拉的请求,而且中间夹杂着很多其他不同请求。

常见方法2,异步处理

突然想起一个流行词,延时满足。到还挺符合。

理论上,所有不需要实时反馈的信息,都可以放在后台异步处理,与前端请求脱钩。

异步处理可以解决大量衍生请求的问题,举个例子,cnzz 2005年从各种草根站长的统计系统中脱颖而出,其实就是因为用了异步处理的思想,统计代码请求服务器之后,不请求数据库,不请求中间层,代码只做日志存储,后台通过日志做异步统计,而且异步处理可以基于某些策略,大量合并请求处理,这样就极大降低了服务端的负载压力。那有人会说,cnzz当时不是号称实时统计么?后台任务每分钟处理,一分钟的时延,用户体验不会有问题的。

有些时候,用户感知是实时回馈的数据和信息,可能并不一定是实时的,一个可靠的异步处理方案,完全可以做到只有1分钟以内的延时响应。

常见方法3,随动加载

资源预加载现在是很常见的,因为可以保持后续操作的流畅性,广告的预加载,游戏内容的预加载,等等等等。与之对应的就是随动加载,也就是跟随用户的操作逐渐加载。随动加载的好处是可以减少衍生请求,降低服务端负载,但缺点就是,操作体验的流畅性会受到一定影响。

这里不存在绝对的正确和错误,根据业务场景诉求斟酌选择。

但其实存在一种兼顾的策略,在负载较轻的时候偏向于预加载,提升用户流畅性感知,在负载较重超过阈值的时候,偏向于随动加载,降低负载保护服务端稳定性。

常见方法4,中间层隔离

前端的所有衍生请求指向中间层,中间层调配请求并通过长连接与后端诸如数据库,缓存,队列都系统通讯。中间层起到了弹性缓冲的作用,可以有效保护大量请求的过载,有些中间层如果设计合理,也可以将大量衍生请求快速合并处理,从而大幅度降低衍生请求的负载压力。

3、雪崩效应导致的请求爆炸

当系统遭遇一些故障的时候,因为某些请求被阻塞,带来连锁反应,相关大量请求被阻塞,系统负载或者一些请求链接数会呈现爆炸式增长,很多时候,即便快速增加资源也无济于事。微博的几次热点八卦事件引发的崩溃,都是这种雪崩效应的体现。

举例来说,请求缓存,如果找不到数据就请求数据库,通常可能数据库的溯源比例不超过30%,但因为缓存被异常清理,所有缓存请求被溯源,导致数据库请求飙升,直接崩溃,这就是一种典型的雪崩效应。

雪崩效应带来的请求也分两种,第一种是来自于系统层面的连锁反应,A阻塞导致B阻塞,B又导致C阻塞,然后某些原因又导致阻塞被放大,最后形成全面的超级崩溃。第二种来自于用户的操作反馈,用户发现页面无法打开或者操作没有响应,往往下意识的频繁刷新操作,这种用户面对问题的频繁操作,也会加剧雪崩效应。

那么面对雪崩效应,其实也是有一些方法论的。

常见方法1,降级响应

在服务雪崩的情况下,系统降级响应,保住核心业务,舍弃次要业务,直到系统恢复。

常见方法2,紧急阻断

当发现负载超标时,应给予用户友好提示,并自动拒绝接受刷新和重复加载的请求。

常见方法3,单点隐患摘除

尽可能让系统不存在单点依赖,每个单点都有自动容灾备份及自动恢复的机制,一旦出现问题,备用系统可以自动上线应急,只要应急效率足够高,那么雪崩发生的几率就会极大降低。

其实前文的请求解耦,异步处理和中间层隔离,不仅可以有效优化大量的衍生请求,对于防范雪崩效应也是非常有意义的,就不再赘述。

大体如此,那么现在由于云服务技术非常先进,很多新的架构方案把早年很多架构师需要自己处理的东西都系统化了,确实技术进展太快,很多领域我已经没有话语权了。

那么有一点要说明的就是,当云服务资源在应急响应扩展的时候,不仅仅要关注各种资源的扩充,也要关注一些制约参数的扩充,这些其实往往隐藏很深,也是经常造成所谓“莫名其妙崩溃”,并且“加资源也解决不了”的现象。非常需要认真并且细心的了解系统层面及云主机服务商各个层面的参数设计理念。

另外就是,如果原始请求增长有限,而系统请求急速激增的时候,前面的内容可以按部就班的核对一下。

最后,优化是无止境的,但毕竟不是每个公司都需要应对阿里,腾讯那样的响应规模,所以,在成本及风险可控的情况下,抓大放小即可,无需沉迷于过度优化,我们那代人用户流量不值钱,带宽和计算资源值钱,所以习惯了抠抠索索的处理方式,特别是4399,单用户价值比行业均值低太多,用户请求规模又大,所以成本概念就特别强,额外的对资源较真,也是我当年自称经济适用架构师的由来。时代进步了,人力成本在飙升,计算资源成本在骤降,这种情况下,过度优化可能就得不偿失了,这是新时代的成本观。

大体如此吧。

本文(含图片)为合作媒体授权创业邦转载,不代表创业邦立场,转载请联系原作者。如有任何疑问,请联系editor@cyzone.cn。