ToC業務使用者彈窗的技術方案

六七十三發表於2023-04-01

現在很多 ToC 客戶端,比如:滴滴、美團、攜程等等,都有很多的彈窗,那後端怎麼設計更合理、更方便、成本更低呢?

我這裡說的彈窗是說一級頁面的彈窗,比如客戶端的首頁、個人中心頁面、訂單頁面等。這種一級頁面一般都有專門的部門負責,其他業務方需要接入彈窗,需要透過這個部門來接入。這裡定義兩種角色:

  • 接入方,是需要在首頁等頁面投放彈窗的業務部門。
  • 公共,負責首頁等公共頁面的部門。

這裡是我們的設計方案:

1 彈窗後端介面設計

1.1 彈窗型別很重要

首先要約束彈窗型別,

| 序號 | 彈窗型別 | 型別說明 |
| :- | :- | :- |
| 1 | 單圖片 | 彈出一張圖片,點選圖片跳轉 |
| 2 | 單Lottie | 彈出一個動圖,點選動圖或者按鈕跳轉 |
| 3 | 雙Lottie | 彈出一個動圖,點選或者自動跳轉第二個動圖,點選第二個動圖跳轉|
| 4 | 其他彈窗1 | 比如,需要前端拼接展示完整圖片的型別 |
| 5 | 其他彈窗 | 需要不同組合欄位組合彈窗資源的都算一種型別 |

1.2 彈窗介面設計

欄位名稱二級欄位欄位型別說明
status int成功失敗狀態碼
message String成功失敗資訊
data
popNameString彈窗名稱,可以用來埋點和彈窗區分
popInfoObject彈窗資源資源,每個型別彈窗裡面欄位不一致

比如圖片彈窗 popInfo

欄位名稱欄位型別說明
imgaeUrlString圖片url
imageWidthint圖片寬度
imageHeight 圖片高度
jumpUrlString跳轉url
popTypeint彈窗型別

其他型別彈窗按需設計欄位即可

2 配置即彈窗

標準型別的彈窗要支援配置即可,不用重複開發,要支援配置,可以有兩種型別:

  • 是所有人都出的彈窗,直接配置靜態資源即可。
  • 種是根據各個接入方自己的條件判斷是否出,彈窗資源接入方自己控制,這種需要接入方提供一個介面,這個介面是一個標準介面。

第一種方式比較簡單,就不說了。直接說第二種,直接制定一個標準介面,接入方直接實現即可。

統一入參,僅供參考,按需設計即可:

欄位名稱欄位型別說明
userIdString使用者id
userNameString使用者暱稱
deviceIdString裝置id
latString緯度
lonString經度

統一出參,這裡以單圖片彈窗為例:

欄位名稱二級欄位欄位型別說明
status int成功失敗狀態碼
message String成功失敗資訊
data
imgaeUrlString圖片url
imageWidthint圖片寬度
imageHeightint圖片高度
jumpUrlString跳轉地址
其他通用欄位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 之 多工併發執行,結果按順序返回第一個

歡迎大家提供更好的實現

相關文章