真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

flutter閑魚(yú),閑魚(yú)放棄fluttergo

閑魚(yú)前端基于serverless的一種多端開(kāi)發(fā)解決方案

前端的發(fā)展太快了,前端框架和技術(shù)的發(fā)展也層出不窮,還包括不同智能設(shè)備的出現(xiàn),對(duì)前端開(kāi)發(fā)同學(xué)來(lái)說(shuō)是個(gè)很大的跳轉(zhuǎn),簡(jiǎn)單列舉下:

成都網(wǎng)絡(luò)公司-成都網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)建站10多年經(jīng)驗(yàn)成就非凡,專業(yè)從事成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè),成都網(wǎng)頁(yè)設(shè)計(jì),成都網(wǎng)頁(yè)制作,軟文發(fā)布平臺(tái)1元廣告等。10多年來(lái)已成功提供全面的成都網(wǎng)站建設(shè)方案,打造行業(yè)特色的成都網(wǎng)站建設(shè)案例,建站熱線:028-86922220,我們期待您的來(lái)電!

這樣就滋生了一些問(wèn)題,比如我要開(kāi)發(fā)一個(gè)通用的頁(yè)面,兼容不同的端側(cè)和 小程序 ,顯然目前是做不到的,我們只能開(kāi)發(fā)多套頁(yè)面去適配不同的場(chǎng)景,這樣的話成本就太高了。

很多同學(xué)都在嘗試解決這個(gè)問(wèn)題,也催生了類似taro這樣的多端統(tǒng)一開(kāi)發(fā)框架,這是一個(gè)好的解決方案,但是比較被動(dòng),缺乏一定的擴(kuò)展性。

這篇文章我們要探討的是,看能不能換個(gè)角度去解決這個(gè)問(wèn)題,提升開(kāi)發(fā)效率。

ViewModel

當(dāng)我們?cè)陂_(kāi)發(fā)一個(gè)頁(yè)面的時(shí)候,不管用的是哪一種框架,通常都會(huì)抽象出一層viewmodel層,它主要有2個(gè)作用

從上圖中我們可以看出,viewmodel是一段獨(dú)立的通用代碼邏輯,起到了承前啟后的作用。它和view層關(guān)系更加緊密,因此通常會(huì)放在前端測(cè)。

既然viewmodel是獨(dú)立的,那我們能不能把它放在后端呢?這樣一個(gè)最大的好處就是viewmodel可以進(jìn)行復(fù)用,不需要在重復(fù)編寫(xiě),而且只需要改動(dòng)一個(gè)viewmodel,就可以全量生效。

似乎是一個(gè)很美好的想法,但是這部分代碼由誰(shuí)去開(kāi)發(fā)呢,總不可能寄希望于后端同學(xué)吧,當(dāng)然只能是我們自己,也感謝于serverless架構(gòu)的出現(xiàn),讓這件事情變成了可能。

有些同學(xué)可能會(huì)問(wèn),既然viewmodel后移了,那view呢?后續(xù)會(huì)考慮結(jié)合我們的ui2code技術(shù),那真的就比較完美了。

什么是serverless

架構(gòu)上,我們可以把serverless分為FaaS和BaaS。

FaaS是用于創(chuàng)建、運(yùn)行、管理函數(shù)服務(wù)的計(jì)算平臺(tái),它支持多種開(kāi)發(fā)語(yǔ)言,比如java、nodejs、dart等,這有利于不同端側(cè)的開(kāi)發(fā)同學(xué)介入開(kāi)發(fā)。FaaS是基于事件驅(qū)動(dòng)的思想,只有當(dāng)一個(gè)函數(shù)被事件觸發(fā)時(shí)才會(huì)占用服務(wù)器資源執(zhí)行,不然都是無(wú)需占用服務(wù)器資源的。

BaaS提供了用于函數(shù)調(diào)用的第三方基礎(chǔ)服務(wù),比如身份校驗(yàn)、日志、數(shù)據(jù)庫(kù)等,它是由服務(wù)商直接提供,開(kāi)發(fā)者無(wú)需關(guān)系實(shí)現(xiàn),直接調(diào)用即可。

業(yè)務(wù)落地

我們是通過(guò)gaia平臺(tái)開(kāi)發(fā)后端接口,gaia可以理解為上文提到的FaaS平臺(tái)。

日常開(kāi)發(fā)中有這樣一個(gè)需求,下面是這個(gè)需求的一個(gè)頁(yè)面。

因?yàn)檫@個(gè)頁(yè)面上的數(shù)據(jù)比較多,先把它切分成一個(gè)個(gè)小的模塊,后臺(tái)返回?cái)?shù)據(jù)的時(shí)候也根據(jù)模塊來(lái)返回?cái)?shù)據(jù)。

我們是根據(jù)viewmodel來(lái)設(shè)計(jì)接口,首先肯定有一個(gè)首屏數(shù)據(jù)接口;然后是頁(yè)面上的交互,比如切換卡片、切換芝麻信用按鈕,切換會(huì)引起頁(yè)面數(shù)據(jù)變化,我們可以統(tǒng)一封裝一個(gè)頁(yè)面更新的接口;最后是一個(gè)開(kāi)通的接口。

后端接口

前后端交互最重要的數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì),我們省略了中間的業(yè)務(wù)邏輯處理,看下接口的數(shù)據(jù)結(jié)構(gòu)。

首屏接口返回的數(shù)據(jù)主要有幾個(gè)特征:

更新接口的返回?cái)?shù)據(jù)結(jié)構(gòu)和首屏接口類似,但是入?yún)⒂兴煌?,主要包?個(gè)字段:

前端處理

從后端返回的數(shù)據(jù)可以看到,數(shù)據(jù)是及其詳細(xì)的,無(wú)需我們做任何的業(yè)務(wù)邏輯處理,直接映射到頁(yè)面即可。這樣,前端已經(jīng)變成了很薄的一層數(shù)據(jù),沒(méi)有任務(wù)的業(yè)務(wù)邏輯處理,變的很簡(jiǎn)單,當(dāng)需要遷移到其他端時(shí),只需要遷移視圖層即可。當(dāng)有任何的業(yè)務(wù)變動(dòng)時(shí),只需要修改后端的接口,就能生效。

收益與總結(jié)

