现在很多 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
优点:
- 所有弹窗频控后端可控。
- 有问题,可操作性强,可以操作redis,去除某些用户的频控限制。
缺点:
- 需要redis,造成架构复杂度上升,如果其他功能不需要使用 redis 的情况下,造成成本上涨。
- 用户量大的情况,比如上亿:redis 的key会非常大,造成redis压力。
3.2 前端缓存每个弹窗的最近一次弹出时间
前端存储每个用户弹窗的时间,请求后端的时候,把所有弹窗的上次弹出时间带给后端,由后端计算是否在频控时间范围内。
新弹窗弹出时间,由后端返给前端,前端存储,下次请求的时候带给后端。
优点:
- 不需要额外的存储,弹窗上次弹出时间存储在用户的客户端中。
- 架构简单。
- 问题好排查,直接看请求参数即可。
缺点:
- 用户卸载重装客户端的时候,会导致数据丢失,造成频控失效;
- 整个频控需要前后端配合才能完成,任何一方有问题,都有可能导致功能出问题。
4 怎么保证速度
异步执行所有弹窗,按顺序返回第一个有数据的弹窗,
参考:Reactor 之 多任务并发执行,结果按顺序返回第一个
欢迎大家提供更好的实现