ToC业务用户弹窗的技术方案

  • Post author:
  • Post category:其他


现在很多 ToC 客户端,比如:滴滴、美团、携程等等,都有很多的弹窗,那后端怎么设计更合理、更方便、成本更低呢?

我这里说的弹窗是说一级页面的弹窗,比如客户端的首页、个人中心页面、订单页面等。这种一级页面一般都有专门的部门负责,其他业务方需要接入弹窗,需要通过这个部门来接入。这里定义两种角色:

  • 接入方,是需要在首页等页面投放弹窗的业务部门。
  • 公共,负责首页等公共页面的部门。

这里是我们的设计方案:



1 弹窗后端接口设计



1.1 弹窗类型很重要

首先要约束弹窗类型,

序号 弹窗类型 类型说明
1 单图片 弹出一张图片,点击图片跳转
2 单Lottie 弹出一个动图,点击动图或者按钮跳转
3 双Lottie 弹出一个动图,点击或者自动跳转第二个动图,点击第二个动图跳转
4 其他弹窗1 比如,需要前端拼接展示完整图片的类型
5 其他弹窗 需要不同组合字段组合弹窗资源的都算一种类型



1.2 弹窗接口设计

字段名称 二级字段 字段类型 说明
status int 成功失败状态码
message String 成功失败信息
data
popName String 弹窗名称,可以用来埋点和弹窗区分
popInfo Object 弹窗资源资源,每个类型弹窗里面字段不一致

比如图片弹窗 popInfo

字段名称 字段类型 说明
imgaeUrl String 图片url
imageWidth int 图片宽度
imageHeight 图片高度
jumpUrl String 跳转url
popType int 弹窗类型

其他类型弹窗按需设计字段即可



2 配置即弹窗

标准类型的弹窗要支持配置即可,不用重复开发,要支持配置,可以有两种类型:

  • 是所有人都出的弹窗,直接配置静态资源即可。
  • 种是根据各个接入方自己的条件判断是否出,弹窗资源接入方自己控制,这种需要接入方提供一个接口,这个接口是一个标准接口。

第一种方式比较简单,就不说了。直接说第二种,直接制定一个标准接口,接入方直接实现即可。

统一入参,仅供参考,按需设计即可:

字段名称 字段类型 说明
userId String 用户id
userName String 用户昵称
deviceId String 设备id
lat String 纬度
lon String 经度

统一出参,这里以单图片弹窗为例:

字段名称 二级字段 字段类型 说明
status int 成功失败状态码
message String 成功失败信息
data
imgaeUrl String 图片url
imageWidth int 图片宽度
imageHeight int 图片高度
jumpUrl String 跳转地址
其他通用字段 String 埋点等通用字段

接入的时候,公共方配置接入方的接口地址即可。



3 频控的两种技术方案

基本上除了某些 APP 之外,所有 APP 的弹窗都不会无限制的弹,都需要频控,否则可能导致用户体验的下降和用户的流失。



3.1 redis setex 弹出缓存自动过期

用户每次弹窗都使用redis 的 setex 设置过期时间,这个时间就是业务允许两次弹窗之间的最小间隔时间。

key 设计:popName + userId

优点:

  1. 所有弹窗频控后端可控。
  2. 有问题,可操作性强,可以操作redis,去除某些用户的频控限制。

缺点:

  1. 需要redis,造成架构复杂度上升,如果其他功能不需要使用 redis 的情况下,造成成本上涨。
  2. 用户量大的情况,比如上亿:redis 的key会非常大,造成redis压力。



3.2 前端缓存每个弹窗的最近一次弹出时间

前端存储每个用户弹窗的时间,请求后端的时候,把所有弹窗的上次弹出时间带给后端,由后端计算是否在频控时间范围内。

新弹窗弹出时间,由后端返给前端,前端存储,下次请求的时候带给后端。

优点:

  1. 不需要额外的存储,弹窗上次弹出时间存储在用户的客户端中。
  2. 架构简单。
  3. 问题好排查,直接看请求参数即可。

缺点:

  1. 用户卸载重装客户端的时候,会导致数据丢失,造成频控失效;
  2. 整个频控需要前后端配合才能完成,任何一方有问题,都有可能导致功能出问题。



4 怎么保证速度

异步执行所有弹窗,按顺序返回第一个有数据的弹窗,

参考:

Reactor 之 多任务并发执行,结果按顺序返回第一个

欢迎大家提供更好的实现



版权声明:本文为Prepared原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。