通過(guò)具體的實(shí)踐,我們發(fā)現(xiàn),對(duì)于前端開(kāi)發(fā)同學(xué)來(lái)說(shuō),變的簡(jiǎn)單了,開(kāi)發(fā)效率有很大的提升,前端同學(xué)甚至都不需要去理解具體的業(yè)務(wù)邏輯,就能完成頁(yè)面的開(kāi)發(fā)。而且,提取的viewmodel可以復(fù)用到不同的端側(cè),設(shè)置還包括native端。我們還可以將viewmodel拆分成更小粒度的viewmodel,方便在不同的頁(yè)面接口中進(jìn)行復(fù)用。我們有同學(xué)還在FaaS側(cè)基于redux的思想封裝了一個(gè)通用的狀態(tài)管理框架,規(guī)范了前后端的交互。

后面, 還有一些問(wèn)題待我們?nèi)ソ鉀Q,比如開(kāi)發(fā)成本、viewmodel的邏輯拆分、具體接口問(wèn)題定位等。

閑魚(yú)團(tuán)隊(duì)是Flutter+Dart FaaS前后端一體化新技術(shù)的行業(yè)領(lǐng)軍者,就是現(xiàn)在! 客戶端/服務(wù)端java/架構(gòu)/前端/質(zhì)量工程師 面向 社會(huì) 招聘,base杭州阿里巴巴西溪園區(qū),一起做有創(chuàng)想空間的社區(qū)產(chǎn)品、做深度頂級(jí)的開(kāi)源項(xiàng)目,一起拓展技術(shù)邊界成就極致!

*投喂簡(jiǎn)歷給小閑魚(yú)→ guicai.gxy@alibaba-inc .com

開(kāi)源項(xiàng)目、峰會(huì)直擊、關(guān)鍵洞察、深度解讀

請(qǐng)認(rèn)準(zhǔn) 閑魚(yú)技術(shù)

Flutter浪潮下的音視頻研發(fā)探索

文/陳爐軍

整理/LiveVideoStack

大家好,我是阿里巴巴閑魚(yú)事業(yè)部的陳爐軍,本次分享的主題是Flutter浪潮下的音視頻研發(fā)探索,主要內(nèi)容是針對(duì)閑魚(yú)APP在當(dāng)下流行的跨平臺(tái)框架Flutter的大規(guī)模實(shí)踐,介紹其在音視頻領(lǐng)域碰到的一些困難以及解決方案。

分享內(nèi)容主要分為四個(gè)方面,首先會(huì)對(duì)Flutter有一個(gè)簡(jiǎn)單介紹以及選擇Flutter作為跨平臺(tái)框架的原因,其次會(huì)介紹Flutter中與音視頻關(guān)系非常大的外接紋理概念,以及對(duì)它做出的一些優(yōu)化。之后會(huì)對(duì)閑魚(yú)在音視頻實(shí)踐過(guò)程中碰到的一些Flutter問(wèn)題提出了一些解決方案——TPM音視頻框架。最后是閑魚(yú)Flutter多媒體開(kāi)源組件的介紹。

Flutter

Flutter是一個(gè)跨平臺(tái)框架,以往的做法是將音頻、視頻和網(wǎng)絡(luò)這些模塊都下沉到C++層或者ARM層,在其上封裝成一個(gè)音視頻的SDK,供UI層的PC、iOS和Android調(diào)用。

而Flutter做為一個(gè)UI層的跨平臺(tái)框架,顧名思義就是在UI層也實(shí)現(xiàn)了一個(gè)跨平臺(tái)開(kāi)發(fā)??梢灶A(yù)想的是未Flutter發(fā)展的好的話,會(huì)逐漸變?yōu)橐粋€(gè)從底層到UI層的一個(gè)全鏈路的跨平臺(tái)開(kāi)發(fā),技術(shù)人員分別負(fù)責(zé)SDK和UI層的開(kāi)發(fā)。

在Flutter之前已經(jīng)有很多跨平臺(tái)UI解決方案,那為什么選擇Flutter呢?

我們主要考慮性能和跨平臺(tái)的能力。

以往的跨平臺(tái)方案比如Weex,ReactNative,Cordova等等因?yàn)榧軜?gòu)的原因無(wú)法滿足性能要求,尤其是在音視頻這種性能要求幾乎苛刻的場(chǎng)景。

而諸如Xamarin等,雖然性能可以和原生App一致,但是大部分邏輯還是需要分平臺(tái)實(shí)現(xiàn)。

我們可以看一下,為什么Flutter可以實(shí)現(xiàn)高性能:

原生的native組件渲染以IOS為例,蘋(píng)果的UIKit通過(guò)調(diào)用平臺(tái)自己的繪制框架QuaztCore來(lái)實(shí)現(xiàn)UI的繪制,圖形繪制也是調(diào)用底層的API,比如OpenGL、Metal等。

而Flutter也是和原生API邏輯一致,也是通過(guò)調(diào)用底層的繪制框架層SKIA實(shí)現(xiàn)UI層。這樣相當(dāng)于Flutter他自己實(shí)現(xiàn)了一套UI框架,提供了一種性能超越原生API的跨平臺(tái)可能性。

但是我們說(shuō)一個(gè)框架最終性能怎樣,其實(shí)取決于設(shè)計(jì)者和開(kāi)發(fā)者。至于現(xiàn)在到底是一個(gè)什么狀況:

在閑魚(yú)的實(shí)踐中,我們發(fā)現(xiàn)在正常的開(kāi)發(fā)沒(méi)有特意的去優(yōu)化UI代碼的情況下,在一些低端機(jī)上,F(xiàn)lutter界面的流暢性是比Native界面要好的。

雖然現(xiàn)在閑魚(yú)某些場(chǎng)景下會(huì)有卡頓閃退等情況,但是這是一個(gè)新事物發(fā)展過(guò)程中的必然問(wèn)題,我們相信未來(lái)性能肯定不會(huì)成為限制Flutter發(fā)展的瓶頸的。

在閑魚(yú)實(shí)踐Flutter的過(guò)程中,混合棧和音視頻是其中比較難解決的兩個(gè)問(wèn)題,混合棧是指一個(gè)APP在Flutter過(guò)程中不可能一口氣將所有業(yè)務(wù)全部重寫(xiě)為Flutter,所以這是一個(gè)逐步迭代的過(guò)程,這期間原生native界面與Flutter界面共存的狀態(tài)就稱之為混合棧。閑魚(yú)在混合棧上也有一些比較好的輸出,例如FlutterBoost。

外接紋理

在講音視頻之前需要簡(jiǎn)要介紹一下外接紋理的概念,我們將它稱之為是Flutter和Frame之間的橋梁。

