查看原文
其他

【阿里在线技术峰会】郑恩阳:电商互动营销的技术实现

2016-07-29 郑恩阳 中生代技术
摘要:本文根据天猫技术部互动平台高级技术专家郑恩阳在首届阿里巴巴在线技术峰会上的分享整理而成。他主要通过全民疯坎和赛车竞速赢汽车案例分享了电商互动营销的整体架构、相应的技术、利用Tengine来分担服务器压力、防作弊策略实现、传统授权方法的优化以及利用Hilo引擎进行多渲染等。


互动营销案例

边看边买的互动


在做这个互动的时候,我们希望能够在顾客的购物路径上做一些改变和创新。当用户看到这个视频的时候,如果用户有需求,能够直接点击视频上的锚点,直接进行购物,可以直接购买到模特身上所穿的所有衣物和饰品。整个视频是一个全景拼接的视频,用户可以通过摇晃手机来看到更多的视场角。

全民疯坎


在这个案例中,其实用户的操作比较简单。用户通过滑动鼠标(PC端)或者滑动屏幕(手机端)进行砍价。用户参与过程中,后端服务器会计算当前有多少用户参与、发起多少砍价请求,整个的价格进度条会慢慢递减,一直递减到底价。达到底价后,我们会对参与的用户进行收集,然后开奖,幸运的用户可以通过底价来买到这些商品。


这个案例最大的挑战在于:我们希望通过真实流量的方式来触发整个价格的递减体系,而不是我们预设一个价格的递减过程。在砍价的过程中,用户的请求量会很大,预计有数百万用户同时参与砍价,每个用户每秒砍价2~3次,砍价QPS将达到千万级别。由于从早到晚每五分钟一次,所以保证绝对的稳定性也很重要。


那么,如何应对千万级别QPS呢?


为了应对上述挑战,设计了一个砍价的集群和一个开奖的集群。砍价的集群主要用来承接用户发起的砍价请求。前端、客户端可以做一些合并请求的处理,没有必要每次砍价都向服务端发送请求,假设客户端将5次砍价合并为一次请求,那么砍价请求的QPS将大大减少。此外,我们还可以通过加大轮询间隔来降低请求量。



在此基础上,我们利用了Tengine来分担服务器压力。经过性能测试,由应用服务器响应轮询请求,单机性能只能支持数千QPS,而如果由Tengine直接响应轮询请求,QPS则可以达到万级别。因此,我们决定由Tengine来直接响应轮询请求,在Tengine里面写一段Lua脚本,让Lua脚本每100ms去缓存集群进行同步当前商品最新的价格,返回给客户端。这样做可以将请求压力转交给缓存器,减少应用服务器的压力。


在此之后,我们需要做的是限流。首先,压测出每个接口的性能数据,根据压测结果对接口性能进行优化,然后根据实际的业务场景设计压测模型,得出实际场景下混合接口的性能数据。最终根据压测结果,结合业务需求,评估出系统的支撑容量。Tengine中部署了限流模块,超出容量的请求都会被限流,以保证系统的正常运行。



砍价的过程不能像秒杀一样,需要控制在1~3分钟,让更多的用户能够有机会参与。为了实现对砍价时间的控制,可以设计了一个命中率公式,命中率的计算综合考虑了商品的原价和底价以及实时的流量情况。如果到达期望时间点商品仍未到达底价,则逐步提高命中率,直至命中率提高为1。当然,在极端情况下,如果参与的用户非常少,那么商品可能会流拍,这也是符合业务需求的。



砍价集群会收集商品到达底价那一刻所有参与砍价的用户,并将这些用户信息分别写入缓存和数据库。产生候选名单的时候,使用了缓存和数据库双写的方式:这是为了稳定性考虑的冗余设计,因为需要在3秒内产生开奖结果,而无论是网络、缓存集群还是数据库,在高压情况下都有可能出现短暂的不稳定,也就是常说的抖动。



为了确保开奖过程万无一失,我们对开奖机制做了特别设计。首先,将开奖集群的机器分成两部分,一部分从缓存集群中读取候选用户数据,另一部分从数据库中读取,以避免可能发生的抖动。在开奖集群内部,使用生产者—消费者模式来分离职责,中间用一个阻塞队列连接。生产者线程从缓存集群或数据库中高速读取候选用户数据,并写入阻塞队列;消费者线程从阻塞队列中取出用户数据,并根据用户信息(比如用户参与的贡献度)进行分桶;当收集到足够数据或者到达预设的超时时间,将中奖结果写入数据库。当到达开奖时间(3秒),数据库中的前N名用户(N等于奖品数量)会被写入缓存集群,砍价集群的Tengine就可以通过Lua脚本获取到中奖名单。由于采用了竞争开奖,即使个别开奖机器出现故障,我们也能保证开奖成功。

