楚楚街是90后用户人群为主的特色移动电商,目前楚楚街只做移动端。平台目前用户数近亿规模,每日流量千万级别。
楚楚街早期以“9块9包邮”切入到电商业务,尽管目前平台已经转型为全品类高性价比的年轻用户喜欢的商品,但“9块9”早已深入人心。从2015年开始,楚楚街将9月9日定义为“楚楚节”,简称“99大促”。每年的9月9日,对于楚楚街来说,流量和业务成交都是与双十一比肩的。所以,对于楚楚街的技术人员来说,在双十一的准备方面有特殊之处:做好了99的考卷,双十一的压力就抗过了一大半。而这一份考卷不是模拟卷,而是真实的考试卷。
今年9月9日~11日,楚楚街的99大促顺利完成,抗住了峰值订单数为平时订单数100倍、流量峰值为平常峰值的50倍的压力。99大促的顺利进行不仅为双十一大促打下了良好的基础,也收获了很多宝贵的经验。大促的顺利进行离不开技术的支持,本文来介绍一下,楚楚街针对今年的两场大促,做了哪些技术上的优化升级。
楚楚街自营商城于2014年年底上线,上线后业务增长迅猛。与很多创业型公司面临的技术问题一样,早期的架构从底层数据到上层的web服务器全都耦合太强,所以从2015年7月开始,为了甩掉系统的历史包袱,开始做技术优化。而优化的核心就一个字——“拆”。
拆分我们主要按照如下几个阶段来做:
按照业务将落到服务器层的流量进行拆分
业务层代码的拆分
数据层的垂直拆分和服务化
第一阶段的拆分,我们主要是梳理业务,将业务进行合理的划分,将原始耦合在业务中的如短信、push、物流、ERP等抽象出平台级系统。其余核心业务如订单、商品、购物车、用户等系统,梳理好业务边界和接口,在最上层按照域名进行流量的切分,这样切分后,各个业务系统的边界清晰了,当大促等大流量活动期,也不会因为某一个业务流量过大引起整体业务雪崩,保证了部分业务可以正常运转。
第二阶段主要是做代码拆分,将过去耦合在一起的代码仓库根据第一阶段的拆分情况进行代码拆分,在拆分的基础上将冗余代码进行清理,可以有效提高系统的性能,增加了代码的可读和可维护性,各系统之间人员垂直,可以大大提升迭代能力。
第三阶段也是整个过程中最关键的阶段,那就是将业务下沉到服务,然后这个过程做DB的垂直的拆分。垂直拆分完成后,核心业务抽象成服务,将核心接口收拢,保证了有限的服务接口,提供了可分布扩展的性能,存储层可以根据服务接口解耦,并有效的保证了SQL等质量,保证了业务的稳定。
下面两图描述了我们拆前和拆后的一个架构对比。
图一:拆之前的架构
图二:拆后的架构
在拆的过程中抽象了很多基础系统:如分布式消息流、数据库中间层、基础业务服务化(用户服务、订单服务等)……
作为创业公司,“拆”的过程不允许耽误业务的发展。在业务发展中寻求技术优化,不耽误业务,与业务发展寻求一个契合点,需要有很强的业务理解力和技术把控力。目前,我们还走在整体服务化的路上。
多级缓存架构在大促这种大流量期间,针对于大量的“读”接口是意义巨大的,也是保证了大促期间业务稳定的重中之重,我们以商品详情页为例作一下介绍。
电商的流量大入口除了首页等导流页面外,商品详情页无疑是流量的集中点。而双十一、99等大促,详情页的访问量又达到历史之最。
详情页看似简单,但其有很多的业务逻辑:比如商品改价、库存变更、sku变更、评论评价等各类与数据强相关的业务逻辑。而详情页有一个非常大的特点,就是基本以读请求为主,因此,针对详情页这类的业务,我们创建多级缓存架构。
多级缓存架构根据业务流量的变化,是一个漏斗模型的系统架构,下层的流量越小,系统就越稳定,目前我们多级缓存架构主要是三层。
第一层是CDN,这一层主要缓存的是大促期间的主会场、分会场、秒杀商品的静态页、商品的富文本详情页、商品属性页等。这部分页面都是大促期间流量最大的,也是最要求速度和体验的,放到CDN,用户根据就近节点进行访问,大大加快了访问速度,并且减少了服务器层的压力。
第二层,我们用Nginx+Lua+OpenResty做了代理层缓存,这层缓存主要缓存住了提供给客户端的API接口的数据,这层cache根据商品的业务需要,会在活动规定时间内决定其cache有效性,一旦商品所在的活动失效,才会走到下一个层次——业务层;而99%以上的流量都在这一层给抗住了。
下图是本层的一个过程图。
第三层,我们在业务层添加了Memcached和Redis的Cache,这一层缓存了DB或者服务化接口拉取出来的数据,这层缓存的主要都是商品ID等纬度的业务数据,根据业务流转情况,保证这层的Cache数据都是实时的,确保了到DB层的量几乎很少。
最后流量才到数据库。数据库所起的作用是数据的持久化以及部分缓存失效的主动更新。根据这个架构,到达数据库的流量很少。
这套架构模型,让我们的详情页访问时间从早期的100ms左右,降到了20ms以内。同时单机能承载的详情页请求数量增加了100倍以上。
下图是此架构服务器部署的一个概述。
1. 流量预估和压测的意义
在每次有新系统上线,或者技术驱动的系统优化完成后,我们会进行系统压力测试。系统压力测试能非常清楚得知道:
对系统的压力有了预期,那么我们可以根据大促流量的情况,提前准备好机器。根据大促的流量如何,我们会对系统进行调整。
2. 如何进行流量预估
如何进行流量预估,流量预估其实是一个很难的问题。难点来自于以下2个问题:
针对第一个问题,我们会看总体运营数据和电商的行业总体情况来预估今年大促的用户量级。所以我们会抽取2015年大促的访问日志来做大规模用户行为分析,大致得出大促会场页、商品详情页、购物车、下单等的访问比例和峰值。
针对第二个问题,我们会提前跟业务团队同步大促要进行的活动内容,包括活动预热和大促当天。通过业务的理解来折算系统的峰值。
3. 如何压测
有了流量预估,就要对我们的性能进行压测。压测分为测试环境压测和线上生产环境的压测。我们更侧重于拥有流量链路的生产环境的压测。为什么流量链路的生产环境压测更为重要呢?因为业务其实一直是在变化的,生产环境的机器硬件环境也好、网络情况和整体业务链路都跟测试环境模拟出来的相差较大,当然压测出来的结果也是有所差异。
压测的方法,业内比较常见。我们采用了以下几个方法:
4. 总结
拿到压测结果,对于性能的短板,我们便开始进行性能改造提升。并且根据每一个服务的机器状况,在云端提前进行机器购买和刻录,为大促做好准备。
监控
楚楚街开发了一套自动化运维系统CMDB。CMDB实现了线上服务器的实时水位监控、业务服务监控、机器自动上下线、代码自动化部署等常见运维功能。根据机器、服务、业务的不同粒度,CMDB在监控和运维的功能描述如下:
在大促期间,运维同学根据业务线实时监控以及各类报警,能在第一时间发现有问题的业务、机器或者服务。根据不同问题的粒度,通过事前准备的预案,第一时间在CMDB上触发切换预案。
预案
双11的流量非常大,就算评估和扩容再好,也有可能出现底层服务、部分机器出问题的情况,这种情况是允许并且不可避免的。因此,根据不同的需求,我们准备了服务、机器、业务三种不同粒度的降级预案。
预案1:服务级别降级
线上系统的服务之间有调用和被调用的关系。一旦下游服务出现不响应,那上游服务要做实时降级。
以详情页评论评价为例。详情页一般都会展示评论评价,评论评价在整个链路里其实并不是一个核心链路,如果评论评价的服务接口挂掉,就算是设置了接口超时时间,由于瞬时流量很大,也依然会将整个交易系统拖死。所以针对非核心链路业务,我们进行了梳理,将非必要服务化接口做了熔断处理,如果接口失败,或者失败达到一定阈值,就不再调用评论评价这个服务,直接返回空数据,这样尽管评论评价不能显示,但正常的核心链路还是可以正常运转的。这是我们常说的有损服务。
预案2:机器预案
楚楚街目前使用zookeeper做服务管理。一旦服务宕机,会自动切换可用机器。同时,我们会根据CMDB反馈的水位情况,快速唤醒虚拟机并且进行对于服务的挂载。这体现了云服务的一个优势,尽早储备好虚拟机并且刻录好业务,服务器的增加是秒级别的操作。
预案3:业务级别的降级
在大促期间的高峰下单时间点,在业务允许范围内,我们会对业务进行降级。比如,在大促0点下单的高峰期,我们会禁用商家实时查看详细用户购买订单以减轻线上订单服务的压力;我们会在流量高峰期,将新用户注册发送优惠券的逻辑从在线逻辑切换到离线数据流逻辑,用户拿到优惠券的时间会比预期晚,但极大的减少了线上的压力。
99前的一个月,多级缓存的上线,让线上压力大大减少,因此我们有精力去更关注其他服务的优化。
这次99,我们的业务降级、服务器快速部署上线,在大促0点的时候起到了很关键的作用,用户在0点时候的下单体验仅有几秒的时间有轻微延迟,其余时间都体验流畅。
99的成功,是双十一之前的强心剂。双十一,楚楚街推出了很多新的业务形式,比如直播、预售等玩法,我们针对这些业务也做了详细的技术预案,但万变不离其宗:垂直业务 + 多级缓存 + 流量预估 + 监控降级, 这条路我们还会继续走下去。
InfoQ在线课堂将于11月22日晚8点开始,AWS首席云计算技术顾问费良宏将介绍用户在Amazon ECS上运行应用程序时所使用的范式和工具。目的是展示如何设置、管理和扩展Amazon ECS资源,保证安全并将应用部署到Amazon ECS集群。同时,费老师还将向您展示监测、记录和服务探索的“最佳实践“。点击“阅读原文”了解详情并报名。