Flutter渲染一幀屏幕數(shù)據(jù)首先要做的是,GPU發(fā)出的VC信號(hào)在Flutter的UI線程,通過(guò)AOT編譯的機(jī)器碼結(jié)合當(dāng)前Dart Runtime,生成Layer Tree UI樹(shù),Layer Tree上每一個(gè)葉子節(jié)點(diǎn)都代表了當(dāng)前屏幕上所需要渲染的每一個(gè)元素,包含了這些元素渲染所需要的內(nèi)容。將Layer Tree拋給GPU線程,在GPU線程內(nèi)調(diào)用Skia去完成整個(gè)UI的渲染過(guò)程。Layer Tree中有PictureLayer和TextureLayer兩個(gè)比較重要的節(jié)點(diǎn)。PictureLayer主要負(fù)責(zé)屏幕圖片的渲染,F(xiàn)lutter內(nèi)部實(shí)現(xiàn)了一套圖片解碼邏輯,在IO線程將圖片讀取或者從網(wǎng)絡(luò)上拉取之后,通過(guò)解碼能夠在IO線程上加載出紋理,交給GPU線程將圖片渲染到屏幕上。但是由于音視頻場(chǎng)景下系統(tǒng)API太過(guò)繁多,業(yè)務(wù)場(chǎng)景過(guò)于復(fù)雜。Flutter沒(méi)有一套邏輯去實(shí)現(xiàn)跨平臺(tái)的音視頻組件,所以說(shuō)Flutter提出了一種讓第三方開(kāi)發(fā)者來(lái)實(shí)現(xiàn)音視頻組件的方式,而這些音視頻組件的視頻渲染出口,就是TextureLayer。

在整個(gè)Layer Tree渲染的過(guò)程中,TextureLayer的數(shù)據(jù)紋理需要由外部第三方開(kāi)發(fā)者來(lái)指定,可以把視頻數(shù)據(jù)和播放器數(shù)據(jù)送到TextureLayer里,由Flutter將這些數(shù)據(jù)渲染出來(lái)。

TextureLayer渲染過(guò)程:首先判斷Layer是否已經(jīng)初始化,如果沒(méi)有就創(chuàng)建一個(gè)Texture,然后將Texture Attach到一個(gè)SufaceTexture上。

這個(gè)SufaceTexture是音視頻的native代碼可以獲取到的對(duì)象,通過(guò)這個(gè)對(duì)象創(chuàng)建的Suface,我們可以將視頻數(shù)據(jù)、攝像頭數(shù)據(jù)解碼放到Suface中,然后Flutter端通過(guò)監(jiān)聽(tīng)SufaceTexture的數(shù)據(jù)更新就可以順利把剛才創(chuàng)建的數(shù)據(jù)更新到它的紋理中,然后再將紋理交給SKIA渲染到屏幕上。

然而我們?nèi)绻枰肍lutter實(shí)現(xiàn)美顏,濾鏡,人臉貼圖等等功能,就需要將視頻數(shù)據(jù)讀取出來(lái),更新到紋理中,再將GPU紋理經(jīng)過(guò)美顏濾鏡處理后生成一個(gè)處理后的紋理。按Flutter提供的現(xiàn)有能力,必須先將紋理中的數(shù)據(jù)從GPU讀出到CPU中,生成Bitmap后再寫(xiě)入Surface中,這樣在Flutter中才能順利的更新到視頻數(shù)據(jù),這樣做對(duì)系統(tǒng)性能的消耗很大。

通過(guò)對(duì)Flutter渲染過(guò)程分析,我們知道Flutter底層需要渲染的數(shù)據(jù)就是GPU紋理,而我們經(jīng)過(guò)美顏濾鏡處理完成以后的結(jié)果也是GPU紋理,如果可以將它直接交給Flutter渲染,那就可以避免GPU-CPU-GPU這樣的無(wú)用循環(huán)。這樣的方法是可行的,但是需要一個(gè)條件,就是OpenGL上下文共享。

OpenGL

在說(shuō)上下文之前,得提到一個(gè)和上線文息息相關(guān)的概念:線程。

Flutter引擎啟動(dòng)后會(huì)啟動(dòng)四個(gè)線程:

第一個(gè)線程是UI線程,這是Flutter自己定義的UI線程,主要負(fù)責(zé)GPU發(fā)出的VSync信號(hào)時(shí)候用當(dāng)前Dart編譯的機(jī)器碼和當(dāng)前運(yùn)行環(huán)境創(chuàng)建出Layer Tree。

還有就是IO線程和GPU線程。和大部分OpenGL處理解決方案中一樣,F(xiàn)lutter也采取一個(gè)線程責(zé)資源加載,一部分負(fù)責(zé)資源渲染這種思路。

兩個(gè)線程之間紋理共享有兩種方式。一種是EGLImage(IOS是 CVOpenGLESTextureCache)。一種是OpenGL Share Context。Flutter通過(guò)Share Context來(lái)實(shí)現(xiàn)紋理共享,將IO線程的Context和GPU線程的Context進(jìn)行Share,放到同一個(gè)Share Group下面,這樣兩個(gè)線程下資源是互相可見(jiàn)可以共享的。

Platform線程是主線程,F(xiàn)lutter中有一個(gè)很奇怪的設(shè)定,GPU線程和主線程共用一個(gè)Context。并且在主線程也有很多OpenGL 操作。

這樣的設(shè)計(jì)會(huì)給音視頻開(kāi)發(fā)帶來(lái)很多問(wèn)題,后面會(huì)詳細(xì)說(shuō)。

音視頻端美顏處理完成的OpenGL紋理能夠讓Flutter直接使用的條件就是Flutter的上下文需要和平臺(tái)音視頻相關(guān)的OpenGL上下文處在一個(gè)Share Group下面。

由于Flutter主線程的Context就是GPU的Context,所以在音視頻端主線程中有一些OpenGL操作的話,很有可能使Flutter整個(gè)OpenGL被破壞掉。所以需要將所有的OpenGL操作都限制在子線程中。

通過(guò)上述這兩個(gè)條件的處理,我們就可以在沒(méi)有增加GPU消耗的前提下實(shí)現(xiàn)美顏和濾鏡等等功能。

TPM

在經(jīng)過(guò)demo驗(yàn)證之后,我們將這個(gè)方案應(yīng)用到閑魚(yú)音視頻組件中,但改造過(guò)程中發(fā)現(xiàn)了一些問(wèn)題。

上圖是攝像頭采集數(shù)據(jù)轉(zhuǎn)換為紋理的一段代碼,其中有兩個(gè)操作:首先是切進(jìn)程,將后面的OpenGL操作都切到cameraQueue中。然后是設(shè)置一次上下文。然后這種限制條件或者說(shuō)是潛規(guī)則往往在開(kāi)發(fā)過(guò)程中容易被忽略的。而這個(gè)條件一旦忽略后果就是出現(xiàn)一些莫名其妙的詭異問(wèn)題極難排查。因此我們就希望能抽象出一套框架,由框架本身實(shí)現(xiàn)線程的切換、上下文和模塊生命周期等的管理,開(kāi)發(fā)者接入框架以后只需要安心實(shí)現(xiàn)自己的算法,而不需要關(guān)心這些潛規(guī)則還有其他一些重復(fù)的邏輯操作。

