Jack Jiang

          我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
          posts - 494, comments - 13, trackbacks - 0, articles - 1

          本文由騰訊WXG客戶端開發(fā)工程師yecong分享,本文做了修訂和改動(dòng)。

          1、引言

          相對(duì)于傳統(tǒng)的消費(fèi)級(jí)IM應(yīng)用,企業(yè)級(jí)IM應(yīng)用的特殊之外在于它的用戶關(guān)系是按照所屬企業(yè)的組織架構(gòu)來關(guān)聯(lián)的起來,而組織架構(gòu)的大小是無法預(yù)設(shè)上限的,這也要求企業(yè)級(jí)IM應(yīng)用在遇到真正的超大規(guī)模組織架構(gòu)時(shí),如何保證它的應(yīng)用性能不受限于(或者說是盡可能不受限于)企業(yè)架構(gòu)規(guī)模,這是個(gè)比較有難度的技術(shù)問題。

          本文主要分享的是企業(yè)微信在百對(duì)百萬級(jí)大規(guī)模組織架構(gòu)后文簡(jiǎn)稱大架構(gòu)時(shí),是如何對(duì)客戶端進(jìn)行性能優(yōu)化過程的,希望帶給你啟發(fā)。

          內(nèi)容分成兩部分講述,第一部分是短線迭代的優(yōu)化,主要是并發(fā)性能的優(yōu)化。第二部分是長(zhǎng)線迭代的優(yōu)化,主要是從業(yè)務(wù)模式上做了根本性優(yōu)化。

          以下是相關(guān)文章,推薦一并閱讀:

          企業(yè)微信客戶端中組織架構(gòu)數(shù)據(jù)的同步更新方案優(yōu)化實(shí)戰(zhàn)

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

          釘釘——基于IM技術(shù)的新一代企業(yè)OA平臺(tái)的技術(shù)挑戰(zhàn)(視頻+PPT) [附件下載]

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

           

          技術(shù)交流:

          (本文已同步發(fā)布于:http://www.52im.net/thread-4437-1-1.html

          2、100萬級(jí)組織架構(gòu)時(shí)的性能問題

          當(dāng)私有化的組織架構(gòu)上升到100W的量級(jí)時(shí),出現(xiàn)了嚴(yán)重影響組織架構(gòu)使用的問題:打開二級(jí)部門時(shí),加載緩慢。

          如圖所示,loading可能持續(xù)一分鐘以上:

          3、100萬級(jí)組織架構(gòu)的問題分析

          我們分析一下加載二級(jí)部門的流程。

          下面是加載二級(jí)部門的流程圖:

          • 1)如果從來沒加載過該部門,需要從服務(wù)端拉取部門下的節(jié)點(diǎn)詳情(這里是因?yàn)橹拔覀円呀?jīng)做了優(yōu)化,首次登錄時(shí)只拉取了部門的節(jié)點(diǎn)ID,沒有拉取詳情);
          • 2)如果加載過該部門,就直接從DB讀取該部門的數(shù)據(jù),然后返回UI展示。

          當(dāng)只有一條DB線程時(shí),組織架構(gòu)更新的任務(wù),可能會(huì)插入到加載二級(jí)部門的任務(wù)的前面。而在百萬級(jí)別的組織架構(gòu)中,全量更新的DB任務(wù)有可能比較久,全量更新的插入或者更新節(jié)點(diǎn)可能比較多,導(dǎo)致本來很快可以完成的二級(jí)部門加載任務(wù),要排隊(duì)比較久才能執(zhí)行完。

          下面是組織架構(gòu)全量更新的流程圖:

          在這里,讀寫并發(fā)上出現(xiàn)了明顯的瓶頸。

          原因總結(jié)如下:

          • 1)加載二級(jí)部門和全量更新共用一條DB線程;
          • 2)當(dāng)全量更新大量節(jié)點(diǎn)時(shí),全量更新的低優(yōu)先級(jí)任務(wù)卡住加載二級(jí)部門的高優(yōu)先級(jí)任務(wù)。

          4、針對(duì)100萬級(jí)組織架構(gòu)的優(yōu)化方案

          4.1基本

          讀寫分離為了提高組織架構(gòu)在大規(guī)模數(shù)據(jù)下的讀寫并發(fā)性能,我們開啟了wal模式,把讀寫任務(wù)分別放在不同的線程中執(zhí)行。

          針對(duì)加載二級(jí)部門的流程,可以在讀線程中讀取部門的詳情節(jié)點(diǎn),而組織架構(gòu)更新可以在寫線程中單獨(dú)執(zhí)行。

          由于加載二級(jí)部門的原流程是拉取數(shù)據(jù)、寫入DB、再從DB讀取數(shù)據(jù),而且wal只支持一寫多讀,因此我們調(diào)整了緩存策略,把保存節(jié)點(diǎn)詳情的寫任務(wù)延遲到流程最后,優(yōu)先構(gòu)造了cache返回UI。

          這樣從DB中讀出數(shù)據(jù)的讀任務(wù),就不需要等待保存節(jié)點(diǎn)詳情的寫任務(wù)。避免了保存節(jié)點(diǎn)的寫任務(wù)再次被其他寫任務(wù)阻塞,讀任務(wù)又被保存節(jié)點(diǎn)的寫任務(wù)阻塞,退化成串行操作。

          4.2WAL機(jī)制的原理

          調(diào)用方修改的數(shù)據(jù)并不直接寫入到數(shù)據(jù)庫文件中,而是寫入到另外一個(gè)稱為WAL的文件中,然后在隨后的某個(gè)時(shí)間點(diǎn)被寫回到數(shù)據(jù)庫文件中。

          在這個(gè)時(shí)間點(diǎn)的回寫操作,會(huì)降低數(shù)據(jù)庫當(dāng)時(shí)的讀寫性能。

          但是通過設(shè)置對(duì)WAL文件大小的限制,這種性能影響是可控的。

          實(shí)際上線后也沒有遇到由于checkpoint同步導(dǎo)致數(shù)據(jù)庫慢的反饋。

          4.3緩存策略

          寫策略的步驟:先更新緩存中的數(shù)據(jù),再更新數(shù)據(jù)庫中的數(shù)據(jù)。

          讀策略的步驟:

          • 1)如果讀取的數(shù)據(jù)命中了緩存,則直接返回?cái)?shù)據(jù);
          • 2)如果讀取的數(shù)據(jù)沒有命中緩存,則從數(shù)據(jù)庫中讀取數(shù)據(jù),然后將數(shù)據(jù)寫入到緩存,并且返回給UI。

          4.4方案總結(jié)

          5、100萬級(jí)優(yōu)化后的效果

           

          在優(yōu)化前,只有52%的用戶能在1s內(nèi)加載完二級(jí)部門。上線之后,93%的用戶都能在1s內(nèi)打開二級(jí)部門。耗時(shí)小于1s的用戶占比提升40%!

          6、當(dāng)對(duì)面300萬組織架構(gòu)時(shí)的問題

          6.1概述

          當(dāng)業(yè)務(wù)進(jìn)一步發(fā)展時(shí),我們預(yù)估未來將要到達(dá)300W量級(jí)的組織架構(gòu)。于是我們就開始提前規(guī)劃如何能在組織架構(gòu)數(shù)量一直增長(zhǎng)的情況下,還能讓組織架構(gòu)流暢好用。

          6.2問題

          主要是:

          • 1)選人控件閃退和ANR;
          • 2)組織架構(gòu)全量更新閃退。

          在300w的組織架構(gòu)環(huán)境中,舊的組織架構(gòu)加載方案,在全量更新、選人控件中均出現(xiàn)了占用內(nèi)存過大甚至閃退的問題。而且舊方案的加載時(shí)間會(huì)隨著節(jié)點(diǎn)數(shù)量的增加,不可避免地成正比增長(zhǎng)。

          6.3分析

          當(dāng)前方案的耗時(shí)、內(nèi)存占用與用戶組織架構(gòu)的大小成正比,單點(diǎn)優(yōu)化無法滿足組織架構(gòu)持續(xù)增長(zhǎng)的需求。

          具體來說,會(huì)造成下面的一些問題:

          • 1)選人控件會(huì)加載全量的組織架構(gòu)ID樹,數(shù)量過多時(shí)容易發(fā)生閃退和ANR;
          • 2)組織架構(gòu)全量更新占用內(nèi)存過大,造成閃退。

          因此,我們需要一個(gè)新的業(yè)務(wù)模式,即便總的組織架構(gòu)規(guī)模一直上漲的情況下,也能維持較好的性能。

          7、針對(duì)300萬組織架構(gòu)的優(yōu)化方案

          比較容易想到的一個(gè)方案是web加載的模式,不保存本地?cái)?shù)據(jù),但是體驗(yàn)比較差,每層都會(huì)出loading。

          聯(lián)系到我們的具體業(yè)務(wù),由于私有化對(duì)不同的部門,劃分出了具有意義的獨(dú)立組織機(jī)構(gòu)——單位。

          單位是具有管理意義的部門,不同單位可以獨(dú)立加載。而每個(gè)人,也擁有主單位和兼崗單位。所以可以按照單位加載的方式,從根本上解決目前組織架構(gòu)面臨的瓶頸。

          按單位加載,可以簡(jiǎn)單理解為按部門加載:

          概念定義:

          • 1)單位:政府行政組織結(jié)構(gòu)中的職能部門,組建架構(gòu)并承擔(dān)對(duì)應(yīng)責(zé)任;
          • 2)主單位:“我”所在的單位;
          • 3)其他單位:除了“我”所在的其他單位;
          • 4)骨架:通訊錄骨架包含了所有的單位節(jié)點(diǎn);
          • 5)普通部門:不屬于任何單位的部門節(jié)點(diǎn)。

          下圖是組織架構(gòu)樹的示意圖:

          如上圖所示:藍(lán)色節(jié)點(diǎn)是優(yōu)先加載的本單位,灰色節(jié)點(diǎn)是其他單位,紅色節(jié)點(diǎn)是骨架。不同的單位獨(dú)立加載。

          8、300萬優(yōu)化方案中的“按單位加載”技術(shù)思路

          8.1加載策略

          接下來我們看看加載策略。

          第一:是對(duì)自己所在的主單位(藍(lán)色節(jié)點(diǎn)),每次喚醒時(shí)就會(huì)更新,跟舊組織架構(gòu)的邏輯類似,但是會(huì)限制拉取節(jié)點(diǎn)的數(shù)量。

          第二:對(duì)于其他單位(灰色節(jié)點(diǎn)),點(diǎn)擊到該單位時(shí)才會(huì)拉取,2個(gè)小時(shí)后會(huì)淘汰刪除,避免數(shù)據(jù)表過大。

          第三:對(duì)于骨架(紅色節(jié)點(diǎn)),會(huì)全量加載節(jié)點(diǎn)ID,再拉取節(jié)點(diǎn)詳情。

          拉取策略限制了能夠拉取的節(jié)點(diǎn)詳情數(shù)量,如果單位節(jié)點(diǎn)數(shù)量超過了限制,首先拉取全量ID,再按照優(yōu)先規(guī)則,拉取配置的節(jié)點(diǎn)詳請(qǐng)數(shù)量。

          8.2加載流程

          加載的流程是先拉取自己的單位列表,然后拉取每個(gè)單位的全量通訊錄ID,再按照后臺(tái)策略,拉取所需的詳細(xì)節(jié)點(diǎn),最后拉取骨架。

          如果點(diǎn)擊到主單位:

          • 1)如果只有ID沒有節(jié)點(diǎn),會(huì)立刻拉取節(jié)點(diǎn)詳情返回界面;
          • 2)如果ID和節(jié)點(diǎn)詳情都有,可以直接返回UI展示,然后延遲刷新節(jié)點(diǎn)。

          如果是點(diǎn)擊到其他單位:可能出現(xiàn)ID和詳情都沒有的情況,需要拉取其他單位的節(jié)點(diǎn),界面loading等待。

          如果是骨架:就一定有節(jié)點(diǎn)和詳情,只需要延遲刷新。

          9、300萬優(yōu)化方案的分層設(shè)計(jì)思路

          接下來我們看看如何分層。

          在300萬量級(jí)的大規(guī)模組織架構(gòu)下,移動(dòng)端和pc端都出現(xiàn)了組織架構(gòu)卡頓、閃退的問題,所以我們希望能夠開發(fā)一套各端共用的邏輯,統(tǒng)一維護(hù)。

          第一:是要抽取公共的基礎(chǔ)庫,包括boost庫、任務(wù)框架、線程管理框架等。

          第二:是設(shè)計(jì)公共的數(shù)據(jù)結(jié)構(gòu)。

          第三:因?yàn)椴煌说木W(wǎng)絡(luò)庫差異比較大,這里不好完全共用,所以需要抽取網(wǎng)絡(luò)任務(wù)接口,由各端獨(dú)立實(shí)現(xiàn)。

          具體到框架圖,我們從下往上看:

          • 1)底層是基礎(chǔ)庫;
          • 2)接著是C++實(shí)現(xiàn)的跨平臺(tái)業(yè)務(wù)層;
          • 3)Service層是移動(dòng)端和pc端分開實(shí)現(xiàn),主要是做接口調(diào)用和回調(diào)的簡(jiǎn)單封裝;
          • 4)上層則各端界面實(shí)現(xiàn)。

          上層界面為了兼容新舊兩套組織架構(gòu),也做了接口抽象,可以通過開關(guān)自由切換。這樣優(yōu)點(diǎn)就是有統(tǒng)一的業(yè)務(wù)邏輯代碼、DB設(shè)計(jì)和線程管理。

          關(guān)鍵點(diǎn):

          • 1)抽取公共基礎(chǔ)庫;
          • 2)抽象公共的數(shù)據(jù)結(jié)構(gòu);
          • 3)抽象網(wǎng)絡(luò)層和數(shù)據(jù)庫層接口。

          優(yōu)點(diǎn):統(tǒng)一的業(yè)務(wù)邏輯代碼、DB設(shè)計(jì)、線程管理。

          10、300萬優(yōu)化方案的整體架構(gòu)設(shè)計(jì)思路

          在具體實(shí)現(xiàn)之前,我們來看看架構(gòu)設(shè)計(jì)的一些概念。

          10.1架構(gòu)整潔之道

          1)業(yè)務(wù)實(shí)體和用例:

          關(guān)鍵業(yè)務(wù)邏輯和關(guān)鍵業(yè)務(wù)數(shù)據(jù)是緊密相關(guān)的,所以它們很適合被放在同一個(gè)對(duì)象中處理。

          我們將這種對(duì)象稱為“業(yè)務(wù)實(shí)體”。業(yè)務(wù)實(shí)體這個(gè)概念中應(yīng)該只有業(yè)務(wù)邏輯,沒有別的,與數(shù)據(jù)庫、用戶界面、第三方框架等內(nèi)容無關(guān)。

          用例所描述的是某種特定應(yīng)用情景下的業(yè)務(wù)邏輯,可以理解為:輸入 + 業(yè)務(wù)實(shí)體 + 輸出 = 用例。

          2)軟件架構(gòu):

          軟件的系統(tǒng)架構(gòu)應(yīng)該為該系統(tǒng)的用例提供支持。

          一個(gè)良好的架構(gòu)設(shè)計(jì)應(yīng)該圍繞著用例來展開,這樣的架構(gòu)設(shè)計(jì)可以在脫離框架、工具以及使用環(huán)境的情況下完整地描述用例。

          3)整潔架構(gòu):

          下圖的同心圓分別代表了軟件系統(tǒng)中的不同層次,越靠近中心,其所在的軟件層次就越高。基本上,外層圓代表的是機(jī)制,內(nèi)層圓代表的是策略。

          這其中有一條貫穿整個(gè)架構(gòu)設(shè)計(jì)的規(guī)則,即依賴關(guān)系規(guī)則:

          10.2我們的架構(gòu)

          我們的類圖與架構(gòu)設(shè)計(jì)概念的對(duì)應(yīng)關(guān)系如下:

          • 1)業(yè)務(wù)實(shí)體:ArchTask;
          • 2)用例:ArchProto;
          • 3)模型層:即最外層,各種第三方框架,如DbInterface(數(shù)據(jù)庫模塊)、ArchLogicHandler(網(wǎng)絡(luò)模塊)等。

          我們從一次具體的業(yè)務(wù)調(diào)用流程來看看這樣設(shè)計(jì)的意義。

          下面是從UI發(fā)起的一次架構(gòu)更新流程,大家可以主要關(guān)注控制流是怎么穿越各層的邊界:控制流從最外層的用戶界面開始,穿過用例(Arch),最后調(diào)用最外層的組件:網(wǎng)絡(luò)模塊和數(shù)據(jù)庫模塊。但是我們?cè)创a中的依賴方向卻都是向內(nèi)指向用例的。

          這里,我們采用的是依賴反轉(zhuǎn)原則(DIP)來解決這種相反性。我們可以通過調(diào)整代碼中的接口和繼承關(guān)系,利用源碼中的依賴關(guān)系,限制控制流只能在正確的地方跨域架構(gòu)邊界。

          在上面的流程圖中,主要有兩個(gè)應(yīng)用依賴反轉(zhuǎn)原則的地方:

          1)CalcPreLoadArchIDs是從SyncUnitArchTask(業(yè)務(wù)實(shí)體)調(diào)用調(diào)用到ArchProto(用例)。

          業(yè)務(wù)實(shí)體這樣的高層概念,是無須了解像用例這樣的底層概念的。反之,底層業(yè)務(wù)用例卻需要了解高層的業(yè)務(wù)實(shí)體。

          所以在SyncUnitArchTask中,其實(shí)是通過調(diào)用ArchProto的接口來調(diào)用CalcPreLoadArchIDs。

          SyncUnitArchTask中的調(diào)用代碼如下:

          arch_service_context_->CalcPreLoadArchIDs(unit_id_, arch_service_context_->GetCurrentVid(), other_unit_click_partyid_, vecHashNode, all_tmp_ids, arch_ids, ptr_map_);

          ArchProto會(huì)在Task初始化時(shí),把自己設(shè)置進(jìn)Task中,給各類型的Task反向調(diào)用。

          classArchProto : publicArchServiceContext

          {

          ...

          };

          2)最外層的模型層一般是由工具、數(shù)據(jù)庫、網(wǎng)絡(luò)框架等組成的。

          框架與驅(qū)動(dòng)程序?qū)又邪怂械膶?shí)現(xiàn)細(xì)節(jié)。

          從系統(tǒng)架構(gòu)的角度看,工具通常是無關(guān)緊要的,因?yàn)檫@只是一個(gè)底層的實(shí)現(xiàn)細(xì)節(jié),一種達(dá)成目標(biāo)的手段。

          當(dāng)Task需要調(diào)用網(wǎng)絡(luò)模塊收發(fā)請(qǐng)求或者調(diào)用數(shù)據(jù)庫模塊獲取數(shù)據(jù)時(shí),為了避免內(nèi)層策略依賴外層機(jī)制,Task只會(huì)調(diào)用外層工具的接口層,而不會(huì)依賴實(shí)現(xiàn)細(xì)節(jié)。

          這樣的架構(gòu)設(shè)計(jì)給我們帶來的好處是,我們可以輕松替換框架,而不影響內(nèi)層策略。比如在桌面端,我們會(huì)有另外一套完全不同的網(wǎng)絡(luò)模塊實(shí)現(xiàn),只需要掛接不同的網(wǎng)絡(luò)實(shí)現(xiàn)子類,我們就可以在桌面端復(fù)用新的大架構(gòu)模塊。

          良好的架構(gòu)設(shè)計(jì)應(yīng)該盡可能地允許用戶推遲和延后決定采用什么框架、數(shù)據(jù)庫、網(wǎng)絡(luò)框架以及其他與環(huán)境相關(guān)的工具。

          總之,良好的架構(gòu)設(shè)計(jì)應(yīng)該只關(guān)注用例,并能將它們與其他的周邊因素隔離。

          10.3新舊組織架構(gòu)模塊的交互

          大架構(gòu)跨平臺(tái)層,跟原來的組織架構(gòu)模塊是怎么交互的呢?

          原來的組織架構(gòu)的數(shù)據(jù)表主要分成三部分:

          • 1)部門表;
          • 2)人員信息表;
          • 3)部門人員關(guān)系表。

          而出現(xiàn)性能問題的主要在于關(guān)系表上。所以數(shù)據(jù)設(shè)計(jì)上,人員信息保留在原組織架構(gòu)底層,部門人員關(guān)系表、部門表在大架構(gòu)底層。

          表結(jié)構(gòu)設(shè)計(jì):

          • 1)主要組成:人員信息表、部門表、部門人員關(guān)系表;
          • 2)大架構(gòu)底層保存部門和部門人員關(guān)系表,人員信息保留在原組織架構(gòu)底層。

          大架構(gòu)底層與原組織架構(gòu)底層的業(yè)務(wù)關(guān)聯(lián):

          • 1)人員展示的部門鏈路如何獲取?從大架構(gòu)底層獲取,因?yàn)殛P(guān)系表存放在大架構(gòu)底層;
          • 2)搜索如何做?部門名字保存到原組織架構(gòu)底層,復(fù)用原組織架構(gòu)底層的索引建立邏輯。

          11、300萬優(yōu)化方案的雙DB切換模式

          11.1舊的讀寫表切換方式

          舊方案里組織架構(gòu)的全量更新流程:

          當(dāng)后臺(tái)告訴客戶端需要全量更新時(shí),客戶端會(huì)將所有節(jié)點(diǎn)標(biāo)為待刪除,然后同步后臺(tái)的節(jié)點(diǎn),清除待刪除標(biāo)記。同步完成后,將寫表的數(shù)據(jù)同步到讀表,更新版本號(hào)。最后UI就可以從讀表中讀取到最新的數(shù)據(jù)。

          而之前通過用戶日志案例分析,最長(zhǎng)的耗時(shí)主要是在將寫表的數(shù)據(jù)拷貝到讀表上面。在這個(gè)過程中,大架構(gòu)下部分用戶的日志里有更新57w節(jié)點(diǎn)的數(shù)據(jù)用了2個(gè)半小時(shí)的情況,而且這個(gè)步驟是原子操作,如果不能夠一次完成,下次還得重新執(zhí)行。

          原有流程里,讀表和寫表是固定的,導(dǎo)致全量更新需要等讀表同步完數(shù)據(jù),界面才能讀到新數(shù)據(jù)。

          分析:寫表同步數(shù)據(jù)到讀表耗時(shí)很久,當(dāng)全量更新時(shí),如果有大量節(jié)點(diǎn)需要更新,會(huì)耗時(shí)很長(zhǎng)。

          缺點(diǎn):寫表和讀表固定,全量更新需要等數(shù)據(jù)同步完成,界面才能讀取到新數(shù)據(jù)。

          11.2新的雙DB切換方式

          針對(duì)舊方案中讀寫表同步過久的問題,大架構(gòu)方案里我們換成了雙DB切換的模式。下面是我們的狀態(tài)機(jī)設(shè)計(jì)和業(yè)務(wù)代碼獲取表名的邏輯。

          這樣修改之后,不需要等讀寫表同步完,UI就可以讀取到最新數(shù)據(jù)。而同步的過程可以在后臺(tái)慢慢完成,并且不會(huì)受原子性操作的限制。業(yè)務(wù)代碼獲取讀表的邏輯,也收攏到了一個(gè)函數(shù)。

           

          因?yàn)閱挝荒J较拢總€(gè)單位的節(jié)點(diǎn)數(shù)量都不會(huì)很多,而且大多數(shù)用戶只會(huì)加載日常有交流的幾個(gè)單位,所以讀寫表同步這里,我們采用了把原表刪掉,全量拷貝的方式。

          12、200萬級(jí)優(yōu)化后的效果

          對(duì)于耗時(shí),優(yōu)化前使用全量加載的方式使得耗時(shí)很長(zhǎng),而優(yōu)化后采用的“本單位+骨架”的預(yù)加載邏輯使得加載耗時(shí)大幅度減小。優(yōu)化后的內(nèi)存占用大小在各場(chǎng)景下均有減小,通訊錄頁面的流暢度也得到了一定的提升。

          耗時(shí):

          CPU占用率:

          內(nèi)存占用大小:

          卡頓:

          13、相關(guān)資料

          [1] 企業(yè)微信客戶端中組織架構(gòu)數(shù)據(jù)的同步更新方案優(yōu)化實(shí)戰(zhàn)

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

          [3] 釘釘——基于IM技術(shù)的新一代企業(yè)OA平臺(tái)的技術(shù)挑戰(zhàn)(視頻+PPT) [附件下載]

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

          [5] 深度解密釘釘即時(shí)消息服務(wù)DTIM的技術(shù)設(shè)計(jì)

          [6] 深度揭密RocketMQ在釘釘IM系統(tǒng)中的應(yīng)用實(shí)踐

          [7] IM開發(fā)干貨分享:萬字長(zhǎng)文,詳解IM“消息“列表卡頓優(yōu)化實(shí)踐

          [8] 手Q客戶端針對(duì)2020年春節(jié)紅包的技術(shù)實(shí)踐

          [9] 移動(dòng)端IM實(shí)踐:Android版微信如何大幅提升交互性能(一)

          [10] 移動(dòng)端IM實(shí)踐:Android版微信如何大幅提升交互性能(二)

          [11] 移動(dòng)端IM實(shí)踐:iOS版微信的多設(shè)備字體適配方案探討

          [12] 愛奇藝技術(shù)分享:愛奇藝Android客戶端啟動(dòng)速度優(yōu)化實(shí)踐總結(jié)

          [13] 微信團(tuán)隊(duì)分享:微信支付代碼重構(gòu)帶來的移動(dòng)端軟件架構(gòu)上的思考


          (本文已同步發(fā)布于:http://www.52im.net/thread-4437-1-1.html



          作者:Jack Jiang (點(diǎn)擊作者姓名進(jìn)入Github)
          出處:http://www.52im.net/space-uid-1.html
          交流:歡迎加入即時(shí)通訊開發(fā)交流群 215891622
          討論:http://www.52im.net/
          Jack Jiang同時(shí)是【原創(chuàng)Java Swing外觀工程BeautyEye】【輕量級(jí)移動(dòng)端即時(shí)通訊框架MobileIMSDK】的作者,可前往下載交流。
          本博文 歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明出處(也可前往 我的52im.net 找到我)。


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          Jack Jiang的 Mail: jb2011@163.com, 聯(lián)系QQ: 413980957, 微信: hellojackjiang
          主站蜘蛛池模板: 清苑县| 额敏县| 辉南县| 察雅县| 桓台县| 汉寿县| 鄂尔多斯市| 宁波市| 五台县| 阳泉市| 施甸县| 德安县| 玛多县| 阜平县| 明溪县| 邵阳市| 道真| 喀喇沁旗| 金寨县| 武城县| 平塘县| 泽普县| 莫力| 西贡区| 星座| 滁州市| 海阳市| 社旗县| 孟津县| 安徽省| 迁西县| 哈巴河县| 甘德县| 建始县| 奈曼旗| 恩平市| 柳林县| 珠海市| 张掖市| 通州市| 佛坪县|