雲栖号資訊:【 點選檢視更多行業資訊】
在這裡您可以找到不同行業的第一手的上雲資訊,還在等什麼,快來!
背景
複雜事件處理(Complex Event Processing,以下簡稱 CEP)在閑魚内得到了廣泛應用,基于使用者使用閑魚的實時行為,為使用者提供更加豐富的優質資訊與服務。閑魚技術公衆号有介紹過 CEP 在服務端和用戶端上的設計與實作。然而之前的設計方案都隻适用于閑魚 App 端内場景,針對端外投放拉新場景(例如使用者通路了多個商品詳情頁之後給使用者發放優惠引導使用者下單)需要設計在純前端環境執行的實時 CEP 架構。本文主要介紹了在前端實作 CEP 的相關設計與實作。
設計目标
整個流程可以抽象為使用者實時行為按照一系列規則比對之後,以前台 UI 的方式對使用者進行觸達幹預。對外投業務場景進行抽象,除了 CEP 基礎能力之外,還有這三點關鍵設計目标:
觸達實時:從使用者相關行為操作到對使用者進行觸達幹預要盡量快,如果整個流程不夠快,在觸達幹預的時候使用者可能已經流失了。
政策動态:業務需要經常對線上政策進行調整,期望業務開發隻需要做一次接入,後續政策都可以服務端動态下發。
多容器:外投場景包括小程式 /Web/Weex 這幾種容器場景,都需要支援。
架構設計
将業務流程拆解為三部分,分别是使用者實時行為采集、對實時行為按照規則複雜計算、以前端 UI 元件進行使用者觸達,對應三個核心子產品:事件采集、複雜計算和使用者觸達。針對上述設計目标,為了實作觸達實時,将對行為的複雜計算放到前端去執行;為了實作政策動态,設計了一個服務端營運平台管理所有政策,采集行為資訊、複雜計算規則、觸達元件資訊都從服務端擷取;為了實作多容器,将實時行為采集和 UI 元件觸達進行标準設計,分不同容器環境實作。此外由于政策會存在跨頁面的場景,底層會有資料同步子產品同步行為資料和計算狀态。下面分别對重要子產品進行詳細介紹。

事件采集
事件采集子產品将使用者行為轉化為标準事件。首先是使用者行為無侵入采集,無侵入采集是為了解決兩個問題,第一個是為了讓業務開發接入更加簡單,不需要手動調用采集代碼;第二個是為了覆寫更多可能的采集點,利于後續政策動态下發。這裡我們選用靜态掃描代碼的方式,在具有特定行為标示(例如 onClick)的元素節點上注入采集參數,采集參數通過元素樣式名稱、元件名稱、檔案路徑等資訊生成,具有比較好的語義;并且和運作時無關,更利于擴充不同容器實作。
初期先定義了使用者基礎操作行為(enter、leave、scroll、appear、click),使用者行為多樣并且形态複雜,是以首先需要将使用者行為做标準化處理。此外随着業務使用後續有一些業務子產品也要事件形式進入計算,例如 http 請求傳回的結果也會作為一個事件,因為這裡設計了一個插件機制,能夠讓業務子產品快速轉化成标準行為。
複雜計算
目前社群前端複雜計算相關方案都比較簡單,不适用于業務場景。自研上選擇參考業界 CEP 标準實作,業界 CEP 設計主要源于這篇論文 Efficient Pattern Matching over Event Streams,在這篇文章裡介紹了 CEP 的核心是 NFA(不确定的有限狀态機),CEP 的比對過程就是 NFA 狀态變化的過程。是以首先在前端實作了一個 NFA 類,實作這樣一個狀态機。
但是我們無法直接建立一個 NFA 去描述比對規則,更習慣按照事件間關系與每個事件的比對規則去定義,是以需要在上層封裝一套 API 來建立 NFA。這裡參考了 Flink CEP Pattern API 的設計。通過 next/followedBy/followedByAny/notNext/notFollowedBy 等 API 來定義事件間關系,通過 where/and/or 等 API 來定義每個事件的比對規則。通過 Pattern 定義會生成一個中間連結清單,生成 NFA 的過程就是反向解析這個連結清單。
前端做複雜計算我們總會擔心性能是否有問題。以下面這個性能壓測為例,有 20 個政策在做比對的情況下,一次灌入 200 條行為資料,整體耗時在 3.73s。雖然時間并不是特别長,但是由于浏覽器運作機制,JS 引擎線程在執行的情況下,UI 渲染線程也會被挂起,在這 3.73s 内使用者所有在頁面上的操作都得不到響應,感覺就是“卡住了”。是以前端複雜計算性能優化更多需要考慮計算過程中不能影響使用者體驗。
對比目前業内的解法,Worker 和 Webassembly 存在容器限制以及優化效果可能不明顯。這裡選用了一種時間切片的解法,整體思路和 React Fiber 機制比較類似。将複雜計算的大任務拆解為小任務執行,在小任務執行完之後,會适當讓出 JS 主執行線程的控制權,讓浏覽器能夠響應使用者操作,保證使用者操作不受影響。下面這張圖是優化後的效果,可以看到每個任務執行之後有一段空閑。并且這個優化方式是純 JS 層面的優化,不受單一容器的限制。
使用者觸達
使用者觸達子產品管理使用者前台展示元件,出于對 bundle 大小的考慮,元件代碼都通過動态加載的方式。由于需要針對不同容器實作,在上層統一标準元件的設計,包括統一元件 API、輸入資料源以及埋點資訊等。元件相關設計最終會影響各容器實作成本和業務效果統計。
資料同步
由于跨頁面場景(例如通路了詳情頁又通路了這個賣家的閑魚号)存在,而前端多個頁面之間不具備通信能力,也不存在一個線程在背景一直處理業務邏輯,是以在行為資料以及計算狀态的同步上需要依賴本地存儲能力。前端本地存儲都隻支援 Key/Value 存儲,能力相對較弱,頻繁讀寫資料容易出錯。是以在本地存儲上層實作一層記憶體緩存,擴充了一些存儲能力,每隔一段時間或者在一些時間節點上(例如離開頁面)和本地存儲同步,這樣既保證了存儲的靈活性,又實作了跨頁面資料同步。
未來展望
目前該前端 CEP 架構已投入線上業務使用,在阿裡小程式、Weex、Web 下都能良好運作,并且提供了一定的營運配置能力,在目前線上單一政策下整個流程可以在毫秒級内完成,後續在業務上會有更廣泛的使用。
在技術細節以及業務易用性上,我們依然有很多可以完善的地方,後續的一些演進方向如下:
端内外全鍊路觸達:與服務端、用戶端在行為定義、規則計算、觸達幹預上統一一套标準協定,在閑魚端内外全鍊路上此類問題通過統一一個系統承接。
營運體系完善:讓業務更加便捷建構政策投放,在資料挖掘上能夠更好輔助業務做決策。
智能化:将目前依據業務經驗的規則比對向算法根據使用者行為智能決策轉化,同時探索前端智能化的可能性。
【雲栖号線上課堂】每天都有産品技術專家分享!
課程位址:
https://yqh.aliyun.com/zhibo立即加入社群,與專家面對面,及時了解課程最新動态!
【雲栖号線上課堂 社群】
https://c.tb.cn/F3.Z8gvnK
原文釋出時間:2020-05-15
本文作者:玉缜
本文來自:“
InfoQ”,了解相關資訊可以關注“[InfoQ](
https://www.infoq.cn/article/pPzmWUUEGF1V6piNAgSU”