在引入Flutter之前閑魚(yú)的音視頻架構(gòu)與大部分音視頻邏輯一樣采用分層架構(gòu):

1:底層是一些獨(dú)立模塊

2:SDK層是對(duì)底層模塊的封裝

3:最上層是UI層。

引入Flutter之后,通過(guò)分析各個(gè)模塊的使用場(chǎng)景,我們可以得出一個(gè)假設(shè)或者說(shuō)是抽象:音視頻應(yīng)用在終端上可以歸納為視頻幀解碼之后視頻數(shù)據(jù)幀在各個(gè)模塊之間流動(dòng)的過(guò)程,基于這種假設(shè)去做Flutter音視頻框架的抽象。

咸魚(yú)Flutter多媒體開(kāi)源組件

整個(gè)Flutter音視頻框架抽象分為管線和數(shù)據(jù)的抽象、模塊的抽象、線程統(tǒng)一管理和上下文同一管理四部分。

管線,其實(shí)就是視頻幀流動(dòng)的管道。數(shù)據(jù),音視頻中涉及到的數(shù)據(jù)包括紋理、Bit Map以及時(shí)間戳等。結(jié)合現(xiàn)有的應(yīng)用場(chǎng)景我們定義了管線流通數(shù)據(jù)以Texture為主數(shù)據(jù),同時(shí)可以選擇性的添加Bit Map等作為輔助數(shù)據(jù)。這樣的數(shù)據(jù)定義方式,避免重復(fù)的創(chuàng)建和銷毀紋理帶來(lái)的性能開(kāi)銷以及多線程訪問(wèn)紋理帶來(lái)的一些問(wèn)題。也滿足一些特殊模塊對(duì)特殊數(shù)據(jù)的需求。同時(shí)也設(shè)計(jì)了紋理池來(lái)管理管線中的紋理數(shù)據(jù)。

模塊:如果把管線和數(shù)據(jù)比喻成血管和血液,那框架音視頻的場(chǎng)景就可以比喻成器官,我們根據(jù)模塊所在管線的位置抽象出采集、處理和輸出三個(gè)基類。這三個(gè)基類里實(shí)現(xiàn)了剛才說(shuō)的線程切換,上下文切換,格式轉(zhuǎn)換等等共同邏輯,各個(gè)功能模塊通過(guò)集成自這些基類,可以避免很多重復(fù)勞動(dòng)。

線程:每一個(gè)模塊初始化的時(shí)候,初始化函數(shù)就會(huì)去線程管理的模塊去獲取自己的線程,線程管理模塊可以決定給初始化函數(shù)分配新的線程或者已經(jīng)分配過(guò)其他模塊的線程。

這樣有三個(gè)好處:

一是可以根據(jù)需要去決定一個(gè)線程可以掛載多少模塊,做到線程間的負(fù)載均衡。第二,多線程并發(fā)式能夠保證模塊內(nèi)的OpenGL操作是在當(dāng)前線程內(nèi)而不會(huì)跑到主線程去,徹底避免Flutter的OpenGL 環(huán)境被破壞。第三,多線程并行可以充分利用CPU多核架構(gòu),提升處理速度。

從Flutter端修改Flutter引擎將Context取出后,根據(jù)Context創(chuàng)建上下文的統(tǒng)一管理模塊,每一個(gè)模塊在初始化的時(shí)候會(huì)獲取它的線程,獲取之后會(huì)調(diào)用上下文管理模塊獲取自己的上下文。這樣可以保證每一個(gè)模塊的上下文都是與Flutter的上下文進(jìn)行Share的,每個(gè)模塊之間資源都是共享可見(jiàn)的,F(xiàn)lutter和音視頻native之間也是互相共享可見(jiàn)的。

基于上述框架如果要實(shí)現(xiàn)一個(gè)簡(jiǎn)單的場(chǎng)景,比如畫(huà)面實(shí)時(shí)預(yù)覽和濾鏡處理功能,

1:需要選擇功能模塊,功能模塊包括攝像頭模塊、濾鏡處理模塊和Flutter畫(huà)面渲染模塊,

2:需要配置模塊參數(shù),比如采集分辨率、濾鏡參數(shù)和前后攝像頭設(shè)置等,

3:在創(chuàng)建視頻管線后使用已配置的參數(shù)創(chuàng)建模塊

4:最后管線搭載模塊,開(kāi)啟管線就可以實(shí)現(xiàn)這樣簡(jiǎn)單的功能。

上圖為整個(gè)功能實(shí)現(xiàn)的代碼和結(jié)構(gòu)圖。

結(jié)合上述音視頻框架,閑魚(yú)實(shí)現(xiàn)了Flutter多媒體開(kāi)源組件。

組要包含四個(gè)基本組件分別是:

1:視頻圖像拍攝組件

2:播放器組件

3:視頻圖像編輯組件

4:相冊(cè)選擇組件

現(xiàn)在這些組件正在走內(nèi)部開(kāi)源流程。預(yù)計(jì)9月份,相冊(cè)和播放器會(huì)實(shí)現(xiàn)開(kāi)源。

后續(xù)展望和規(guī)劃

1:實(shí)現(xiàn)開(kāi)頭所說(shuō)的從底層SDK到UI的全鏈路的跨端開(kāi)發(fā)。目前底層框架層和模塊層都是各個(gè)平臺(tái)各自實(shí)現(xiàn),反而是Flutter的UI端進(jìn)行了跨平臺(tái)的統(tǒng)一,所以后續(xù)會(huì)將底層也按照音視頻常用做法把邏輯下沉到C++層,盡可能的實(shí)現(xiàn)全鏈路跨平臺(tái)。

2:第二部分內(nèi)容為開(kāi)源共建,閑魚(yú)開(kāi)源的內(nèi)容不僅包括拍攝、編輯組件,還包括了很多底層模塊,希望有開(kāi)發(fā)者在基于Flutter開(kāi)發(fā)音視頻應(yīng)用時(shí)可以充分利用閑魚(yú)開(kāi)源出的音視頻模塊能力,搭建APP框架,開(kāi)發(fā)者只要去負(fù)責(zé)實(shí)現(xiàn)特殊需求模塊就可以,盡可能的減少重復(fù)勞動(dòng)。