赛车竞速赢汽车


挑战:对防作弊有很高要求,必须有一套完善的防作弊的机制来抵御一些恶意请求的用户。在这个案例中,用户操作赛车进行竞速赛,赛道上会出现一些随机的路障。需要解决的几个问题包括:前端需要有绘制赛道地图的能力;服务端需要有防范作弊的能力。


绘制赛道有两个选择,一是直线和贝塞尔曲线组合,二是直线和圆弧组合。


采用直线和圆弧组合时,前端工程师和设计师更方便确定参数;处理赛道和赛道叠加时候,不会出现贝塞尔曲线形变剧烈的情况,视觉感受上更容易接受;赛道的最后连接,使用圆弧切线相比贝塞尔曲线切线看起来更自然。直线+贝塞尔曲线的方式,可以在设计师设计阶段就导出地图的数据,但是圆弧需要记录的数据偏多,导出相对困难,而且如果日后需求改动,前端工程师无法对设计师完成的地图进行有效的数据校验。



为了解决上面提到的缺点,做了一个赛道地图编辑器。编辑器的主要作用就是完成地图的描点和相关的数据校验,并生成前后端统一的数据格式然后导出。使用赛道编辑器可以将数据和展现层进行分离,可以很随意的替换展现层,这样就可以做到一些类似换肤的功能。



防作弊策略——服务端重放技术。在前端用户操作的过程中,搜集用户整个操作的过程,将游戏过程中的所有操作和最终成绩上传给后端服务器。服务端会用类似前端的算法将用户操作作为输入,快速地将游戏过程重放一次得到一个正确的游戏成绩,将这个正确的成绩与用户上报的成绩作对比,验证用户的操作是否合理。在此过程中,可以通过压缩重放时间来完成瞬间验证。



防作弊策略——随机路障。为了解决脚本录制的问题,我们必须在游戏过程中增加随机性,让操作不可预测,为此,可以在赛道上设计路障。由服务端计算好开闭时间,由前端渲染到画面上。路障由服务端生成并下发给前端,并且需要具备一定的散列性。


互动开放体系


上图是整个开放体系的架构。第一部分是暴露给互动团队的API。客户端具有排插式的native扩展。客户端启动时,会把SDK具备的能力注册到API的服务管理器中。当SV通过TIDA API调用请求时,首先会通过bridge的接入层判断整个调用是哪一方的调用。如果是第三方的调用,会有一个授权的过程。


传统授权的优化


原协议是OAuth2的协议,是基于PC端的规范,过程中有很多次的redirect的跳转,致使客户端有很多白屏的现象,使得用户体验很差。此外,OAuth2协议会有Access Token泄露的情况。为了解决上述问题,我们新的协议是基于客户端的规范,有很多黑匣子可以保护客户的安全。整个过程是基于用户登录态设计的,Access Token不会给到SV去保存。具体过程见上图。

电商互动游戏引擎——Hilo


Hilo引擎具有的优点是:

  • 极简内核:Hilo核心模块极精简,保留了2D游戏引擎最必要的模块,同时采用模块化管理;

  • 完善接入&扩展:Hilo 支持多种模块范式的包装版本,包括AMD,CMD,Standalone多种方式接入。另外,你可以新增和扩展需要的模块和类型;

  • 多种渲染方式:提供DOM,Canvas,Flash,WebGL等多种渲染方案,可以做到跨全端,高性能的要求;

  • 完善的周边工具:提供动画编辑器 ,Yeoman脚手架及典型案例产出的辅助开发工具。



实现多渲染方式的原因:View和render进行了分离。View在自身属性进行更新的时候完全不需要考虑自己是怎么被画出来的。只要拿到了view,我们可以用不同的render把它描绘出来。Render主要解决两个问题:一是位置、尺寸、旋转等变化信息;二是渲染的信息。



接入Hilo没有使用传统模块定义范式,而是使用了module和requires,显得清晰简单。编译的时候,会把这些通过Hilo模块定义的范式翻译成传统模块定义的范式。



扩展Hilo时可以使用Class.mix(target, [mixinObject])方法将所需要的属性mix到class中。

关于Hilo的更多详情可以通过官网(https://github.com/hiloteam/Hilo)了解。

『中生代技术』


连接技术大咖的桥梁促进科技技术的交流


微信号:freshmanTechnology

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存