互动营销案例
边看边买的互动
在做这个互动的时候,我们希望能够在顾客的购物路径上做一些改变和创新。当用户看到这个视频的时候,如果用户有需求,能够直接点击视频上的锚点,直接进行购物,可以直接购买到模特身上所穿的所有衣物和饰品。整个视频是一个全景拼接的视频,用户可以通过摇晃手机来看到更多的视场角。
全民疯坎在这个案例中,其实用户的操作比较简单。用户通过滑动鼠标(PC端)或者滑动屏幕(手机端)进行砍价。用户参与过程中,后端服务器会计算当前有多少用户参与、发起多少砍价请求,整个的价格进度条会慢慢递减,一直递减到底价。达到底价后,我们会对参与的用户进行收集,然后开奖,幸运的用户可以通过底价来买到这些商品。
这个案例最大的挑战在于:我们希望通过真实流量的方式来触发整个价格的递减体系,而不是我们预设一个价格的递减过程。在砍价的过程中,用户的请求量会很大,预计有数百万用户同时参与砍价,每个用户每秒砍价2~3次,砍价QPS将达到千万级别。由于从早到晚每五分钟一次,所以保证绝对的稳定性也很重要。
那么,如何应对千万级别QPS呢?
为了应对上述挑战,设计了一个砍价的集群和一个开奖的集群。砍价的集群主要用来承接用户发起的砍价请求。前端、客户端可以做一些合并请求的处理,没有必要每次砍价都向服务端发送请求,假设客户端将5次砍价合并为一次请求,那么砍价请求的QPS将大大减少。此外,我们还可以通过加大轮询间隔来降低请求量。
在此基础上,我们利用了Tengine来分担服务器压力。经过性能测试,由应用服务器响应轮询请求,单机性能只能支持数千QPS,而如果由Tengine直接响应轮询请求,QPS则可以达到万级别。因此,我们决定由Tengine来直接响应轮询请求,在Tengine里面写一段Lua脚本,让Lua脚本每ms去缓存集群进行同步当前商品最新的价格,返回给客户端。这样做可以将请求压力转交给缓存器,减少应用服务器的压力。
在此之后,我们需要做的是限流。首先,压测出每个接口的性能数据,根据压测结果对接口性能进行优化,然后根据实际的业务场景设计压测模型,得出实际场景下混合接口的性能数据。最终根据压测结果,结合业务需求,评估出系统的支撑容量。Tengine中部署了限流模块,超出容量的请求都会被限流,以保证系统的正常运行。
砍价的过程不能像秒杀一样,需要控制在1~3分钟,让更多的用户能够有机会参与。为了实现对砍价时间的控制,可以设计了一个命中率公式,命中率的计算综合考虑了商品的原价和底价以及实时的流量情况。如果到达期望时间点商品仍未到达底价,则逐步提高命中率,直至命中率提高为1。当然,在极端情况下,如果参与的用户非常少,那么商品可能会流拍,这也是符合业务需求的。
砍价集群会收集商品到达底价那一刻所有参与砍价的用户,并将这些用户信息分别写入缓存和数据库。产生候选名单的时候,使用了缓存和数据库双写的方式:这是为了稳定性考虑的冗余设计,因为需要在3秒内产生开奖结果,而无论是网络、缓存集群还是数据库,在高压情况下都有可能出现短暂的不稳定,也就是常说的抖动。
为了确保开奖过程万无一失,我们对开奖机制做了特别设计。首先,将开奖集群的机器分成两部分,一部分从缓存集群中读取候选用户数据,另一部分从数据库中读取,以避免可能发生的抖动。在开奖集群内部,使用生产者—消费者模式来分离职责,中间用一个阻塞队列连接。生产者线程从缓存集群或数据库中高速读取候选用户数据,并写入阻塞队列;消费者线程从阻塞队列中取出用户数据,并根据用户信息(比如用户参与的贡献度)进行分桶;当收集到足够数据或者到达预设的超时时间,将中奖结果写入数据库。当到达开奖时间(3秒),数据库中的前N名用户(N等于奖品数量)会被写入缓存集群,砍价集群的Tengine就可以通过Lua脚本获取到中奖名单。由于采用了竞争开奖,即使个别开奖机器出现故障,我们也能保证开奖成功。
赛车竞速赢汽车挑战:对防作弊有很高要求,必须有一套完善的防作弊的机制来抵御一些恶意请求的用户。在这个案例中,用户操作赛车进行竞速赛,赛道上会出现一些随机的路障。需要解决的几个问题包括:前端需要有绘制赛道地图的能力;服务端需要有防范作弊的能力。
绘制赛道有两个选择,一是直线和贝塞尔曲线组合,二是直线和圆弧组合。
采用直线和圆弧组合时,前端工程师和设计师更方便确定参数;处理赛道和赛道叠加时候,不会出现贝塞尔曲线形变剧烈的情况,视觉感受上更容易接受;赛道的最后连接,使用圆弧切线相比贝塞尔曲线切线看起来更自然。直线+贝塞尔曲线的方式,可以在设计师设计阶段就导出地图的数据,但是圆弧需要记录的数据偏多,导出相对困难,而且如果日后需求改动,前端工程师无法对设计师完成的地图进行有效的数据校验。
为了解决上面提到的缺点,做了一个赛道地图编辑器。编辑器的主要作用就是完成地图的描点和相关的数据校验,并生成前后端统一的数据格式然后导出。使用赛道编辑器可以将数据和展现层进行分离,可以很随意的替换展现层,这样就可以做到一些类似换肤的功能。
防作弊策略——服务端重放技术。在前端用户操作的过程中,搜集用户整个操作的过程,将游戏过程中的所有操作和最终成绩上传给后端服务器。服务端会用类似前端的算法将用户操作作为输入,快速地将游戏过程重放一次得到一个正确的游戏成绩,将这个正确的成绩与用户上报的成绩作对比,验证用户的操作是否合理。在此过程中,可以通过压缩重放时间来完成瞬间验证。
防作弊策略——随机路障。为了解决脚本录制的问题,我们必须在游戏过程中增加随机性,让操作不可预测,为此,可以在赛道上设计路障。由服务端计算好开闭时间,由前端渲染到画面上。路障由服务端生成并下发给前端,并且需要具备一定的散列性。
互动开放体系
上图是整个开放体系的架构。第一部分是暴露给互动团队的API。客户端具有排插式的native扩展。客户端启动时,会把SDK具备的能力注册到API的服务管理器中。当SV通过TIDAAPI调用请求时,首先会通过bridge的接入层判断整个调用是哪一方的调用。如果是第三方的调用,会有一个授权的过程。
传统授权的优化
原协议是OAuth2的协议,是基于PC端的规范,过程中有很多次的redirect的跳转,致使客户端有很多白屏的现象,使得用户体验很差。此外,OAuth2协议会有AccessToken泄露的情况。为了解决上述问题,我们新的协议是基于客户端的规范,有很多黑匣子可以保护客户的安全。整个过程是基于用户登录态设计的,AccessToken不会给到SV去保存。具体过程见上图。
电商互动游戏引擎——HiloHilo引擎具有的优点是:
极简内核: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的更多详情可以通过