Archsummit 2019重磅分享|閑魚(yú)Flutter&FaaS云端一體化架構(gòu)

作者:閑魚(yú)技術(shù)-國(guó)有

國(guó)有,閑魚(yú)架構(gòu)團(tuán)隊(duì)負(fù)責(zé)人。在7月13號(hào)落幕的2019年Archsummit峰會(huì)上就近一年來(lái)閑魚(yú)在FlutterFaaS一體化項(xiàng)目上的 探索 和實(shí)踐進(jìn)行了分享。

隨著無(wú)線,IoT的發(fā)展,5G的到來(lái),移動(dòng)研發(fā)越發(fā)向多端化發(fā)展。傳統(tǒng)的基于Native+Web+服務(wù)端的開(kāi)發(fā)方式,研發(fā)效率低下,顯然已經(jīng)無(wú)法適應(yīng)發(fā)展需要。

我們希望 探索 閑魚(yú)這樣規(guī)模的獨(dú)立APP的高效研發(fā)架構(gòu)。主要思路是圍繞Flutter解決多端問(wèn)題,并使Flutter與FaaS等無(wú)服務(wù)容能力打通,形成云端一體化的研發(fā)能力,支持一云多端的發(fā)展需要。在某些場(chǎng)景已經(jīng)取得效果,希望分享過(guò)程中的思考,與大家交流。

閑魚(yú)選擇Flutter主要是出于高性能的考慮。Flutter高性能主要來(lái)源于2個(gè)原因:

更多比較:

沒(méi)有銀彈的解決方案,F(xiàn)lutter與RN各有優(yōu)點(diǎn)。如何選擇因素很多,關(guān)鍵看如何取舍,舉個(gè)例子:

云端技術(shù)棧的打通,是減少協(xié)同的不錯(cuò)的解法。以往前端+Node.js的一體化方案大家應(yīng)該不會(huì)陌生,然而如果端側(cè)使用了Flutter,那云側(cè)Dart自然是第一選擇。

FaaS的本質(zhì)是運(yùn)行在云端,那Dart適合用在云/Server上嗎?

Dart語(yǔ)言早于Flutter,在最初的設(shè)計(jì)上,Dart就可以用于Web、Server。Dart具備一些服務(wù)端語(yǔ)言的特點(diǎn):

閑魚(yú)首先嘗試將Dart作為普通的Server,替代傳統(tǒng)的Java Server,然后再將Dart容器嵌入到FaaS容器中。建立Dart Server能力是第一步,也是主要的工作量所在。

閑魚(yú)在Dart Server方面的建設(shè)思路:

開(kāi)發(fā)期:

運(yùn)行期:

上述內(nèi)容實(shí)現(xiàn)了FlutterDart FaaS的技術(shù)棧的統(tǒng)一,但僅技術(shù)棧統(tǒng)一還遠(yuǎn)遠(yuǎn)不夠,端、云的同學(xué)仍然無(wú)法真正互補(bǔ)和一體化打通,原因在于還有更多深入問(wèn)題需要考慮:

面向這些問(wèn)題,閑魚(yú)的解法思路:

案例一,一體化在資源均衡方面的體現(xiàn)。在近期的一個(gè)項(xiàng)目中,云端一體化使原本2個(gè)月的項(xiàng)目時(shí)間,減少了20天。

案例二,一體化在業(yè)務(wù)閉環(huán)方面的體現(xiàn)。負(fù)責(zé)增長(zhǎng)的一位開(kāi)發(fā)同學(xué),專注在增長(zhǎng)業(yè)務(wù)上,在合適的情況下為合適的人投放合適的內(nèi)容,以此帶來(lái)用戶的增長(zhǎng)和活躍效果。一體化的方式下,可以統(tǒng)一云、端的切面,業(yè)務(wù)研發(fā)不再受云、端的限制。

一體化是建設(shè)高效研發(fā)框架的方向,并不是所有場(chǎng)景都需要一體化的開(kāi)發(fā),但一體化的Flutter、FaaS等技術(shù)組件,可以獨(dú)立使用,也會(huì)帶來(lái)效率提升,并且與原有的開(kāi)發(fā)模式兼容。從一體化的思路去建設(shè),可以使整體架構(gòu)體系更加一致,也有機(jī)會(huì)做一體的架構(gòu)沉淀。

未來(lái)閑魚(yú)希望在一體化上做更多嘗試和深入 探索 ,包括一體化工具、一體化業(yè)務(wù)平臺(tái)、數(shù)據(jù)化智能化等方向。

阿里IM技術(shù)分享(六):閑魚(yú)億級(jí)IM消息系統(tǒng)的離線推送到達(dá)率優(yōu)化

本文由阿里閑魚(yú)技術(shù)團(tuán)隊(duì)逸昂分享,原題“消息鏈路優(yōu)化之弱感知鏈路優(yōu)化”,有修訂和改動(dòng),感謝作者的分享。

閑魚(yú)的IM消息系統(tǒng)作為買(mǎi)家與賣(mài)家的溝通工具,增進(jìn)理解、促進(jìn)信任,對(duì)閑魚(yú)的商品成交有重要的價(jià)值,是提升用戶體驗(yàn)最關(guān)鍵的環(huán)節(jié)。

然而,隨著業(yè)務(wù)體量的快速增長(zhǎng),當(dāng)前這套消息系統(tǒng)正面臨著諸多急待解決的問(wèn)題。

以下幾個(gè)問(wèn)題典型最為典型:

1) 在線消息的體驗(yàn)提升;

2) 離線推送的到達(dá)率;

3) 消息玩法與消息底層系統(tǒng)的耦合過(guò)強(qiáng)。

經(jīng)過(guò)評(píng)估,我們認(rèn)為現(xiàn)階段離線推送的到達(dá)率問(wèn)題最為關(guān)鍵,對(duì)用戶體驗(yàn)影響較大。

本文將要分享的是閑魚(yú)IM消息在解決離線推送的到達(dá)率方面的技術(shù)實(shí)踐,內(nèi)容包括問(wèn)題分析和技術(shù)優(yōu)化思路等 ,希望能帶給你啟發(fā)。

(本文已同步發(fā)布于: ?)

本文是系列文章的第6篇,總目錄如下:

《 阿里IM技術(shù)分享(一):企業(yè)級(jí)IM王者——釘釘在后端架構(gòu)上的過(guò)人之處 》

《 阿里IM技術(shù)分享(二):閑魚(yú)IM基于Flutter的移動(dòng)端跨端改造實(shí)踐 》

《 阿里IM技術(shù)分享(三):閑魚(yú)億級(jí)IM消息系統(tǒng)的架構(gòu)演進(jìn)之路 》

