前言为什么突然想写总结了?事实上,我被虐待了。今年3月初,我们商城接到了XX银行的一件代购活动(说白了就是羊毛)。当时,这是活动的第一阶段。没想到活动入口一打开,流量直接把CPU冲到100%。导致服务出现短502。期间采取了应急预案,一直到活动结束,没想到还有第二期活动,还有上周刚刚启动的第三期活动。考虑到最近做了一些事情,遇到了一些坑,趁着这个机会,就不偷懒记录下来了。你在活动的第一阶段到第三阶段做了什么?技术背景&瓶颈项目基于Vue+SSR架构,没有做缓存。不做缓存的主要原因是原来的应用tps比较低,改造的动力不强,页面渲染结果包含用户数据和服务器时间,不修改直接缓存。所以第一阶段的活动在被大量流量打的时候,在高并发下很容易把CPU打到100%。第一阶段,在未知情况下,服务无法直接处理。当时为了正常开展活动,首先解决的办法是增加机器来承担部分压力,然后再增加缓存。目前有两种缓存方案,缓存页面或者缓存组件,但是由于我们需要缓存的商品详情页面组件涉及到动态信息,可维护性太差,心理成本高,所以最终选择了前者。我们整理了业务详情页动态变化的信息数据(时间/用户等相关数据)。活动期间,紧急屏蔽了一些不影响功能的动态内容,然后在页面上传了CDN。活动结束后,我们做了一个回顾,好像应用在大流量的情况下一定要能够保证稳定运行,性能优化处理在所难免。为此,我们做了以下四种解决方案:1.静态和动态数据分离:我们可以将数据分为静态和动态两类。静态数据是一段时间内不随时间/用户而变化的数据。动态数据则相反。变化、时间相关和用户相关的数据都可以归类为动态数据。原始页面缓存失败的最大障碍是node在渲染模板时,会默认获取用户数据,或者在asyncData中调用用户相关接口;此外,它还会设置服务器时间等动态数据。所以思路是node上获取静态数据,动态数据放在客户端(浏览器生命周期中浏览器读取asyncData、mounted等)获取,保证服务端的整洁。2、页面接入CDN:动静分离改造后,其路径已经可以加入CDN。但是需要注意path上的query等参数是否会影响渲染。如果是这样,您需要将逻辑移至客户端。同时需要注意过期时间(比如10分钟)是否会影响业务。3、应用缓存:如果在CDN失效的情况下,回源率增加,应用本身还是需要准备的。需要根据项目需要选择内存缓存/redis缓存。4、自动降级:在极端情况下,之前的缓存不阻塞流量,需要终极解决方案:降级渲染。所谓降级渲染就是不进入路由直接返回空模板,完全交给浏览器渲染。这样做最大的好处就是完全避免了节点压力,把一个SSR应用变成了一个静态应用。劣势也很明显。用户看到的是一个空模板,需要等待初始化。那么如何自动降级呢,可以通过定时器查看cpu压力和负载来判断当前机器负载,从而决定是否降级;也可以通过查询url是否带有特定标识来决定是否显式降级。经过以上项目方案的性能优化,接下来就是压测,算是顺利上线了。🤪不久前二期活动又来了,不过正如我们所预料的那样,项目一直能够稳稳顶住压力,期间还增加了流量接口,增加了友情提醒等优化。但是痛点之一就是需要针对几个特殊的产品做一个文案流程。这些文案不是接口返回的,也是一些临时的醒目的提示,不需要在详情页接口返回。由于时间也很紧迫,我们不确定是否有具体的文案需求(与特定页面和特定区域相关联),所以我们决定暂时写一些低代码:针对特定的活动产品id,临时添加文案,活动下线后,删除文案。这样做是有风险的。毕竟代码是临时的,需要上线下线,有时间延迟。不过好在活动结束是周末,最后一天的访问量不是很大。给予了相应的指导文案和售后处理,估计影响不大,可以接受。下面图片的商品详情页和商品购买页需要添加的具体文案:XX事件的阶段,但整体计划仍然与第二阶段相同。心里:又来了???(小声打工人太难了),因为最终时间还没有定下来,吸取了二期的教训,我也跟后端同学商量了活动产品的配置。从方向上考虑,将文本模块放在我们的配置后台是可行的。对于商品详情页,为了不破坏动静分离,首先要保证配置接口返回的数据是静态的,并且可以在服务端获取到。具体完成以下三项工作:配置参与活动的商品文案,从配置界面获取,去除低代码。整理大流量活动页面(如业务详情页)的界面,放置在客户端的界面需要进行限定,接口达到一定的tps后,会返回429状态,前端需要做容错处理,页面功能可以正常访问,堵住限流接口的错误。购买限流接口需要忙音提示(活动太火,请稍后再试)//getResponseErrorInterceptor处429状态统一处理exportconstgetResponseErrorInterceptor=({errorCallback})=>(error)=>{if(!isClient){...}else{//429代码服务错误需要支持不弹出错误提示if(+error.response.status===429){//添加needBusyMsg属性限流接口和需要忙提示errorCallback(error.config.needBusyMsg?'活动太热,请稍后重试':null);}else{...);}}returnthrowError(error);};结束上周忙碌的压测和测试,第三期终于上线了。👏👏👏👏如果想了解更多VueSSR性能优化方案,可以移步这里:VueSSR性能优化实践实际过程中遇到的SomeCodingQuestions1.本地项目(vue-SSR架构),动态接口放置时服务端获取,有一段代码很简单,一个是否是会员的标志,开启会员按钮的显示和隐藏,代码如下(代码精简): Text
