需求,app中使用webview和h5交互,根據(jù)h5發(fā)過來的消息,在屏幕上展示flutter組件,并且可以發(fā)送消息給h5。

創(chuàng)新互聯(lián)專注于林口網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供林口營銷型網(wǎng)站建設(shè),林口網(wǎng)站制作、林口網(wǎng)頁設(shè)計、林口網(wǎng)站官網(wǎng)定制、微信小程序開發(fā)服務(wù),打造林口網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供林口網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。
首先使用的組件是flutter_WebView_plugin,這個組件不能嵌套flutter組件,所以放棄這個組件。
flutter_inappbrowser 可以實現(xiàn)組合布局, 所以選用了此庫, GitHub鏈接
[
Flutter支持穩(wěn)定的桌面設(shè)備開發(fā)已經(jīng)一段時間了,不得不說,F(xiàn)lutter多平臺支持的特性真的很香。我本人并沒有任何桌面開發(fā)的經(jīng)驗,但仍然使用Flutter開發(fā)出了一個桌面版小程序,功能很簡單,就是對輸入的json做格式化處理和轉(zhuǎn)模型。
話不多說,先來看看實際效果。 項目源碼地址
開發(fā)環(huán)境如下:
Flutter : 2.8.1
Dart : 2.15.1
IDE : VSCode
JSON作為我們?nèi)粘i_發(fā)工作中經(jīng)常要打交道的一種數(shù)據(jù)格式,它共有6種數(shù)據(jù)類型: null , num , string , object , array , bool 。我們勢必對它又愛又恨。愛他因為他作為數(shù)據(jù)處理的一種格式確實非常方便簡潔。但是在我們做Flutter開發(fā)中,又需要接觸到j(luò)son解析時,就會感覺非常棘手,因為flutter沒有反射,導(dǎo)致json轉(zhuǎn)模型這塊需要手寫那繁雜的映射關(guān)系。就像下面這樣子。
數(shù)據(jù)量少還能接受,一旦量大,那么光手寫這個解析方法都能讓你懷疑人生。更何況手寫還有出錯的可能。好在官方有個工具**json_serializable**可以自動生成這塊轉(zhuǎn)換代碼,也解決了flutter界json轉(zhuǎn)模型的空缺。當(dāng)然,業(yè)界也有專門解析json的網(wǎng)站,可以自動生成dart代碼,使用者在生成后復(fù)制進項目中即可,也是非常方便的。
本項目以json解析為切入點,和大家一起來看下flutter是如何開發(fā)桌面應(yīng)用的。
要讓我們的flutter項目支持桌面設(shè)備。我們首先需要修改下flutter的設(shè)置。如下,讓我們的項目支持 windows 和 macos 系統(tǒng)。
接下來使用 flutter create 命令創(chuàng)建我們的模版工程。
創(chuàng)建完項目后,我們就可以 run 起來了。
先來看下整體界面,界面四塊,分別為功能模塊、文件選擇模塊、輸入模塊、輸出模塊。
我們在新建一個桌面應(yīng)用時,默認(rèn)的模版又一個Appbar,此時應(yīng)用可以用鼠標(biāo)拖拽移動,放大縮小,還可以縮到很小。但是,我們一旦去掉這個導(dǎo)航欄,那么窗口就不能用鼠標(biāo)拖動了,并且我們往往不希望用戶將我們的窗口縮放的很小,這會導(dǎo)致頁面異常,一些重要信息都展示不全。因此這里需要借助第三方組件 bitsdojo_window 。通過 bitsdojo_window ,我們可以實現(xiàn)窗口的定制化,拖動,最小尺寸,最大尺寸,窗口邊框,窗口頂部放大、縮小、關(guān)閉的按鈕等。
通過 InkWell 組件,可以捕捉到手勢、鼠標(biāo)、觸控筆的移動和停留位置
這個功能是鼠標(biāo)移動后的UI交互界面。要在窗口上顯示一個提示框,可以使用 Overlay 。需要注意的是,由于在 Overlay 上的 text 的根結(jié)點不是 Material 風(fēng)格的組件,因此會出現(xiàn)黃色的下劃線。因此一定要用 Material 包一下 text 。并且你必須給創(chuàng)建的 OverlayEntry 一個位置,否則它將全屏顯示。
讀取說表拖拽的文件一開始想嘗試使用 InkWell 組件,但是這個組件無法識別拖拽中的鼠標(biāo),并且也無法從中拿到文件信息。因此放棄。后來從文章《Flutter-2天寫個桌面端APP》中發(fā)現(xiàn)一個可讀取拖拽文件的組件 desktop_drop ,能滿足要求。
使用開源組件 file_picker ,選完圖片后的操作和拖拽選擇圖片后的操作一致。
Textfield 如果要顯示富文本,那么需要自定義 TextEditingController 。并重寫 buildTextSpan 方法。
在做導(dǎo)出功能時遇到下列報錯,保存提示為沒有權(quán)限訪問對應(yīng)目錄下的文件。
通過Apple的開發(fā)文檔找到有關(guān)權(quán)限問題的說明。其中有個授權(quán)私鑰的key為 com.apple.security.files.downloads.read-write ,表示 對用戶的下載文件夾的讀/寫訪問權(quán)限 。那么,使用Xcode打開Flutter項目中的mac應(yīng)用,修改工程目錄下的 DebugProfile.entitlements 文件,向 entitlements 文件中添加 com.apple.security.files.downloads.read-write ,并將值設(shè)置為YES,保存后重啟Flutter項目。發(fā)現(xiàn)已經(jīng)可以向下載目錄中讀寫文件了。
當(dāng)然,這是正常操作。還有個騷操作就是關(guān)閉系統(tǒng)的沙盒機制。將 entitlements 文件的 App Sandbox 設(shè)置為NO。這樣我們就可以訪問任意路徑了。當(dāng)然關(guān)閉應(yīng)用的沙盒也就相當(dāng)于關(guān)閉了應(yīng)用的防護機制,因此這個選項慎用。
原文地址:
沒有。
咸魚flutter沒有換成h5,咸魚不僅有flutter的開發(fā)應(yīng)用,還包括h5的開發(fā)應(yīng)用,flutterflutter更偏向客戶端的研發(fā)體系,h5性能穩(wěn)定,因為二者有不同的優(yōu)勢,所以咸魚flutter沒有換成h5,而是兩者共用。
咸魚flutter是一個全新的移動UI框架,它允許使用同一個代碼庫構(gòu)建高性能的Android和iOS應(yīng)用,在此基礎(chǔ)之上,以h5為數(shù)據(jù)分析的系統(tǒng),進行大數(shù)據(jù)分析,從而二者共同促進咸魚的使用率。
文/陳爐軍
整理/LiveVideoStack
大家好,我是阿里巴巴閑魚事業(yè)部的陳爐軍,本次分享的主題是Flutter浪潮下的音視頻研發(fā)探索,主要內(nèi)容是針對閑魚APP在當(dāng)下流行的跨平臺框架Flutter的大規(guī)模實踐,介紹其在音視頻領(lǐng)域碰到的一些困難以及解決方案。
分享內(nèi)容主要分為四個方面,首先會對Flutter有一個簡單介紹以及選擇Flutter作為跨平臺框架的原因,其次會介紹Flutter中與音視頻關(guān)系非常大的外接紋理概念,以及對它做出的一些優(yōu)化。之后會對閑魚在音視頻實踐過程中碰到的一些Flutter問題提出了一些解決方案——TPM音視頻框架。最后是閑魚Flutter多媒體開源組件的介紹。
Flutter
Flutter是一個跨平臺框架,以往的做法是將音頻、視頻和網(wǎng)絡(luò)這些模塊都下沉到C++層或者ARM層,在其上封裝成一個音視頻的SDK,供UI層的PC、iOS和Android調(diào)用。
而Flutter做為一個UI層的跨平臺框架,顧名思義就是在UI層也實現(xiàn)了一個跨平臺開發(fā)。可以預(yù)想的是未Flutter發(fā)展的好的話,會逐漸變?yōu)橐粋€從底層到UI層的一個全鏈路的跨平臺開發(fā),技術(shù)人員分別負(fù)責(zé)SDK和UI層的開發(fā)。
在Flutter之前已經(jīng)有很多跨平臺UI解決方案,那為什么選擇Flutter呢?
我們主要考慮性能和跨平臺的能力。
以往的跨平臺方案比如Weex,ReactNative,Cordova等等因為架構(gòu)的原因無法滿足性能要求,尤其是在音視頻這種性能要求幾乎苛刻的場景。
而諸如Xamarin等,雖然性能可以和原生App一致,但是大部分邏輯還是需要分平臺實現(xiàn)。
我們可以看一下,為什么Flutter可以實現(xiàn)高性能:
原生的native組件渲染以IOS為例,蘋果的UIKit通過調(diào)用平臺自己的繪制框架QuaztCore來實現(xiàn)UI的繪制,圖形繪制也是調(diào)用底層的API,比如OpenGL、Metal等。
而Flutter也是和原生API邏輯一致,也是通過調(diào)用底層的繪制框架層SKIA實現(xiàn)UI層。這樣相當(dāng)于Flutter他自己實現(xiàn)了一套UI框架,提供了一種性能超越原生API的跨平臺可能性。
但是我們說一個框架最終性能怎樣,其實取決于設(shè)計者和開發(fā)者。至于現(xiàn)在到底是一個什么狀況:
在閑魚的實踐中,我們發(fā)現(xiàn)在正常的開發(fā)沒有特意的去優(yōu)化UI代碼的情況下,在一些低端機上,F(xiàn)lutter界面的流暢性是比Native界面要好的。
雖然現(xiàn)在閑魚某些場景下會有卡頓閃退等情況,但是這是一個新事物發(fā)展過程中的必然問題,我們相信未來性能肯定不會成為限制Flutter發(fā)展的瓶頸的。
在閑魚實踐Flutter的過程中,混合棧和音視頻是其中比較難解決的兩個問題,混合棧是指一個APP在Flutter過程中不可能一口氣將所有業(yè)務(wù)全部重寫為Flutter,所以這是一個逐步迭代的過程,這期間原生native界面與Flutter界面共存的狀態(tài)就稱之為混合棧。閑魚在混合棧上也有一些比較好的輸出,例如FlutterBoost。
外接紋理
在講音視頻之前需要簡要介紹一下外接紋理的概念,我們將它稱之為是Flutter和Frame之間的橋梁。
Flutter渲染一幀屏幕數(shù)據(jù)首先要做的是,GPU發(fā)出的VC信號在Flutter的UI線程,通過AOT編譯的機器碼結(jié)合當(dāng)前Dart Runtime,生成Layer Tree UI樹,Layer Tree上每一個葉子節(jié)點都代表了當(dāng)前屏幕上所需要渲染的每一個元素,包含了這些元素渲染所需要的內(nèi)容。將Layer Tree拋給GPU線程,在GPU線程內(nèi)調(diào)用Skia去完成整個UI的渲染過程。Layer Tree中有PictureLayer和TextureLayer兩個比較重要的節(jié)點。PictureLayer主要負(fù)責(zé)屏幕圖片的渲染,F(xiàn)lutter內(nèi)部實現(xiàn)了一套圖片解碼邏輯,在IO線程將圖片讀取或者從網(wǎng)絡(luò)上拉取之后,通過解碼能夠在IO線程上加載出紋理,交給GPU線程將圖片渲染到屏幕上。但是由于音視頻場景下系統(tǒng)API太過繁多,業(yè)務(wù)場景過于復(fù)雜。Flutter沒有一套邏輯去實現(xiàn)跨平臺的音視頻組件,所以說Flutter提出了一種讓第三方開發(fā)者來實現(xiàn)音視頻組件的方式,而這些音視頻組件的視頻渲染出口,就是TextureLayer。
在整個Layer Tree渲染的過程中,TextureLayer的數(shù)據(jù)紋理需要由外部第三方開發(fā)者來指定,可以把視頻數(shù)據(jù)和播放器數(shù)據(jù)送到TextureLayer里,由Flutter將這些數(shù)據(jù)渲染出來。
TextureLayer渲染過程:首先判斷Layer是否已經(jīng)初始化,如果沒有就創(chuàng)建一個Texture,然后將Texture Attach到一個SufaceTexture上。
這個SufaceTexture是音視頻的native代碼可以獲取到的對象,通過這個對象創(chuàng)建的Suface,我們可以將視頻數(shù)據(jù)、攝像頭數(shù)據(jù)解碼放到Suface中,然后Flutter端通過監(jiān)聽SufaceTexture的數(shù)據(jù)更新就可以順利把剛才創(chuàng)建的數(shù)據(jù)更新到它的紋理中,然后再將紋理交給SKIA渲染到屏幕上。
然而我們?nèi)绻枰肍lutter實現(xiàn)美顏,濾鏡,人臉貼圖等等功能,就需要將視頻數(shù)據(jù)讀取出來,更新到紋理中,再將GPU紋理經(jīng)過美顏濾鏡處理后生成一個處理后的紋理。按Flutter提供的現(xiàn)有能力,必須先將紋理中的數(shù)據(jù)從GPU讀出到CPU中,生成Bitmap后再寫入Surface中,這樣在Flutter中才能順利的更新到視頻數(shù)據(jù),這樣做對系統(tǒng)性能的消耗很大。
通過對Flutter渲染過程分析,我們知道Flutter底層需要渲染的數(shù)據(jù)就是GPU紋理,而我們經(jīng)過美顏濾鏡處理完成以后的結(jié)果也是GPU紋理,如果可以將它直接交給Flutter渲染,那就可以避免GPU-CPU-GPU這樣的無用循環(huán)。這樣的方法是可行的,但是需要一個條件,就是OpenGL上下文共享。
OpenGL
在說上下文之前,得提到一個和上線文息息相關(guān)的概念:線程。
Flutter引擎啟動后會啟動四個線程:
第一個線程是UI線程,這是Flutter自己定義的UI線程,主要負(fù)責(zé)GPU發(fā)出的VSync信號時候用當(dāng)前Dart編譯的機器碼和當(dāng)前運行環(huán)境創(chuàng)建出Layer Tree。
還有就是IO線程和GPU線程。和大部分OpenGL處理解決方案中一樣,F(xiàn)lutter也采取一個線程責(zé)資源加載,一部分負(fù)責(zé)資源渲染這種思路。
兩個線程之間紋理共享有兩種方式。一種是EGLImage(IOS是 CVOpenGLESTextureCache)。一種是OpenGL Share Context。Flutter通過Share Context來實現(xiàn)紋理共享,將IO線程的Context和GPU線程的Context進行Share,放到同一個Share Group下面,這樣兩個線程下資源是互相可見可以共享的。
Platform線程是主線程,F(xiàn)lutter中有一個很奇怪的設(shè)定,GPU線程和主線程共用一個Context。并且在主線程也有很多OpenGL 操作。
這樣的設(shè)計會給音視頻開發(fā)帶來很多問題,后面會詳細(xì)說。
音視頻端美顏處理完成的OpenGL紋理能夠讓Flutter直接使用的條件就是Flutter的上下文需要和平臺音視頻相關(guān)的OpenGL上下文處在一個Share Group下面。
由于Flutter主線程的Context就是GPU的Context,所以在音視頻端主線程中有一些OpenGL操作的話,很有可能使Flutter整個OpenGL被破壞掉。所以需要將所有的OpenGL操作都限制在子線程中。
通過上述這兩個條件的處理,我們就可以在沒有增加GPU消耗的前提下實現(xiàn)美顏和濾鏡等等功能。
TPM
在經(jīng)過demo驗證之后,我們將這個方案應(yīng)用到閑魚音視頻組件中,但改造過程中發(fā)現(xiàn)了一些問題。
上圖是攝像頭采集數(shù)據(jù)轉(zhuǎn)換為紋理的一段代碼,其中有兩個操作:首先是切進程,將后面的OpenGL操作都切到cameraQueue中。然后是設(shè)置一次上下文。然后這種限制條件或者說是潛規(guī)則往往在開發(fā)過程中容易被忽略的。而這個條件一旦忽略后果就是出現(xiàn)一些莫名其妙的詭異問題極難排查。因此我們就希望能抽象出一套框架,由框架本身實現(xiàn)線程的切換、上下文和模塊生命周期等的管理,開發(fā)者接入框架以后只需要安心實現(xiàn)自己的算法,而不需要關(guān)心這些潛規(guī)則還有其他一些重復(fù)的邏輯操作。
在引入Flutter之前閑魚的音視頻架構(gòu)與大部分音視頻邏輯一樣采用分層架構(gòu):
1:底層是一些獨立模塊
2:SDK層是對底層模塊的封裝
3:最上層是UI層。
引入Flutter之后,通過分析各個模塊的使用場景,我們可以得出一個假設(shè)或者說是抽象:音視頻應(yīng)用在終端上可以歸納為視頻幀解碼之后視頻數(shù)據(jù)幀在各個模塊之間流動的過程,基于這種假設(shè)去做Flutter音視頻框架的抽象。
咸魚Flutter多媒體開源組件
整個Flutter音視頻框架抽象分為管線和數(shù)據(jù)的抽象、模塊的抽象、線程統(tǒng)一管理和上下文同一管理四部分。
管線,其實就是視頻幀流動的管道。數(shù)據(jù),音視頻中涉及到的數(shù)據(jù)包括紋理、Bit Map以及時間戳等。結(jié)合現(xiàn)有的應(yīng)用場景我們定義了管線流通數(shù)據(jù)以Texture為主數(shù)據(jù),同時可以選擇性的添加Bit Map等作為輔助數(shù)據(jù)。這樣的數(shù)據(jù)定義方式,避免重復(fù)的創(chuàng)建和銷毀紋理帶來的性能開銷以及多線程訪問紋理帶來的一些問題。也滿足一些特殊模塊對特殊數(shù)據(jù)的需求。同時也設(shè)計了紋理池來管理管線中的紋理數(shù)據(jù)。
模塊:如果把管線和數(shù)據(jù)比喻成血管和血液,那框架音視頻的場景就可以比喻成器官,我們根據(jù)模塊所在管線的位置抽象出采集、處理和輸出三個基類。這三個基類里實現(xiàn)了剛才說的線程切換,上下文切換,格式轉(zhuǎn)換等等共同邏輯,各個功能模塊通過集成自這些基類,可以避免很多重復(fù)勞動。
線程:每一個模塊初始化的時候,初始化函數(shù)就會去線程管理的模塊去獲取自己的線程,線程管理模塊可以決定給初始化函數(shù)分配新的線程或者已經(jīng)分配過其他模塊的線程。
這樣有三個好處:
一是可以根據(jù)需要去決定一個線程可以掛載多少模塊,做到線程間的負(fù)載均衡。第二,多線程并發(fā)式能夠保證模塊內(nèi)的OpenGL操作是在當(dāng)前線程內(nèi)而不會跑到主線程去,徹底避免Flutter的OpenGL 環(huán)境被破壞。第三,多線程并行可以充分利用CPU多核架構(gòu),提升處理速度。
從Flutter端修改Flutter引擎將Context取出后,根據(jù)Context創(chuàng)建上下文的統(tǒng)一管理模塊,每一個模塊在初始化的時候會獲取它的線程,獲取之后會調(diào)用上下文管理模塊獲取自己的上下文。這樣可以保證每一個模塊的上下文都是與Flutter的上下文進行Share的,每個模塊之間資源都是共享可見的,F(xiàn)lutter和音視頻native之間也是互相共享可見的。
基于上述框架如果要實現(xiàn)一個簡單的場景,比如畫面實時預(yù)覽和濾鏡處理功能,
1:需要選擇功能模塊,功能模塊包括攝像頭模塊、濾鏡處理模塊和Flutter畫面渲染模塊,
2:需要配置模塊參數(shù),比如采集分辨率、濾鏡參數(shù)和前后攝像頭設(shè)置等,
3:在創(chuàng)建視頻管線后使用已配置的參數(shù)創(chuàng)建模塊
4:最后管線搭載模塊,開啟管線就可以實現(xiàn)這樣簡單的功能。
上圖為整個功能實現(xiàn)的代碼和結(jié)構(gòu)圖。
結(jié)合上述音視頻框架,閑魚實現(xiàn)了Flutter多媒體開源組件。
組要包含四個基本組件分別是:
1:視頻圖像拍攝組件
2:播放器組件
3:視頻圖像編輯組件
4:相冊選擇組件
現(xiàn)在這些組件正在走內(nèi)部開源流程。預(yù)計9月份,相冊和播放器會實現(xiàn)開源。
后續(xù)展望和規(guī)劃
1:實現(xiàn)開頭所說的從底層SDK到UI的全鏈路的跨端開發(fā)。目前底層框架層和模塊層都是各個平臺各自實現(xiàn),反而是Flutter的UI端進行了跨平臺的統(tǒng)一,所以后續(xù)會將底層也按照音視頻常用做法把邏輯下沉到C++層,盡可能的實現(xiàn)全鏈路跨平臺。
2:第二部分內(nèi)容為開源共建,閑魚開源的內(nèi)容不僅包括拍攝、編輯組件,還包括了很多底層模塊,希望有開發(fā)者在基于Flutter開發(fā)音視頻應(yīng)用時可以充分利用閑魚開源出的音視頻模塊能力,搭建APP框架,開發(fā)者只要去負(fù)責(zé)實現(xiàn)特殊需求模塊就可以,盡可能的減少重復(fù)勞動。
本文由阿里閑魚技術(shù)團隊逸昂分享,原題“消息鏈路優(yōu)化之弱感知鏈路優(yōu)化”,有修訂和改動,感謝作者的分享。
閑魚的IM消息系統(tǒng)作為買家與賣家的溝通工具,增進理解、促進信任,對閑魚的商品成交有重要的價值,是提升用戶體驗最關(guān)鍵的環(huán)節(jié)。
然而,隨著業(yè)務(wù)體量的快速增長,當(dāng)前這套消息系統(tǒng)正面臨著諸多急待解決的問題。
以下幾個問題典型最為典型:
1) 在線消息的體驗提升;
2) 離線推送的到達率;
3) 消息玩法與消息底層系統(tǒng)的耦合過強。
經(jīng)過評估,我們認(rèn)為現(xiàn)階段離線推送的到達率問題最為關(guān)鍵,對用戶體驗影響較大。
本文將要分享的是閑魚IM消息在解決離線推送的到達率方面的技術(shù)實踐,內(nèi)容包括問題分析和技術(shù)優(yōu)化思路等 ,希望能帶給你啟發(fā)。
(本文已同步發(fā)布于: ?)
本文是系列文章的第6篇,總目錄如下:
《 阿里IM技術(shù)分享(一):企業(yè)級IM王者——釘釘在后端架構(gòu)上的過人之處 》
《 阿里IM技術(shù)分享(二):閑魚IM基于Flutter的移動端跨端改造實踐 》
《 阿里IM技術(shù)分享(三):閑魚億級IM消息系統(tǒng)的架構(gòu)演進之路 》
《 阿里IM技術(shù)分享(四):閑魚億級IM消息系統(tǒng)的可靠投遞優(yōu)化實踐 》
《 阿里IM技術(shù)分享(五):閑魚億級IM消息系統(tǒng)的及時性優(yōu)化實踐 》
《 阿里IM技術(shù)分享(六):閑魚億級IM消息系統(tǒng)的離線推送到達率優(yōu)化 》(* 本文)
從數(shù)據(jù)通信鏈接的技術(shù)角度,我們根據(jù)閑魚客戶端是否在線,將整體消息鏈路大致分為強感知鏈路和弱感知鏈路。
強感知鏈路由以下子系統(tǒng)或模塊:
1) 發(fā)送方客戶端;
2) idleapi-message(閑魚的消息網(wǎng)關(guān));
3) heracles(閑魚的消息底層服務(wù));
4) accs(阿里自研的長連接通道);
5) 接收方客戶端組成。
整條鏈路的核心指標(biāo)在于端到端延遲和消息到達率。
強感知鏈路中的雙方都是在線的,消息到達客戶端就可以保證接收方感知到。強感知鏈路的主要痛點在消息的端到端延遲。
弱感知鏈路與強感知鏈路的主要不同在于: 弱感知鏈路的接收方是離線的,需要依賴離線推送這樣的方式送達。
因此弱感知鏈路的用戶感知度不強,其核心指標(biāo)在于消息的到達率,而非延遲。
所以當(dāng)前階段,優(yōu)化弱感知鏈路的重點也就是提升離線消息的到達率。換句話說, 提升離線消息到達率問題,也就是優(yōu)化弱感知鏈路本身 。
下圖一張整個IM消息系統(tǒng)的架構(gòu)圖,感受下整體鏈路:
如上圖所示,各主要組件和子系統(tǒng)分工如下:
1) HSF是一個遠(yuǎn)程服務(wù)框架,是dubbo的內(nèi)部版本;
2) tair是阿里自研的分布式緩存框架,支持 memcached、Redis、LevelDB 等不同存儲引擎;
3) agoo是阿里的離線推送中臺,負(fù)責(zé)整合不同廠商的離線推送通道,向集團用戶提供一個統(tǒng)一的離線推送服務(wù);
4) accs是阿里自研的長連接通道,為客戶端、服務(wù)端的實時雙向交互提供便利;
5) lindorm是阿里自研的NoSQL產(chǎn)品,與HBase有異曲同工之妙;
6) 域環(huán)是閑魚消息優(yōu)化性能的核心結(jié)構(gòu),用來存儲用戶最新的若干條消息。
強感知鏈路和弱感知鏈路在通道選擇上是不同的:
1) 強感知鏈路使用accs這個在線通道;
2) 弱感知鏈路使用agoo這個離線通道。
通俗了說,弱感知鏈路指的就是離線消息推送系統(tǒng)。
相比較于在線消息和端內(nèi)推送(也就是上面說的強感知鏈路),離線推送難以確保被用戶感知到。
典型的情況包括:
1) 未發(fā)送到用戶設(shè)備:即推送未送達用戶設(shè)備,這種情況可以從通道的返回分析;
2) 發(fā)送到用戶設(shè)備但沒有展示到系統(tǒng)通知欄:閑魚曾遇到通道返回成功,但是用戶未看到推送的案例;
3) 展示到通知欄,并被系統(tǒng)折疊:不同安卓廠商對推送的折疊策略不同,被折疊后,需用戶主動展開才能看到內(nèi)容,觸達效果明顯變差;
4) 展示到通知欄,并被用戶忽略:離線推送的點擊率相比于在線推送更低。
針對“1)未發(fā)送到用戶設(shè)備”,原因有:
1) 離線通道的token失效;
2) 參數(shù)錯誤;
3) 用戶關(guān)閉應(yīng)用通知;
4) 用戶已卸載等。
針對“3)展示到通知欄,并被系統(tǒng)折疊”,原因有:
1) 通知的點擊率;
2) 應(yīng)用在廠商處的權(quán)重;
3) 推送的數(shù)量等。
針對“4)展示到通知欄,并被用戶忽略”,原因有:
1) 用戶不愿意查看推送;
2) 用戶看到了推送,但是對內(nèi)容不感興趣;
3) 用戶在忙別的事,無暇處理。
總之: 以上這些離線消息推送場景,對于用戶來說感知度不高,我們也便稱之為弱感知鏈路。
我們的弱感知鏈路分為3部分,即:
1) 系統(tǒng);
2) 通道;
3) 用戶。
共包含了Hermes、agoo、廠商、設(shè)備、用戶、承接頁這幾個環(huán)節(jié)。具體如下圖所示。
從推送的產(chǎn)生到用戶最終進入APP,共分為如下幾個步驟:
步驟1 :Hermes是閑魚的用戶觸達系統(tǒng),負(fù)責(zé)人群管理、內(nèi)容管理、時機把控,是整個弱感知鏈路的起點。;
步驟2 :agoo是阿里內(nèi)部承接離線推送的中臺,是閑魚離線推送能力的基礎(chǔ);
步驟3 :agoo實現(xiàn)離線推送依靠的是廠商的推送通道(如:蘋果的 apns通道 、Google的fcm通道、及 國內(nèi)各廠商的自建通道 。;
步驟4 :通過廠商的通道,推送最終出現(xiàn)在用戶的設(shè)備上,這是用戶能感知到推送的前提條件;
步驟5 :如果用戶剛巧看到這條推送,推送的內(nèi)容也很有趣,在用戶的主動點擊下會喚起APP,打開承接頁,進而給用戶展示個性化的商品。
經(jīng)過以上5個步驟,至此弱感知鏈路就完成了使命。
弱感知鏈路的核心問題在于:
1) 推送的消息是否投遞給了用戶;
2) 已投遞到的消息用戶是否有感知。
這對應(yīng)推送的兩個階段:
1) 推送消息是否已到達設(shè)備;
2) 用戶是否查看推送并點擊。
其中: 到達設(shè)備這個階段是最基礎(chǔ)的,也是本次優(yōu)化的核心。
我們可以將每一步的消息處理量依次平鋪,展開為一張漏斗圖,從而直觀的查看鏈路的瓶頸。
漏斗圖斜率最大的地方是優(yōu)化的重點,差異小的地方不需要優(yōu)化:
通過分析以上漏斗圖,弱感知鏈路的優(yōu)化重點在三個方面:
1) agoo受理率:是指我們發(fā)送推送請到的數(shù)量到可以通過agoo(阿里承接離線推送的中臺)轉(zhuǎn)發(fā)到廠商通道的數(shù)量之間的漏斗;
2) 廠商受理率:是指agoo中臺受理的量到廠商返回成功的量之間的漏斗;
3) Push點擊率:也就通過以上通道最終已送到到用戶終端的消息,是否最終轉(zhuǎn)化為用戶的主動“點擊”。
有了優(yōu)化方向,我們來看看優(yōu)化手段吧。
跟隨推送的視角,順著鏈路看一下我們是如何進行優(yōu)化的。
用戶的推送,從 Hermes 站點搭乘“班車”,駛向下一站:? agoo 。
這是推送經(jīng)歷的第一站。到站一看,傻眼了,只有不到一半的推送到站下車了。這是咋回事嘞?
這就要先說說 agoo 了,調(diào)用 agoo 有兩種方式:
1) 指定設(shè)備和客戶端,agoo直接將推送投遞到相應(yīng)的設(shè)備;
2) 指定用戶和客戶端,agoo根據(jù)內(nèi)部的轉(zhuǎn)換表,找到用戶對應(yīng)的設(shè)備,再進行投遞。
我們的系統(tǒng)不保存用戶的設(shè)備信息。因此,是按照用戶來調(diào)用agoo的。
同時: 由于沒有用戶的設(shè)備信息,并不知道用戶是 iOS 客戶端還是 Android 客戶端。工程側(cè)不得不向 iOS 和 Android 都發(fā)送一遍推送。雖然保證了到達,但是,一半的調(diào)用都是無效的。
為了解這個問題: 我們使用了agoo的設(shè)備信息。將用戶轉(zhuǎn)換設(shè)備這一階段提前到了調(diào)用 agoo 之前,先明確用戶對應(yīng)的設(shè)備,再指定設(shè)備調(diào)用 agoo,從而避免無效調(diào)用。
agoo調(diào)用方式優(yōu)化后,立刻剔除了無效調(diào)用,agoo受理率有了明顯提升。
至此: 我們總算能對 agoo 受理失敗的真正原因做一個高大上的分析了。
根據(jù)統(tǒng)計: 推送被 agoo 拒絕的主要原因是——用戶關(guān)閉了通知權(quán)限。同時,我們對 agoo 調(diào)用數(shù)據(jù)的進一步分析發(fā)現(xiàn)——有部分用戶找不到對應(yīng)的設(shè)備。 優(yōu)化到此,我們猛然發(fā)現(xiàn)多了兩個問題。
那就繼續(xù)優(yōu)化唄:
1) 通知體驗優(yōu)化,引導(dǎo)打開通知權(quán)限;
2) 與agoo共建設(shè)備庫,解決設(shè)備轉(zhuǎn)換失敗的問題。
這兩個優(yōu)化方向又是一片新天地,我們擇日再聊。
推送到達 agoo ,分機型搭乘廠商“專列”,駛向下一站:用戶設(shè)備。
這是推送經(jīng)歷的第二站。出站查票,發(fā)現(xiàn)竟然超員了。
于是乎: 我們每天有大量推送因為超過廠商設(shè)定的限額被攔截。
為什么會這樣呢?
實際上: 提供推送通道的廠商(沒錯, 各手機廠商的自家推送通道良莠不齊 ),為了保證用戶體驗,會對每個應(yīng)用能夠推送的消息總量進行限制。
對于廠商而言,這個限制會根據(jù)推送的類型和應(yīng)用的用戶規(guī)模設(shè)定——推送主要分為產(chǎn)品類的推送和營銷類的推送。
廠商推送通道對于不同類型消息的限制是:
1) 對于產(chǎn)品類推送,廠商會保證到達;
2) 對于營銷類推送,廠商會進行額度限制;
3) 未標(biāo)記的推送,默認(rèn)作為營銷類推送對待。
我們剛好沒有對推送進行標(biāo)記,因此觸發(fā)了廠商的推送限制。
這對我們的用戶來說,會帶來困擾。閑魚的交易,很依賴買賣家之間的消息互動。這部分消息是需要確保到達的。
同樣: 訂單類的消息、用戶的關(guān)注,也需要保證推送給用戶。
根據(jù)主流廠商的接口協(xié)議,我們將推送的消息分為以下幾類,并進行相應(yīng)標(biāo)記:
1) 即時通訊消息;
2) 訂單狀態(tài)變化;
3) 用戶關(guān)注內(nèi)容;
4) 營銷消息這幾類。
同時,在業(yè)務(wù)上,我們也進行了推送的治理——將用戶關(guān)注度不高的消息,取消推送,避免打擾。
經(jīng)過這些優(yōu)化,因為超過廠商限額而被攔截的推送實現(xiàn)了清零。
通過優(yōu)化agoo受理率、廠商受理率,我們解決了推送到達量的瓶頸。但即使消息被最終送達,用戶到底點擊了沒有?這才是消息推送的根本意義所在。
于是,在日常的開發(fā)測試過程中,我們發(fā)現(xiàn)了推送的兩個體驗問題:
1) 用戶點擊Push有開屏廣告;
2) 營銷Push也有權(quán)限校驗,更換用戶登陸后無法點擊。
對于開屏廣告功能,我們增加了Push點擊跳過廣告的能力。
針對Push的權(quán)限校驗功能,閑魚根據(jù)場景做了細(xì)分:
1) 涉及個人隱私的推送,保持權(quán)限校驗不變;
2) 營銷類的推送,放開權(quán)限校驗。
以上是點擊體驗的優(yōu)化,我們還需要考慮用戶的點擊意愿。
用戶點擊量與推送的曝光量、推送素材的有趣程度相關(guān)。推送的曝光量又和推送的到達量、推送的到達時機有關(guān)。
具體的優(yōu)化手段是:
1) 在推送內(nèi)容上:我們需要優(yōu)化的是推送的時機和相應(yīng)的素材;
2) 在推送時機上:算法會根據(jù)用戶的偏好和個性化行為數(shù)據(jù),計算每個用戶的個性化推送時間,在用戶空閑的時間推送(避免在不合適的時間打擾用戶,同時也能提升用戶看到推送的可能性)。
3) 在推送素材上:算法會根據(jù)素材的實時點擊反饋,對素材做實時賽馬。只發(fā)用戶感興趣的素材,提高用戶點擊意愿。
通過以上我們的分析和技術(shù)優(yōu)化手段,整體弱推送鏈路鏈路有了不錯的提升,離線消息的到達率相對提升了兩位數(shù)。
本篇主要和大家聊的是只是IM消息系統(tǒng)鏈路中的一環(huán)——弱感知鏈路的優(yōu)化,落地到到具體的業(yè)務(wù)也就是離線消息送達率問題。
整體IM消息系統(tǒng),還是一個比較復(fù)雜的領(lǐng)域。
我們在消息系統(tǒng)的發(fā)展過程中,面臨著如下問題:
1) 如何進行消息的鏈路追蹤;
2) 如何保證IM消息的快速到達(見《 閑魚億級IM消息系統(tǒng)的及時性優(yōu)化實踐 》);
3) 如何將消息的玩法和底層能力分離;
4) 離線推送中如何通過用戶找到對應(yīng)的設(shè)備。
這些問題,我們在以前的文章中有所分享,以后也會陸續(xù)分享更多,敬請期待。
[1]? Android P正式版即將到來:后臺應(yīng)用保活、消息推送的真正噩夢
[2]? 一套高可用、易伸縮、高并發(fā)的IM群聊、單聊架構(gòu)方案設(shè)計實踐
[3]? 一套億級用戶的IM架構(gòu)技術(shù)干貨(上篇):整體架構(gòu)、服務(wù)拆分等
[4]? 一套億級用戶的IM架構(gòu)技術(shù)干貨(下篇):可靠性、有序性、弱網(wǎng)優(yōu)化等
[5]? 從新手到專家:如何設(shè)計一套億級消息量的分布式IM系統(tǒng)
[6]? 企業(yè)微信的IM架構(gòu)設(shè)計揭秘:消息模型、萬人群、已讀回執(zhí)、消息撤回等
[7]? 融云技術(shù)分享:全面揭秘億級IM消息的可靠投遞機制
[8]? 移動端IM中大規(guī)模群消息的推送如何保證效率、實時性?
[9]? 現(xiàn)代IM系統(tǒng)中聊天消息的同步和存儲方案探討
[10]? 新手入門一篇就夠:從零開發(fā)移動端IM
[11]? 移動端IM開發(fā)者必讀(一):通俗易懂,理解移動網(wǎng)絡(luò)的“弱”和“慢”
[12]? 移動端IM開發(fā)者必讀(二):史上最全移動弱網(wǎng)絡(luò)優(yōu)化方法總結(jié)
[13]? IM消息送達保證機制實現(xiàn)(一):保證在線實時消息的可靠投遞
[14]? IM消息送達保證機制實現(xiàn)(二):保證離線消息的可靠投遞
[15]? 零基礎(chǔ)IM開發(fā)入門(一):什么是IM系統(tǒng)?
[16]? 零基礎(chǔ)IM開發(fā)入門(二):什么是IM系統(tǒng)的實時性?
[17]? 零基礎(chǔ)IM開發(fā)入門(三):什么是IM系統(tǒng)的可靠性?
[18]? 零基礎(chǔ)IM開發(fā)入門(四):什么是IM系統(tǒng)的消息時序一致性?
(本文已同步發(fā)布于: ?)
分享名稱:咸魚放棄flutter,咸魚放棄fluttergo
標(biāo)題路徑:http://www.chinadenli.net/article28/dsdipjp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動態(tài)網(wǎng)站、網(wǎng)站收錄、搜索引擎優(yōu)化、外貿(mào)建站、網(wǎng)站建設(shè)、全網(wǎng)營銷推廣
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)