《 阿里IM技術(shù)分享(四):閑魚(yú)億級(jí)IM消息系統(tǒng)的可靠投遞優(yōu)化實(shí)踐 》

《 阿里IM技術(shù)分享(五):閑魚(yú)億級(jí)IM消息系統(tǒng)的及時(shí)性優(yōu)化實(shí)踐 》

《 阿里IM技術(shù)分享(六):閑魚(yú)億級(jí)IM消息系統(tǒng)的離線推送到達(dá)率優(yōu)化 》(* 本文)

從數(shù)據(jù)通信鏈接的技術(shù)角度,我們根據(jù)閑魚(yú)客戶端是否在線,將整體消息鏈路大致分為強(qiáng)感知鏈路和弱感知鏈路。

強(qiáng)感知鏈路由以下子系統(tǒng)或模塊:

1) 發(fā)送方客戶端;

2) idleapi-message(閑魚(yú)的消息網(wǎng)關(guān));

3) heracles(閑魚(yú)的消息底層服務(wù));

4) accs(阿里自研的長(zhǎng)連接通道);

5) 接收方客戶端組成。

整條鏈路的核心指標(biāo)在于端到端延遲和消息到達(dá)率。

強(qiáng)感知鏈路中的雙方都是在線的,消息到達(dá)客戶端就可以保證接收方感知到。強(qiáng)感知鏈路的主要痛點(diǎn)在消息的端到端延遲。

弱感知鏈路與強(qiáng)感知鏈路的主要不同在于: 弱感知鏈路的接收方是離線的,需要依賴離線推送這樣的方式送達(dá)。

因此弱感知鏈路的用戶感知度不強(qiáng),其核心指標(biāo)在于消息的到達(dá)率,而非延遲。

所以當(dāng)前階段,優(yōu)化弱感知鏈路的重點(diǎn)也就是提升離線消息的到達(dá)率。換句話說(shuō), 提升離線消息到達(dá)率問(wèn)題,也就是優(yōu)化弱感知鏈路本身 。

下圖一張整個(gè)IM消息系統(tǒng)的架構(gòu)圖,感受下整體鏈路:

如上圖所示,各主要組件和子系統(tǒng)分工如下:

1) HSF是一個(gè)遠(yuǎn)程服務(wù)框架,是dubbo的內(nèi)部版本;

2) tair是阿里自研的分布式緩存框架,支持 memcached、Redis、LevelDB 等不同存儲(chǔ)引擎;

3) agoo是阿里的離線推送中臺(tái),負(fù)責(zé)整合不同廠商的離線推送通道,向集團(tuán)用戶提供一個(gè)統(tǒng)一的離線推送服務(wù);

4) accs是阿里自研的長(zhǎng)連接通道,為客戶端、服務(wù)端的實(shí)時(shí)雙向交互提供便利;

5) lindorm是阿里自研的NoSQL產(chǎn)品,與HBase有異曲同工之妙;

6) 域環(huán)是閑魚(yú)消息優(yōu)化性能的核心結(jié)構(gòu),用來(lái)存儲(chǔ)用戶最新的若干條消息。

強(qiáng)感知鏈路和弱感知鏈路在通道選擇上是不同的:

1) 強(qiáng)感知鏈路使用accs這個(gè)在線通道;

2) 弱感知鏈路使用agoo這個(gè)離線通道。

通俗了說(shuō),弱感知鏈路指的就是離線消息推送系統(tǒng)。

相比較于在線消息和端內(nèi)推送(也就是上面說(shuō)的強(qiáng)感知鏈路),離線推送難以確保被用戶感知到。

典型的情況包括:

1) 未發(fā)送到用戶設(shè)備:即推送未送達(dá)用戶設(shè)備,這種情況可以從通道的返回分析;

2) 發(fā)送到用戶設(shè)備但沒(méi)有展示到系統(tǒng)通知欄:閑魚(yú)曾遇到通道返回成功,但是用戶未看到推送的案例;

3) 展示到通知欄,并被系統(tǒng)折疊:不同安卓廠商對(duì)推送的折疊策略不同,被折疊后,需用戶主動(dòng)展開(kāi)才能看到內(nèi)容,觸達(dá)效果明顯變差;

4) 展示到通知欄,并被用戶忽略:離線推送的點(diǎn)擊率相比于在線推送更低。

針對(duì)“1)未發(fā)送到用戶設(shè)備”,原因有:

1) 離線通道的token失效;

2) 參數(shù)錯(cuò)誤;

3) 用戶關(guān)閉應(yīng)用通知;

4) 用戶已卸載等。

針對(duì)“3)展示到通知欄,并被系統(tǒng)折疊”,原因有:

1) 通知的點(diǎn)擊率;

2) 應(yīng)用在廠商處的權(quán)重;

3) 推送的數(shù)量等。

針對(duì)“4)展示到通知欄,并被用戶忽略”,原因有:

1) 用戶不愿意查看推送;

2) 用戶看到了推送,但是對(duì)內(nèi)容不感興趣;

3) 用戶在忙別的事,無(wú)暇處理。

總之: 以上這些離線消息推送場(chǎng)景,對(duì)于用戶來(lái)說(shuō)感知度不高,我們也便稱之為弱感知鏈路。

我們的弱感知鏈路分為3部分,即:

1) 系統(tǒng);

2) 通道;

3) 用戶。

共包含了Hermes、agoo、廠商、設(shè)備、用戶、承接頁(yè)這幾個(gè)環(huán)節(jié)。具體如下圖所示。

從推送的產(chǎn)生到用戶最終進(jìn)入APP,共分為如下幾個(gè)步驟:

步驟1 :Hermes是閑魚(yú)的用戶觸達(dá)系統(tǒng),負(fù)責(zé)人群管理、內(nèi)容管理、時(shí)機(jī)把控,是整個(gè)弱感知鏈路的起點(diǎn)。;

步驟2 :agoo是阿里內(nèi)部承接離線推送的中臺(tái),是閑魚(yú)離線推送能力的基礎(chǔ);

步驟3 :agoo實(shí)現(xiàn)離線推送依靠的是廠商的推送通道(如:蘋(píng)果的 apns通道 、Google的fcm通道、及 國(guó)內(nèi)各廠商的自建通道 。;

步驟4 :通過(guò)廠商的通道,推送最終出現(xiàn)在用戶的設(shè)備上,這是用戶能感知到推送的前提條件;

步驟5 :如果用戶剛巧看到這條推送,推送的內(nèi)容也很有趣,在用戶的主動(dòng)點(diǎn)擊下會(huì)喚起APP,打開(kāi)承接頁(yè),進(jìn)而給用戶展示個(gè)性化的商品。

經(jīng)過(guò)以上5個(gè)步驟,至此弱感知鏈路就完成了使命。

弱感知鏈路的核心問(wèn)題在于:

1) 推送的消息是否投遞給了用戶;

2) 已投遞到的消息用戶是否有感知。

這對(duì)應(yīng)推送的兩個(gè)階段:

1) 推送消息是否已到達(dá)設(shè)備;

2) 用戶是否查看推送并點(diǎn)擊。

其中: 到達(dá)設(shè)備這個(gè)階段是最基礎(chǔ)的,也是本次優(yōu)化的核心。

我們可以將每一步的消息處理量依次平鋪,展開(kāi)為一張漏斗圖,從而直觀的查看鏈路的瓶頸。

漏斗圖斜率最大的地方是優(yōu)化的重點(diǎn),差異小的地方不需要優(yōu)化:

通過(guò)分析以上漏斗圖,弱感知鏈路的優(yōu)化重點(diǎn)在三個(gè)方面:

1) agoo受理率:是指我們發(fā)送推送請(qǐng)到的數(shù)量到可以通過(guò)agoo(阿里承接離線推送的中臺(tái))轉(zhuǎn)發(fā)到廠商通道的數(shù)量之間的漏斗;

2) 廠商受理率:是指agoo中臺(tái)受理的量到廠商返回成功的量之間的漏斗;

3) Push點(diǎn)擊率:也就通過(guò)以上通道最終已送到到用戶終端的消息,是否最終轉(zhuǎn)化為用戶的主動(dòng)“點(diǎn)擊”。

有了優(yōu)化方向,我們來(lái)看看優(yōu)化手段吧。

跟隨推送的視角,順著鏈路看一下我們是如何進(jìn)行優(yōu)化的。

用戶的推送,從 Hermes 站點(diǎn)搭乘“班車”,駛向下一站:? agoo 。

這是推送經(jīng)歷的第一站。到站一看,傻眼了,只有不到一半的推送到站下車了。這是咋回事嘞?

這就要先說(shuō)說(shuō) agoo 了,調(diào)用 agoo 有兩種方式:

1) 指定設(shè)備和客戶端,agoo直接將推送投遞到相應(yīng)的設(shè)備;

2) 指定用戶和客戶端,agoo根據(jù)內(nèi)部的轉(zhuǎn)換表,找到用戶對(duì)應(yīng)的設(shè)備,再進(jìn)行投遞。

我們的系統(tǒng)不保存用戶的設(shè)備信息。因此,是按照用戶來(lái)調(diào)用agoo的。

同時(shí): 由于沒(méi)有用戶的設(shè)備信息,并不知道用戶是 iOS 客戶端還是 Android 客戶端。工程側(cè)不得不向 iOS 和 Android 都發(fā)送一遍推送。雖然保證了到達(dá),但是,一半的調(diào)用都是無(wú)效的。

為了解這個(gè)問(wèn)題: 我們使用了agoo的設(shè)備信息。將用戶轉(zhuǎn)換設(shè)備這一階段提前到了調(diào)用 agoo 之前,先明確用戶對(duì)應(yīng)的設(shè)備,再指定設(shè)備調(diào)用 agoo,從而避免無(wú)效調(diào)用。

agoo調(diào)用方式優(yōu)化后,立刻剔除了無(wú)效調(diào)用,agoo受理率有了明顯提升。

至此: 我們總算能對(duì) agoo 受理失敗的真正原因做一個(gè)高大上的分析了。

根據(jù)統(tǒng)計(jì): 推送被 agoo 拒絕的主要原因是——用戶關(guān)閉了通知權(quán)限。同時(shí),我們對(duì) agoo 調(diào)用數(shù)據(jù)的進(jìn)一步分析發(fā)現(xiàn)——有部分用戶找不到對(duì)應(yīng)的設(shè)備。 優(yōu)化到此,我們猛然發(fā)現(xiàn)多了兩個(gè)問(wèn)題。

那就繼續(xù)優(yōu)化唄:

1) 通知體驗(yàn)優(yōu)化,引導(dǎo)打開(kāi)通知權(quán)限;

2) 與agoo共建設(shè)備庫(kù),解決設(shè)備轉(zhuǎn)換失敗的問(wèn)題。

這兩個(gè)優(yōu)化方向又是一片新天地,我們擇日再聊。

推送到達(dá) agoo ,分機(jī)型搭乘廠商“專列”,駛向下一站:用戶設(shè)備。

這是推送經(jīng)歷的第二站。出站查票,發(fā)現(xiàn)竟然超員了。

于是乎: 我們每天有大量推送因?yàn)槌^(guò)廠商設(shè)定的限額被攔截。

為什么會(huì)這樣呢?

實(shí)際上: 提供推送通道的廠商(沒(méi)錯(cuò), 各手機(jī)廠商的自家推送通道良莠不齊 ),為了保證用戶體驗(yàn),會(huì)對(duì)每個(gè)應(yīng)用能夠推送的消息總量進(jìn)行限制。

對(duì)于廠商而言,這個(gè)限制會(huì)根據(jù)推送的類型和應(yīng)用的用戶規(guī)模設(shè)定——推送主要分為產(chǎn)品類的推送和營(yíng)銷類的推送。

廠商推送通道對(duì)于不同類型消息的限制是:

1) 對(duì)于產(chǎn)品類推送,廠商會(huì)保證到達(dá);

2) 對(duì)于營(yíng)銷類推送,廠商會(huì)進(jìn)行額度限制;

3) 未標(biāo)記的推送,默認(rèn)作為營(yíng)銷類推送對(duì)待。

我們剛好沒(méi)有對(duì)推送進(jìn)行標(biāo)記,因此觸發(fā)了廠商的推送限制。

這對(duì)我們的用戶來(lái)說(shuō),會(huì)帶來(lái)困擾。閑魚(yú)的交易,很依賴買(mǎi)賣(mài)家之間的消息互動(dòng)。這部分消息是需要確保到達(dá)的。

同樣: 訂單類的消息、用戶的關(guān)注,也需要保證推送給用戶。

根據(jù)主流廠商的接口協(xié)議,我們將推送的消息分為以下幾類,并進(jìn)行相應(yīng)標(biāo)記:

1) 即時(shí)通訊消息;

2) 訂單狀態(tài)變化;

3) 用戶關(guān)注內(nèi)容;

4) 營(yíng)銷消息這幾類。

同時(shí),在業(yè)務(wù)上,我們也進(jìn)行了推送的治理——將用戶關(guān)注度不高的消息,取消推送,避免打擾。

經(jīng)過(guò)這些優(yōu)化,因?yàn)槌^(guò)廠商限額而被攔截的推送實(shí)現(xiàn)了清零。

通過(guò)優(yōu)化agoo受理率、廠商受理率,我們解決了推送到達(dá)量的瓶頸。但即使消息被最終送達(dá),用戶到底點(diǎn)擊了沒(méi)有?這才是消息推送的根本意義所在。

于是,在日常的開(kāi)發(fā)測(cè)試過(guò)程中,我們發(fā)現(xiàn)了推送的兩個(gè)體驗(yàn)問(wèn)題:

1) 用戶點(diǎn)擊Push有開(kāi)屏廣告;

2) 營(yíng)銷Push也有權(quán)限校驗(yàn),更換用戶登陸后無(wú)法點(diǎn)擊。

對(duì)于開(kāi)屏廣告功能,我們?cè)黾恿薖ush點(diǎn)擊跳過(guò)廣告的能力。

針對(duì)Push的權(quán)限校驗(yàn)功能,閑魚(yú)根據(jù)場(chǎng)景做了細(xì)分:

1) 涉及個(gè)人隱私的推送,保持權(quán)限校驗(yàn)不變;

2) 營(yíng)銷類的推送,放開(kāi)權(quán)限校驗(yàn)。

以上是點(diǎn)擊體驗(yàn)的優(yōu)化,我們還需要考慮用戶的點(diǎn)擊意愿。

用戶點(diǎn)擊量與推送的曝光量、推送素材的有趣程度相關(guān)。推送的曝光量又和推送的到達(dá)量、推送的到達(dá)時(shí)機(jī)有關(guān)。

具體的優(yōu)化手段是:

1) 在推送內(nèi)容上:我們需要優(yōu)化的是推送的時(shí)機(jī)和相應(yīng)的素材;

2) 在推送時(shí)機(jī)上:算法會(huì)根據(jù)用戶的偏好和個(gè)性化行為數(shù)據(jù),計(jì)算每個(gè)用戶的個(gè)性化推送時(shí)間,在用戶空閑的時(shí)間推送(避免在不合適的時(shí)間打擾用戶,同時(shí)也能提升用戶看到推送的可能性)。

3) 在推送素材上:算法會(huì)根據(jù)素材的實(shí)時(shí)點(diǎn)擊反饋,對(duì)素材做實(shí)時(shí)賽馬。只發(fā)用戶感興趣的素材,提高用戶點(diǎn)擊意愿。

通過(guò)以上我們的分析和技術(shù)優(yōu)化手段,整體弱推送鏈路鏈路有了不錯(cuò)的提升,離線消息的到達(dá)率相對(duì)提升了兩位數(shù)。

本篇主要和大家聊的是只是IM消息系統(tǒng)鏈路中的一環(huán)——弱感知鏈路的優(yōu)化,落地到到具體的業(yè)務(wù)也就是離線消息送達(dá)率問(wèn)題。

整體IM消息系統(tǒng),還是一個(gè)比較復(fù)雜的領(lǐng)域。

我們?cè)谙⑾到y(tǒng)的發(fā)展過(guò)程中,面臨著如下問(wèn)題:

1) 如何進(jìn)行消息的鏈路追蹤;

2) 如何保證IM消息的快速到達(dá)(見(jiàn)《 閑魚(yú)億級(jí)IM消息系統(tǒng)的及時(shí)性優(yōu)化實(shí)踐 》);

3) 如何將消息的玩法和底層能力分離;

4) 離線推送中如何通過(guò)用戶找到對(duì)應(yīng)的設(shè)備。

這些問(wèn)題,我們?cè)谝郧暗奈恼轮杏兴窒?,以后也?huì)陸續(xù)分享更多,敬請(qǐng)期待。

[1]? Android P正式版即將到來(lái):后臺(tái)應(yīng)用?;?、消息推送的真正噩夢(mèng)

[2]? 一套高可用、易伸縮、高并發(fā)的IM群聊、單聊架構(gòu)方案設(shè)計(jì)實(shí)踐

[3]? 一套億級(jí)用戶的IM架構(gòu)技術(shù)干貨(上篇):整體架構(gòu)、服務(wù)拆分等

[4]? 一套億級(jí)用戶的IM架構(gòu)技術(shù)干貨(下篇):可靠性、有序性、弱網(wǎng)優(yōu)化等

[5]? 從新手到專家:如何設(shè)計(jì)一套億級(jí)消息量的分布式IM系統(tǒng)

[6]? 企業(yè)微信的IM架構(gòu)設(shè)計(jì)揭秘:消息模型、萬(wàn)人群、已讀回執(zhí)、消息撤回等

[7]? 融云技術(shù)分享:全面揭秘億級(jí)IM消息的可靠投遞機(jī)制

[8]? 移動(dòng)端IM中大規(guī)模群消息的推送如何保證效率、實(shí)時(shí)性?

[9]? 現(xiàn)代IM系統(tǒng)中聊天消息的同步和存儲(chǔ)方案探討

[10]? 新手入門(mén)一篇就夠:從零開(kāi)發(fā)移動(dòng)端IM

[11]? 移動(dòng)端IM開(kāi)發(fā)者必讀(一):通俗易懂,理解移動(dòng)網(wǎng)絡(luò)的“弱”和“慢”

[12]? 移動(dòng)端IM開(kāi)發(fā)者必讀(二):史上最全移動(dòng)弱網(wǎng)絡(luò)優(yōu)化方法總結(jié)

[13]? IM消息送達(dá)保證機(jī)制實(shí)現(xiàn)(一):保證在線實(shí)時(shí)消息的可靠投遞

[14]? IM消息送達(dá)保證機(jī)制實(shí)現(xiàn)(二):保證離線消息的可靠投遞

[15]? 零基礎(chǔ)IM開(kāi)發(fā)入門(mén)(一):什么是IM系統(tǒng)?

[16]? 零基礎(chǔ)IM開(kāi)發(fā)入門(mén)(二):什么是IM系統(tǒng)的實(shí)時(shí)性?

[17]? 零基礎(chǔ)IM開(kāi)發(fā)入門(mén)(三):什么是IM系統(tǒng)的可靠性?

[18]? 零基礎(chǔ)IM開(kāi)發(fā)入門(mén)(四):什么是IM系統(tǒng)的消息時(shí)序一致性?

(本文已同步發(fā)布于: ?)


本文題目:flutter閑魚(yú),閑魚(yú)放棄fluttergo
網(wǎng)站路徑:http://weahome.cn/article/dsddihh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部