關(guān)于微信內(nèi)部正在使用的網(wǎng)絡(luò)層封裝庫(kù)Mars開(kāi)源的消息,1個(gè)多月前就已滿天飛(參見(jiàn)《微信Mars:微信內(nèi)部正在使用的網(wǎng)絡(luò)層封裝庫(kù),即將開(kāi)源》),不過(guò)微信團(tuán)隊(duì)沒(méi)有失約,微信Mars 于2016年12月28日正式公開(kāi)源碼(源碼地址:https:" />

国产成人精品无码青草_亚洲国产美女精品久久久久∴_欧美人与鲁交大毛片免费_国产果冻豆传媒麻婆精东

15158846557 在線咨詢 在線咨詢
15158846557 在線咨詢
所在位置: 首頁(yè) > 營(yíng)銷(xiāo)資訊 > 網(wǎng)站運(yùn)營(yíng) > 如約而至:微信自用的移動(dòng)端IM網(wǎng)絡(luò)層跨平臺(tái)組件庫(kù)Mars已正式開(kāi)源

如約而至:微信自用的移動(dòng)端IM網(wǎng)絡(luò)層跨平臺(tái)組件庫(kù)Mars已正式開(kāi)源

時(shí)間:2022-08-07 08:54:01 | 來(lái)源:網(wǎng)站運(yùn)營(yíng)

時(shí)間:2022-08-07 08:54:01 來(lái)源:網(wǎng)站運(yùn)營(yíng)

1、前言

關(guān)于微信內(nèi)部正在使用的網(wǎng)絡(luò)層封裝庫(kù)Mars開(kāi)源的消息,1個(gè)多月前就已滿天飛(參見(jiàn)《微信Mars:微信內(nèi)部正在使用的網(wǎng)絡(luò)層封裝庫(kù),即將開(kāi)源》),不過(guò)微信團(tuán)隊(duì)沒(méi)有失約,微信Mars 于2016年12月28日正式公開(kāi)源碼(源碼地址:https://github.com/Tencent/mars,也可從本文文末的附件下載之,Android版演示程序可以從文末的附件中下載)。

之前無(wú)論是微信團(tuán)隊(duì)還是手機(jī)QQ團(tuán)隊(duì),都以騰訊公司的名義在Github開(kāi)源了數(shù)個(gè)工程,但這些工程所受的關(guān)注度遠(yuǎn)不及Mars。之所以Mars廣受關(guān)注的原因,其實(shí)搞移動(dòng)端IM或推送技術(shù)的開(kāi)發(fā)者同行都明白,因?yàn)橐苿?dòng)網(wǎng)絡(luò)實(shí)在太不可靠、太復(fù)雜,以至于寫(xiě)出一個(gè)能用于大規(guī)模用戶環(huán)境的穩(wěn)定、省流量、省電、數(shù)據(jù)傳輸流暢、弱網(wǎng)絡(luò)健壯、后臺(tái)自動(dòng)?;畹燃夹g(shù)指標(biāo)的IM或推送是相當(dāng)困難的。

更為重要的原因是畢竟微信Mars經(jīng)過(guò)微信團(tuán)隊(duì)多年積累并經(jīng)過(guò)海量用戶的測(cè)試和使用,是經(jīng)受的住各種復(fù)雜移動(dòng)端網(wǎng)絡(luò)環(huán)境、各種亂七八糟型號(hào)智能手機(jī)的真實(shí)考驗(yàn)的。若Mars開(kāi)源,必將為IM及相關(guān)技術(shù)應(yīng)用領(lǐng)域的同行帶來(lái)很多有價(jià)值的實(shí)踐成果,畢竟微信的體量和應(yīng)用規(guī)模決定了技術(shù)的高度,確實(shí)是值得同行學(xué)習(xí)和關(guān)注。

之前的文章,比如《微信移動(dòng)端應(yīng)對(duì)弱網(wǎng)絡(luò)情況的探索和實(shí)踐PPT》、《微信Mars:微信內(nèi)部正在使用的網(wǎng)絡(luò)層封裝庫(kù),即將開(kāi)源》,也都或多或少對(duì)Mars進(jìn)行了初步介紹,但微信Mars到底是個(gè)啥玩意,它能解決啥問(wèn)題?

我們簡(jiǎn)要的概括一下,微信Mars解決了如下問(wèn)題:

  1. 提供長(zhǎng)連、短連兩種網(wǎng)絡(luò)通道;
  2. 常規(guī)的網(wǎng)絡(luò)能力,例如 DNS 防劫持、動(dòng)態(tài) IP 下發(fā)、就近接入、容災(zāi)恢復(fù)等;
  3. 貼合移動(dòng)互聯(lián)網(wǎng)的網(wǎng)絡(luò)層解決方案;
  4. 貼合移動(dòng)終端的平臺(tái)特性:前后臺(tái)、活躍態(tài)、休眠、省電、省流量等。

以上特點(diǎn),還不盡于概括微信Mars的技術(shù)特征,建議對(duì)C++熟悉的IM或推送技術(shù)同行可以直接去看看Mars源碼。

那么微信Mars到底有什么用呢?毫無(wú)疑問(wèn),微信Mars存在的前提就是為了更好的服務(wù)微信這個(gè)超級(jí)IM而存在,最適合干的活就是開(kāi)發(fā)移動(dòng)端IM了,當(dāng)然由于提煉的很好,相信移動(dòng)端推送技術(shù)等都是可以使用微信Mars作為網(wǎng)絡(luò)層lib來(lái)使用,從而以微信的成果為起點(diǎn)開(kāi)發(fā)出擁有更加優(yōu)秀網(wǎng)絡(luò)體驗(yàn)的移動(dòng)端富網(wǎng)絡(luò)應(yīng)用。

好了,言歸正傳,本文正文內(nèi)容引用了微信開(kāi)發(fā)團(tuán)隊(duì)的資料,請(qǐng)繼續(xù)往下閱讀。(本文同步發(fā)布于:如約而至:微信自用的移動(dòng)端IM網(wǎng)絡(luò)層跨平臺(tái)組件庫(kù)Mars已正式開(kāi)源-IM開(kāi)發(fā)/專項(xiàng)技術(shù)區(qū) - 即時(shí)通訊開(kāi)發(fā)者社區(qū)!)

2、關(guān)聯(lián)文章

《移動(dòng)端IM實(shí)踐:實(shí)現(xiàn)Android版微信的智能心跳機(jī)制》

《微信Mars:微信內(nèi)部正在使用的網(wǎng)絡(luò)層封裝庫(kù),即將開(kāi)源》

《微信移動(dòng)端應(yīng)對(duì)弱網(wǎng)絡(luò)情況的探索和實(shí)踐PPT [附件下載]》

《微信異步化改造實(shí)踐:8億月活、單機(jī)千萬(wàn)連接背后的后臺(tái)解決方案》

3、微信Mars起源

2012 年中,微信支持包括 Android、iOS、Symbian 三個(gè)平臺(tái)。但在各個(gè)平臺(tái)上,微信客戶端沒(méi)有任何統(tǒng)一的基礎(chǔ)模塊。2012 年的微信正處于高速發(fā)展時(shí)期,各平臺(tái)的迭代速度不一、使用的編程語(yǔ)言各異,后臺(tái)架構(gòu)也處在不斷探索的過(guò)程中。多種因素使得各個(gè)平臺(tái)基礎(chǔ)模塊的實(shí)現(xiàn)出現(xiàn)了差異,導(dǎo)致出現(xiàn)多次需要服務(wù)器做兼容的善后工作。網(wǎng)絡(luò)作為微信的基礎(chǔ),重要性不言而喻。任何網(wǎng)絡(luò)實(shí)現(xiàn)的 bug 都可能導(dǎo)致重大事故。例如微信的容災(zāi)實(shí)現(xiàn),如果因?yàn)榘姹镜膶?shí)現(xiàn)差異,導(dǎo)致某些版本上無(wú)法進(jìn)行容災(zāi)恢復(fù),將會(huì)嚴(yán)重的影響用戶體驗(yàn),甚至造成用戶的流失。我們亟需一套統(tǒng)一的網(wǎng)絡(luò)基礎(chǔ)庫(kù),為微信的高速發(fā)展保駕護(hù)航。

恰好,這個(gè)時(shí)候塞班漸入日暮,微信對(duì)塞班的支持也逐漸減弱。老大從塞班組抽調(diào)人力,組成一個(gè)三人小 team 的初始團(tuán)隊(duì),開(kāi)始著手做通用的基礎(chǔ)組件。這個(gè)基礎(chǔ)組件最初就定位為:跨平臺(tái)、跨業(yè)務(wù)的基礎(chǔ)組件?,F(xiàn)在看,這個(gè)組件除了解決了已有問(wèn)題,還給微信的高速發(fā)展帶來(lái)了很多優(yōu)勢(shì),例如:


經(jīng)過(guò)四年多的發(fā)展,跨平臺(tái)的基礎(chǔ)組件已經(jīng)包含了網(wǎng)絡(luò)組件、日志組件在內(nèi)的多個(gè)組件。回頭看,這是一條開(kāi)荒路。

4、微信Mars設(shè)計(jì)原則

在基礎(chǔ)模塊的開(kāi)發(fā)中,設(shè)計(jì)尤為重要。在設(shè)計(jì)上,微信基礎(chǔ)組件以跨平臺(tái)、跨業(yè)務(wù)為前提,遵從高可用,高性能,負(fù)載均衡的設(shè)計(jì)原則。

可用是一個(gè)即時(shí)通訊類(lèi) App 的立身之本。高可用又體現(xiàn)在多個(gè)層面上:網(wǎng)絡(luò)的可用性、 App 的可用性、系統(tǒng)的可用性等。

[1] 網(wǎng)絡(luò)的可用性:

移動(dòng)互聯(lián)網(wǎng)有著丟包率高、帶寬受限、延遲波動(dòng)、第三方影響等特點(diǎn),使得網(wǎng)絡(luò)的可用性,尤其是弱網(wǎng)絡(luò)下的可用性變得尤為關(guān)鍵。Mars 的 STN 組件作為基于 socket 層的網(wǎng)絡(luò)解決方案,在很多細(xì)節(jié)設(shè)計(jì)上會(huì)充分考慮弱網(wǎng)絡(luò)下的可用性。

[2] App 的可用性:

App 的可用性包含穩(wěn)定性、運(yùn)行性能等多個(gè)方面。文章高性能日志模塊 xlog 描述了 xlog 在不影響 App 運(yùn)行性能的前提下進(jìn)行的大量設(shè)計(jì)思考。

[3] 系統(tǒng)的可用性:

除了考慮正常的使用場(chǎng)景,APP的設(shè)計(jì)還需要從整個(gè)系統(tǒng)的角度進(jìn)行設(shè)計(jì)思考。例如在容災(zāi)設(shè)計(jì)上,Mars 不僅使用了服務(wù)器容災(zāi)方案,也設(shè)計(jì)了客戶端的本地容災(zāi)。當(dāng)部分服務(wù)器出災(zāi)時(shí),目前微信可以做到,15min 內(nèi)把95%以上的用戶轉(zhuǎn)移到可用服務(wù)器上。

保障高可用并不代表可以犧牲性能,對(duì)于一個(gè)用戶使用最頻繁的應(yīng)用,反而更要對(duì)使用的資源精打細(xì)算。例如在 Mars 信令傳輸超時(shí)設(shè)計(jì)中,多級(jí)超時(shí)的設(shè)計(jì)充分的考慮了可用性與高性能之間的平衡取舍。

如果說(shuō)高可用高性能只是客戶端本身的考慮的話,負(fù)載均衡就需要結(jié)合服務(wù)器端來(lái)考慮了,做一個(gè)客戶端網(wǎng)絡(luò)永遠(yuǎn)不能只把眼光放在客戶端上。任何有關(guān)網(wǎng)絡(luò)訪問(wèn)的決策都要考慮給服務(wù)器所帶來(lái)的額外壓力是多大。為了選用質(zhì)量較好的 IP,曾經(jīng)寫(xiě)了完整的客戶端測(cè)速代碼,后來(lái)刪掉,其中一個(gè)原因是因?yàn)椴幌虢o服務(wù)器帶來(lái)額外的負(fù)擔(dān)。Mars 的代碼中,選擇 IP 時(shí)用了大量的隨機(jī)函數(shù)也是為了規(guī)避大量的用戶同時(shí)訪問(wèn)同一臺(tái)服務(wù)器而做的。

在這四年,我學(xué)到最多的就是簡(jiǎn)單和平衡。 把方案做的盡可能簡(jiǎn)單,這樣才不容易出錯(cuò)。設(shè)計(jì)方案時(shí)大多數(shù)時(shí)候都不可能滿足所有想達(dá)到的條件,這個(gè)時(shí)候就需要去平衡各個(gè)因素。在組件中一個(gè)很好的例子就是長(zhǎng)連接的連接頻率(具體實(shí)現(xiàn)見(jiàn)longlink_connect_monitor.cc),這個(gè)連接頻率就是綜合耗電量,流量,網(wǎng)絡(luò)高可用,用戶行為等因素進(jìn)行綜合考慮的。

5、Mars 的發(fā)展歷程

5.1 階段1:讓微信跑起來(lái)

跨平臺(tái)基礎(chǔ)組件的需求起源于微信,首要目標(biāo)當(dāng)然是先承載起微信業(yè)務(wù)。為了不局限于微信,滿足跨平臺(tái)、跨業(yè)務(wù)的設(shè)計(jì)目標(biāo),在設(shè)計(jì)上,網(wǎng)絡(luò)組件定位為客戶端與服務(wù)端之間的無(wú)狀態(tài)網(wǎng)絡(luò)信令通道,即交互方式主要包含一來(lái)一回、主動(dòng)push兩種方式。這使得基礎(chǔ)組件無(wú)需考慮請(qǐng)求間的關(guān)聯(lián)性、時(shí)序性,核心接口得到了極大的簡(jiǎn)化。同時(shí),簡(jiǎn)潔的交互也使得業(yè)務(wù)邏輯的耦合極少。目前基礎(chǔ)組件與業(yè)務(wù)的交互只包括:編解碼、auth狀態(tài)查詢兩部分(具體見(jiàn)stn_logic.h)。

voidStartTask(...);


intOnTaskEnd(...);

voidOnPush(...);

boolReq2Buf(...);

intBuf2Resp(...);

boolMakeSureAuthed();

在線程模型的選擇上,最早使用的是多線程模型。當(dāng)需要異步做一個(gè)工作,就起一個(gè)線程。多線程勢(shì)必少不了鎖。但當(dāng)灰度幾次之后發(fā)現(xiàn),想要規(guī)避死鎖的四個(gè)必要條件并沒(méi)有想象中的那么容易。用戶使用場(chǎng)景復(fù)雜,客戶端的時(shí)序、狀態(tài)的影響因素多,例如網(wǎng)絡(luò)切換事件、前后臺(tái)事件、定時(shí)器事件、網(wǎng)絡(luò)事件、任務(wù)事件等,導(dǎo)致了不少的死鎖現(xiàn)象和對(duì)象析構(gòu)時(shí)序錯(cuò)亂導(dǎo)致的內(nèi)存非法訪問(wèn)問(wèn)題。

這時(shí),我們開(kāi)始思考,多線程確實(shí)有它的優(yōu)點(diǎn):可以并發(fā)甚至并行提高運(yùn)行速度。但是對(duì)于網(wǎng)絡(luò)模塊來(lái)說(shuō),性能瓶頸主要是在網(wǎng)絡(luò)耗時(shí)上,并不在于本地程序執(zhí)行速度上。那為何不把大部分程序執(zhí)行改成串行的,這樣就不會(huì)存在多線程臨界區(qū)的問(wèn)題,無(wú)鎖自然就不會(huì)死鎖。

因此,我們目前使用了消息隊(duì)列的方案(具體實(shí)現(xiàn)見(jiàn)comm/messagequeue目錄),把絕大多數(shù)非阻塞操作放到消息隊(duì)列里執(zhí)行。并且規(guī)定,基礎(chǔ)組件與調(diào)用方之間的交互必須1. 盡快完成,不進(jìn)行任何阻塞操作;2. 單向調(diào)用,避免形成環(huán)狀的復(fù)雜時(shí)序。消息隊(duì)列的引入很好的改善了死鎖問(wèn)題,但消息隊(duì)列的線程模型中,我們還是不能避免存在需要阻塞的調(diào)用,例如網(wǎng)絡(luò)操作。在未來(lái)的嘗試中,我們計(jì)劃引入?yún)f(xié)程的方式,將線程模型盡可能的簡(jiǎn)化。

在其它技術(shù)選型上,有時(shí)甚至需要細(xì)節(jié)到API 的使用,比如考慮平臺(tái)兼容性問(wèn)題,舍棄了一些函數(shù)的線程安全版本,使用了 asctime、localtime、rand 等非線程安全的版本。

5.2 階段2:修煉內(nèi)功

在多次的灰度驗(yàn)證、數(shù)據(jù)比對(duì)下,微信各平臺(tái)的網(wǎng)絡(luò)邏輯順利的過(guò)渡到了統(tǒng)一基礎(chǔ)組件。為了有效的驗(yàn)證組件的效果,我們開(kāi)發(fā)了 smc 的統(tǒng)計(jì)監(jiān)控組件,開(kāi)始關(guān)注網(wǎng)絡(luò)的各項(xiàng)指標(biāo),進(jìn)行網(wǎng)絡(luò)基礎(chǔ)研究與優(yōu)化,尤其是關(guān)注移動(dòng)網(wǎng)絡(luò)的特征。

基礎(chǔ)網(wǎng)絡(luò)優(yōu)化:常規(guī)的網(wǎng)絡(luò)能力,例如 DNS 防劫持、動(dòng)態(tài) IP 下發(fā)、就近接入、容災(zāi)恢復(fù)等,在這一階段得到逐步的建設(shè)與完善。除此之外,Mars 的網(wǎng)絡(luò)模塊是基于 socket 層的網(wǎng)絡(luò)解決方案,在缺失大而全的 HTTP 能力的同時(shí),卻可以將優(yōu)化做到更細(xì)致,細(xì)致到連接策略、連接超時(shí)、多級(jí)讀寫(xiě)超時(shí)、收發(fā)策略等每個(gè)網(wǎng)絡(luò)過(guò)程中。例如,當(dāng)遇到弱網(wǎng)絡(luò)下連通率較低,或者某些連通率不好的的服務(wù)器影響使用時(shí),我們使用了復(fù)合連接(代碼見(jiàn)complexconnect.cc)和 IP 排序(代碼見(jiàn)simple_ipport_sort.cc)的方案很好的應(yīng)對(duì)這兩個(gè)問(wèn)題。

平臺(tái)特性優(yōu)化:雖然 Mars 是跨平臺(tái)的基礎(chǔ)組件,但在很多設(shè)計(jì)上是需要結(jié)合各平臺(tái)的特性的。例如為了盡量減少頻繁的喚醒手機(jī),引入了智能心跳(詳見(jiàn)《移動(dòng)端IM實(shí)踐:實(shí)現(xiàn)Android版微信的智能心跳機(jī)制》),并且在智能心跳中考慮了 Android 的 alarm 對(duì)齊特性(具體實(shí)現(xiàn)見(jiàn)smart_heartbeat.cc)。再如在網(wǎng)絡(luò)切換時(shí),為了平滑切換的過(guò)程,使用了 iOS 中網(wǎng)絡(luò)的特性,在 iOS 中做了延遲處理等。

移動(dòng)特性優(yōu)化:微信的使用場(chǎng)景大部分是在手機(jī)端進(jìn)行使用,在組件的設(shè)計(jì)過(guò)程中,我們也會(huì)研究移動(dòng)設(shè)備的特性,并進(jìn)行結(jié)合優(yōu)化。例如,結(jié)合移動(dòng)設(shè)備的無(wú)線電資源控制器(RRC)的狀態(tài)切換,對(duì)一些性能要求特別特別敏感的請(qǐng)求,進(jìn)行提前激活的優(yōu)化處理等。

5.3 階段3:“抓妖記”

基礎(chǔ)組件全量上線微信后,以微信的用戶量,當(dāng)然也會(huì)遇到各種各樣的“妖”。例如,寫(xiě)網(wǎng)絡(luò)程序躲不開(kāi)運(yùn)營(yíng)商。印象比較深刻的某地的用戶反饋連接 WiFi 時(shí),微信不可用,后來(lái) tcpdump 發(fā)現(xiàn),當(dāng)包的大小超過(guò)一定大小后就發(fā)不出去。解決方案:在 WiFi 網(wǎng)絡(luò)下強(qiáng)制把 MSS 改為1400(代碼見(jiàn)unix_socket.cc)。

做移動(dòng)客戶端更避不開(kāi)手機(jī)廠商。一次遇到了一個(gè)百思不得其解的 crash,堆棧如下:

#00pc0x43e50/system/lib/libc.so (???)

#01pc0x3143/system/vendor/lib/libvendorconn.so (handleDpmIpcReq+154)

#02pc0x2f6d/system/vendor/lib/libvendorconn.so (send_ipc_req+276)

#03pc0x30ff/system/vendor/lib/libcneconn.so (connect+438)

看堆棧結(jié)合程序 xlog 分析,非阻塞 socket 卡在了 connect 函數(shù)里超過(guò)了6 min, 被我們自帶的 anr 檢測(cè)(代碼見(jiàn)http://anr.cc)發(fā)現(xiàn)然后自殺。最后實(shí)在束手無(wú)策,聯(lián)系廠商一起排查,最終查明原因:為了省電,當(dāng)手機(jī)鎖屏?xí)r連的不是 WiFi 且又沒(méi)有下行網(wǎng)絡(luò)數(shù)據(jù)時(shí),芯片 gate 會(huì)關(guān)閉,block 住所有網(wǎng)絡(luò)請(qǐng)求,直到有下行數(shù)據(jù)或者超過(guò) 20min 才會(huì)放開(kāi)。當(dāng)手機(jī)有網(wǎng)絡(luò)即使是手機(jī)網(wǎng)絡(luò)的情況下,很難沒(méi)有下行數(shù)據(jù),所以基本不會(huì)觸發(fā)組件自帶的 anr 檢測(cè),但當(dāng)手機(jī)沒(méi)連接任何網(wǎng)絡(luò)時(shí),就很容易觸發(fā)。解決方案:廠商修改代碼邏輯,當(dāng)沒(méi)有任何網(wǎng)絡(luò)時(shí)不 block 網(wǎng)絡(luò)請(qǐng)求。

運(yùn)營(yíng)商和手機(jī)廠商對(duì)我們來(lái)說(shuō)已經(jīng)是一個(gè)黑盒,但其實(shí)也遇到過(guò)更黑的黑盒。當(dāng)手機(jī)長(zhǎng)時(shí)間不重啟,有極小概率不能繼續(xù)使用微信,重啟手機(jī)會(huì)恢復(fù)。但因?yàn)橐恢闭也坏揭粋€(gè)愿意配合我們又滿足條件的用戶,導(dǎo)致這個(gè)問(wèn)題很長(zhǎng)一段時(shí)間內(nèi)都沒(méi)有任何進(jìn)展,最終偶然一個(gè)機(jī)會(huì),在一臺(tái)測(cè)試機(jī)器上重現(xiàn)了該問(wèn)題,tcpdump 發(fā)現(xiàn)在三步握手階段,服務(wù)器帶回的客戶端帶過(guò)去的 tsval 字段被篡改,導(dǎo)致三步握手直接失敗,而且這個(gè)篡改發(fā)生在離開(kāi)服務(wù)器之后到達(dá)客戶端之前。

這個(gè)問(wèn)題是微信網(wǎng)絡(luò)模塊中排查時(shí)間最長(zhǎng)也是花費(fèi)精力最多的一個(gè)問(wèn)題,不僅因?yàn)楹荛L(zhǎng)一段時(shí)間內(nèi)無(wú)案例可分析,也因?yàn)樵谥噩F(xiàn)后,聯(lián)系了大量的同事和外部有關(guān)人的幫忙,想排查出罪魁禍?zhǔn)住5驗(yàn)橹虚g涉及的環(huán)節(jié)和運(yùn)營(yíng)商相關(guān)部門(mén)過(guò)多,無(wú)法繼續(xù)排查下去,最終也沒(méi)找到根本原因。 解決辦法:服務(wù)器更改 net.ipv4.tcp_timestamps = 0。

這段時(shí)間是痛并快樂(lè)著,見(jiàn)識(shí)到了各種極差的網(wǎng)絡(luò),才切膚感受到移動(dòng)網(wǎng)絡(luò)環(huán)境的惡劣程度,但看著我們的網(wǎng)絡(luò)性能數(shù)據(jù)在穩(wěn)步提升又有種滿足感。截止到今天,已經(jīng)很少有真正的網(wǎng)絡(luò)問(wèn)題需要跟進(jìn)了。這也是我們能有時(shí)間開(kāi)始把這些代碼開(kāi)源出去的很大的一個(gè)原因。

6、為了更好地開(kāi)源Mars,微信團(tuán)隊(duì)做了這些前期工作

大概一年前(大約2015年10月),我們開(kāi)始有想法把基礎(chǔ)組件開(kāi)源出去,當(dāng)時(shí)大家都在糾結(jié)叫什么名字好呢?此時(shí)恰逢《火星救援》正在熱映,一位同事說(shuō)干脆叫 Mars 吧,于是就定下來(lái)叫了 Mars??戳丝创a,發(fā)現(xiàn)想要開(kāi)源出去可能還是需要做一些其他工作的。

6.1 代碼重構(gòu)

首先,代碼風(fēng)格方面,因?yàn)樽畛跷覀兪褂梦募?、函?shù)名、變量名的規(guī)則是內(nèi)部定義的規(guī)則,為了能讓其他人讀起來(lái)更舒心,我們決定把代碼風(fēng)格改為谷歌風(fēng)格,比如:變量名一律小寫(xiě), 單詞之間用下劃線連接;左大括號(hào)不換行等等。但是為了更好的區(qū)分訪問(wèn)空間,我們又在谷歌代碼風(fēng)格進(jìn)行了一些變通,比如:私有函數(shù)全部是”__”開(kāi)頭;函數(shù)參數(shù)全部以”_”開(kāi)頭 等等。

其次,雖然最初的設(shè)計(jì)一直是秉承著業(yè)務(wù)性無(wú)關(guān)的設(shè)計(jì),但在實(shí)際開(kāi)發(fā)過(guò)程中仍然難免帶上了微信的業(yè)務(wù)性相關(guān)代碼,比較典型的就是 newdns 。為了 Mars 以后的維護(hù)以及保證開(kāi)源出去代碼的同源,在開(kāi)源出去之前必須把這些業(yè)務(wù)性有關(guān)的代碼抽離出來(lái),抽離后的結(jié)構(gòu)如下:


最后,為了接口更易用,對(duì)調(diào)用接口以及回調(diào)接口的參數(shù)也進(jìn)行了反復(fù)思考與修改。

6.2 編譯優(yōu)化

在 Mars之前,是直接給 Android 提供動(dòng)態(tài)庫(kù)(.so),因?yàn)榇a邏輯都已經(jīng)固定,不需要有可定制的部分。給 Apple 系平臺(tái)提供靜態(tài)庫(kù)(.a),因?yàn)閷?duì)外暴露的函數(shù)幾乎不會(huì)改變,直接把相應(yīng)的頭文件放到相應(yīng)的項(xiàng)目里就行。但對(duì)外開(kāi)源就完全不一樣了:日志的加密算法可能別人需要自己實(shí)現(xiàn);長(zhǎng)連或者短連的包頭有人需要自己定制;對(duì)外接口的頭文件我們可能會(huì)修改……

為了讓使用者可定制代碼,對(duì)于編譯 Android 平臺(tái)我們提供了兩種選擇:

  1. 動(dòng)態(tài)庫(kù)。有些可能需要定制的代碼都提供了默認(rèn)實(shí)現(xiàn)。
  2. 先編譯靜態(tài)庫(kù),再編譯動(dòng)態(tài)庫(kù)。

編譯出來(lái)靜態(tài)庫(kù)后,實(shí)現(xiàn)自己需要定制的代碼后,執(zhí)行 ndk-build 后即可編譯出來(lái)動(dòng)態(tài)庫(kù)。 對(duì)于 Apple 系平臺(tái),把頭文件全部收攏為 Mars 維護(hù),直接編譯出 Framework。

為了能讓開(kāi)發(fā)者快速的入門(mén),我們提供了 Android、iOS、OS X 平臺(tái)的 demo(微信開(kāi)源Mars的Demo源碼點(diǎn)此進(jìn)入),其他平臺(tái)的編譯和 demo 會(huì)在不久就加上支持。


▲ 成型的 Mars 結(jié)構(gòu)圖如上圖所示

6.3 同類(lèi)技術(shù)橫向?qū)Ρ?/b>

我們做的一直都不是滿足所有需求的組件,只是做了一個(gè)更適合我們使用的組件,這里也列了下和同類(lèi)型的開(kāi)源代碼的對(duì)比。

可以看出:

  1. Mars 中包括一個(gè)完整的高性能的日志組件 xlog;
  2. Mars 中 STN 是一個(gè)跨平臺(tái)的 socket 層解決方案,并不支持完整的 HTTP 協(xié)議;
  3. Mars 中 STN 模塊是更加貼合“移動(dòng)互聯(lián)網(wǎng)”、“移動(dòng)平臺(tái)”特性的網(wǎng)絡(luò)解決方案,尤其針對(duì)弱網(wǎng)絡(luò)、平臺(tái)特性等有很多的相關(guān)優(yōu)化策略。

總的來(lái)說(shuō),Mars 是一個(gè)結(jié)合移動(dòng) App 所設(shè)計(jì)的基于 socket 層的解決方案,在網(wǎng)絡(luò)調(diào)優(yōu)方面有更好的可控性,對(duì)于 HTTP 完整協(xié)議的支持,已經(jīng)考慮后續(xù)版本會(huì)加入。

6.4 Mars開(kāi)源源碼結(jié)構(gòu)


7、獲取Mars的演示Demo(Sample)

7.1 下載和安裝

試用 Android Demo 請(qǐng)從文末的附件下載之,iOS sample 請(qǐng)通過(guò)Mars的Github倉(cāng)庫(kù)編譯獲得(或文末的附件下載源碼)。

7.2 Mars Android版演示程序截圖


7.3 Mars iOS版演示程序源碼截圖


8、本文小結(jié)

經(jīng)常有朋友和我說(shuō):發(fā)現(xiàn)網(wǎng)絡(luò)信號(hào)差的時(shí)候或者其他應(yīng)用不能用的時(shí)候,微信仍然能發(fā)出去消息。不知不覺(jué)我們好像什么都沒(méi)做,回頭看,原來(lái)我們已經(jīng)做了這么多。

我想,并不是任何一行代碼都可以經(jīng)歷日活躍5億用戶的考驗(yàn),感謝微信給我們提供了這么一個(gè)平臺(tái)?,F(xiàn)在我們想把這些代碼和你們分享,運(yùn)營(yíng)方式上 Mars 所開(kāi)源出去的代碼會(huì)和微信所用的代碼保持同源,所有開(kāi)源出去的代碼也首先會(huì)在微信上驗(yàn)證通過(guò)后再公開(kāi)。

開(kāi)源并不是結(jié)束,只是開(kāi)始。我們后續(xù)仍然會(huì)繼續(xù)探索在移動(dòng)互聯(lián)網(wǎng)下的網(wǎng)絡(luò)優(yōu)化。Talk is cheap,show you our code。

(本文同步發(fā)布于:如約而至:微信自用的移動(dòng)端IM網(wǎng)絡(luò)層跨平臺(tái)組件庫(kù)Mars已正式開(kāi)源-IM開(kāi)發(fā)/專項(xiàng)技術(shù)區(qū) - 即時(shí)通訊開(kāi)發(fā)者社區(qū)!,本文引用了微信團(tuán)隊(duì)原創(chuàng)文章:原始文字點(diǎn)此進(jìn)入)

9、更多IM技術(shù)資料

[1] 網(wǎng)絡(luò)編程基礎(chǔ)資料:

《TCP/IP詳解-第11章·UDP:用戶數(shù)據(jù)報(bào)協(xié)議》

《TCP/IP詳解-第17章·TCP:傳輸控制協(xié)議》

《TCP/IP詳解-第18章·TCP連接的建立與終止》

《TCP/IP詳解-第21章·TCP的超時(shí)與重傳》

《技術(shù)往事:改變世界的TCP/IP協(xié)議(珍貴多圖、手機(jī)慎點(diǎn))》

《通俗易懂-深入理解TCP協(xié)議(上):理論基礎(chǔ)》

《通俗易懂-深入理解TCP協(xié)議(下):RTT、滑動(dòng)窗口、擁塞處理》

《理論經(jīng)典:TCP協(xié)議的3次握手與4次揮手過(guò)程詳解》

《理論聯(lián)系實(shí)際:Wireshark抓包分析TCP 3次握手、4次揮手過(guò)程》

《計(jì)算機(jī)網(wǎng)絡(luò)通訊協(xié)議關(guān)系圖(中文珍藏版)》

《UDP中一個(gè)包的大小最大能多大?》

《Java新一代網(wǎng)絡(luò)編程模型AIO原理及Linux系統(tǒng)AIO介紹》

《NIO框架入門(mén)(一):服務(wù)端基于Netty4的UDP雙向通信Demo演示》

《NIO框架入門(mén)(二):服務(wù)端基于MINA2的UDP雙向通信Demo演示》

《NIO框架入門(mén)(三):iOS與MINA2、Netty4的跨平臺(tái)UDP雙向通信實(shí)戰(zhàn)》

《NIO框架入門(mén)(四):Android與MINA2、Netty4的跨平臺(tái)UDP雙向通信實(shí)戰(zhàn)》

《P2P技術(shù)詳解(一):NAT詳解——詳細(xì)原理、P2P簡(jiǎn)介》

《P2P技術(shù)詳解(二):P2P中的NAT穿越(打洞)方案詳解》

《P2P技術(shù)詳解(三):P2P技術(shù)之STUN、TURN、ICE詳解》

《高性能網(wǎng)絡(luò)編程(一):?jiǎn)闻_(tái)服務(wù)器并發(fā)TCP連接數(shù)到底可以有多少》

《高性能網(wǎng)絡(luò)編程(二):上一個(gè)10年,著名的C10K并發(fā)連接問(wèn)題》

《高性能網(wǎng)絡(luò)編程(三):下一個(gè)10年,是時(shí)候考慮C10M并發(fā)問(wèn)題了》

《高性能網(wǎng)絡(luò)編程(四):從C10K到C10M高性能網(wǎng)絡(luò)應(yīng)用的理論探索》

>>更多同類(lèi)文章 ……

[2] 有關(guān)IM/推送的通信格式、協(xié)議的選擇:

《為什么QQ用的是UDP協(xié)議而不是TCP協(xié)議?》

《移動(dòng)端即時(shí)通訊協(xié)議選擇:UDP還是TCP?》

《如何選擇即時(shí)通訊應(yīng)用的數(shù)據(jù)傳輸格式》

《強(qiáng)列建議將Protobuf作為你的即時(shí)通訊應(yīng)用數(shù)據(jù)傳輸格式》

《移動(dòng)端IM開(kāi)發(fā)需要面對(duì)的技術(shù)問(wèn)題(含通信協(xié)議選擇)》

《簡(jiǎn)述移動(dòng)端IM開(kāi)發(fā)的那些坑:架構(gòu)設(shè)計(jì)、通信協(xié)議和客戶端》

《理論聯(lián)系實(shí)際:一套典型的IM通信協(xié)議設(shè)計(jì)詳解》

《58到家實(shí)時(shí)消息系統(tǒng)的協(xié)議設(shè)計(jì)等技術(shù)實(shí)踐分享》

>>更多同類(lèi)文章 ……

[3] 有關(guān)IM/推送的心跳?;钐幚恚?/b>

《Android進(jìn)程?;钤斀猓阂黄恼陆鉀Q你的所有疑問(wèn)》

《Android端消息推送總結(jié):實(shí)現(xiàn)原理、心跳?;?、遇到的問(wèn)題等》

《為何基于TCP協(xié)議的移動(dòng)端IM仍然需要心跳?;顧C(jī)制?》

《微信團(tuán)隊(duì)原創(chuàng)分享:Android版微信后臺(tái)保活實(shí)戰(zhàn)分享(進(jìn)程?;钇?》

《微信團(tuán)隊(duì)原創(chuàng)分享:Android版微信后臺(tái)?;顚?shí)戰(zhàn)分享(網(wǎng)絡(luò)?;钇?》

《移動(dòng)端IM實(shí)踐:實(shí)現(xiàn)Android版微信的智能心跳機(jī)制》

《移動(dòng)端IM實(shí)踐:WhatsApp、Line、微信的心跳策略分析》

>>更多同類(lèi)文章 ……

[4] 有關(guān)WEB端即時(shí)通訊開(kāi)發(fā):

《新手入門(mén)貼:史上最全Web端即時(shí)通訊技術(shù)原理詳解》

《Web端即時(shí)通訊技術(shù)盤(pán)點(diǎn):短輪詢、Comet、Websocket、SSE》

《SSE技術(shù)詳解:一種全新的HTML5服務(wù)器推送事件技術(shù)》

《Comet技術(shù)詳解:基于HTTP長(zhǎng)連接的Web端實(shí)時(shí)通信技術(shù)》

《WebSocket詳解(一):初步認(rèn)識(shí)WebSocket技術(shù)》

《socket.io實(shí)現(xiàn)消息推送的一點(diǎn)實(shí)踐及思路》

《LinkedIn的Web端即時(shí)通訊實(shí)踐:實(shí)現(xiàn)單機(jī)幾十萬(wàn)條長(zhǎng)連接》

>>更多同類(lèi)文章 ……

[5] 有關(guān)IM架構(gòu)設(shè)計(jì):

《淺談IM系統(tǒng)的架構(gòu)設(shè)計(jì)》

《簡(jiǎn)述移動(dòng)端IM開(kāi)發(fā)的那些坑:架構(gòu)設(shè)計(jì)、通信協(xié)議和客戶端》

《一套原創(chuàng)分布式即時(shí)通訊(IM)系統(tǒng)理論架構(gòu)方案》

《從零到卓越:京東客服即時(shí)通訊系統(tǒng)的技術(shù)架構(gòu)演進(jìn)歷程》

《蘑菇街即時(shí)通訊/IM服務(wù)器開(kāi)發(fā)之架構(gòu)選擇》

《騰訊QQ1.4億在線用戶的技術(shù)挑戰(zhàn)和架構(gòu)演進(jìn)之路PPT》

《微信技術(shù)總監(jiān)談架構(gòu):微信之道——大道至簡(jiǎn)(演講全文)》

《如何解讀《微信技術(shù)總監(jiān)談架構(gòu):微信之道——大道至簡(jiǎn)》》

《快速裂變:見(jiàn)證微信強(qiáng)大后臺(tái)架構(gòu)從0到1的演進(jìn)歷程(一)》

《17年的實(shí)踐:騰訊海量產(chǎn)品的技術(shù)方法論》

>>更多同類(lèi)文章 ……

[6] 有關(guān)IM安全的文章:

《即時(shí)通訊安全篇(一):正確地理解和使用Android端加密算法》

《即時(shí)通訊安全篇(二):探討組合加密算法在IM中的應(yīng)用》

《即時(shí)通訊安全篇(三):常用加解密算法與通訊安全講解》

《即時(shí)通訊安全篇(四):實(shí)例分析Android中密鑰硬編碼的風(fēng)險(xiǎn)》

《即時(shí)通訊安全篇(五):對(duì)稱加密技術(shù)在Android平臺(tái)上的應(yīng)用實(shí)踐》

《即時(shí)通訊安全篇(六):非對(duì)稱加密技術(shù)的原理與應(yīng)用實(shí)踐》

《傳輸層安全協(xié)議SSL/TLS的Java平臺(tái)實(shí)現(xiàn)簡(jiǎn)介和Demo演示》

《理論聯(lián)系實(shí)際:一套典型的IM通信協(xié)議設(shè)計(jì)詳解(含安全層設(shè)計(jì))》

《微信新一代通信安全解決方案:基于TLS1.3的MMTLS詳解》

《來(lái)自阿里OpenIM:打造安全可靠即時(shí)通訊服務(wù)的技術(shù)實(shí)踐分享》

>>更多同類(lèi)文章 ……

[7] 有關(guān)實(shí)時(shí)音視頻開(kāi)發(fā):

《即時(shí)通訊音視頻開(kāi)發(fā)(一):視頻編解碼之理論概述》

《即時(shí)通訊音視頻開(kāi)發(fā)(二):視頻編解碼之?dāng)?shù)字視頻介紹》

《即時(shí)通訊音視頻開(kāi)發(fā)(三):視頻編解碼之編碼基礎(chǔ)》

《即時(shí)通訊音視頻開(kāi)發(fā)(四):視頻編解碼之預(yù)測(cè)技術(shù)介紹》

《即時(shí)通訊音視頻開(kāi)發(fā)(五):認(rèn)識(shí)主流視頻編碼技術(shù)H.264》

《即時(shí)通訊音視頻開(kāi)發(fā)(六):如何開(kāi)始音頻編解碼技術(shù)的學(xué)習(xí)》

《即時(shí)通訊音視頻開(kāi)發(fā)(七):音頻基礎(chǔ)及編碼原理入門(mén)》

《即時(shí)通訊音視頻開(kāi)發(fā)(八):常見(jiàn)的實(shí)時(shí)語(yǔ)音通訊編碼標(biāo)準(zhǔn)》

《即時(shí)通訊音視頻開(kāi)發(fā)(九):實(shí)時(shí)語(yǔ)音通訊的回音及回音消除概述》

《即時(shí)通訊音視頻開(kāi)發(fā)(十):實(shí)時(shí)語(yǔ)音通訊的回音消除技術(shù)詳解》

《即時(shí)通訊音視頻開(kāi)發(fā)(十一):實(shí)時(shí)語(yǔ)音通訊丟包補(bǔ)償技術(shù)詳解》

《即時(shí)通訊音視頻開(kāi)發(fā)(十二):多人實(shí)時(shí)音視頻聊天架構(gòu)探討》

《即時(shí)通訊音視頻開(kāi)發(fā)(十三):實(shí)時(shí)視頻編碼H.264的特點(diǎn)與優(yōu)勢(shì)》

《即時(shí)通訊音視頻開(kāi)發(fā)(十四):實(shí)時(shí)音視頻數(shù)據(jù)傳輸協(xié)議介紹》

《即時(shí)通訊音視頻開(kāi)發(fā)(十五):聊聊P2P與實(shí)時(shí)音視頻的應(yīng)用情況》

《即時(shí)通訊音視頻開(kāi)發(fā)(十六):移動(dòng)端實(shí)時(shí)音視頻開(kāi)發(fā)的幾個(gè)建議》

《即時(shí)通訊音視頻開(kāi)發(fā)(十七):視頻編碼H.264、V8的前世今生》

《網(wǎng)易視頻云技術(shù)分享:音頻處理與壓縮技術(shù)快速入門(mén)》

《學(xué)習(xí)RFC3550:RTP/RTCP實(shí)時(shí)傳輸協(xié)議基礎(chǔ)知識(shí)》

《簡(jiǎn)述開(kāi)源實(shí)時(shí)音視頻技術(shù)WebRTC的優(yōu)缺點(diǎn)》

《良心分享:WebRTC 零基礎(chǔ)開(kāi)發(fā)者教程(中文)》

《開(kāi)源實(shí)時(shí)音視頻技術(shù)WebRTC中RTP/RTCP數(shù)據(jù)傳輸協(xié)議的應(yīng)用》

《基于RTMP數(shù)據(jù)傳輸協(xié)議的實(shí)時(shí)流媒體技術(shù)研究(論文全文)》

《聲網(wǎng)架構(gòu)師談實(shí)時(shí)音視頻云的實(shí)現(xiàn)難點(diǎn)(視頻采訪)》

《淺談開(kāi)發(fā)實(shí)時(shí)視頻直播平臺(tái)的技術(shù)要點(diǎn)》

《還在靠“喂喂喂”測(cè)試實(shí)時(shí)語(yǔ)音通話質(zhì)量?本文教你科學(xué)的評(píng)測(cè)方法!》

《實(shí)現(xiàn)延遲低于500毫秒的1080P實(shí)時(shí)音視頻直播的實(shí)踐分享》

《移動(dòng)端實(shí)時(shí)視頻直播技術(shù)實(shí)踐:如何做到實(shí)時(shí)秒開(kāi)、流暢不卡》

《如何用最簡(jiǎn)單的方法測(cè)試你的實(shí)時(shí)音視頻方案》

《技術(shù)揭秘:支持百萬(wàn)級(jí)粉絲互動(dòng)的Facebook實(shí)時(shí)視頻直播》

>>更多同類(lèi)文章 ……

[8] IM開(kāi)發(fā)綜合文章:

《移動(dòng)端IM開(kāi)發(fā)需要面對(duì)的技術(shù)問(wèn)題》

《開(kāi)發(fā)IM是自己設(shè)計(jì)協(xié)議用字節(jié)流好還是字符流好?》

《請(qǐng)問(wèn)有人知道語(yǔ)音留言聊天的主流實(shí)現(xiàn)方式嗎?》

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

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

《談?wù)勔苿?dòng)端 IM 開(kāi)發(fā)中登錄請(qǐng)求的優(yōu)化》

《完全自已開(kāi)發(fā)的IM該如何設(shè)計(jì)“失敗重試”機(jī)制?》

《微信對(duì)網(wǎng)絡(luò)影響的技術(shù)試驗(yàn)及分析(論文全文)》

《即時(shí)通訊系統(tǒng)的原理、技術(shù)和應(yīng)用(技術(shù)論文)》

《開(kāi)源IM工程“蘑菇街TeamTalk”的現(xiàn)狀:一場(chǎng)有始無(wú)終的開(kāi)源秀》

《騰訊原創(chuàng)分享(一):如何大幅提升移動(dòng)網(wǎng)絡(luò)下手機(jī)QQ的圖片傳輸速度和成功率》

《如約而至:微信自用的移動(dòng)端IM網(wǎng)絡(luò)層跨平臺(tái)組件庫(kù)Mars已正式開(kāi)源》

>>更多同類(lèi)文章 ……

[9] 開(kāi)源移動(dòng)端IM技術(shù)框架資料:

《開(kāi)源移動(dòng)端IM技術(shù)框架MobileIMSDK:快速入門(mén)》

《開(kāi)源移動(dòng)端IM技術(shù)框架MobileIMSDK:常見(jiàn)問(wèn)題解答》

《開(kāi)源移動(dòng)端IM技術(shù)框架MobileIMSDK:壓力測(cè)試報(bào)告》

>>更多同類(lèi)文章 ……

[10] 有關(guān)推送技術(shù)的文章:

《iOS的推送服務(wù)APNs詳解:設(shè)計(jì)思路、技術(shù)原理及缺陷等》

《Android端消息推送總結(jié):實(shí)現(xiàn)原理、心跳?;?、遇到的問(wèn)題等》

《掃盲貼:認(rèn)識(shí)MQTT通信協(xié)議》

《一個(gè)基于MQTT通信協(xié)議的完整Android推送Demo》

《IBM技術(shù)經(jīng)理訪談:MQTT協(xié)議的制定歷程、發(fā)展現(xiàn)狀等》

《求教android消息推送:GCM、XMPP、MQTT三種方案的優(yōu)劣》

《移動(dòng)端實(shí)時(shí)消息推送技術(shù)淺析》

《掃盲貼:淺談iOS和Android后臺(tái)實(shí)時(shí)消息推送的原理和區(qū)別》

《絕對(duì)干貨:基于Netty實(shí)現(xiàn)海量接入的推送服務(wù)技術(shù)要點(diǎn)》

《移動(dòng)端IM實(shí)踐:谷歌消息推送服務(wù)(GCM)研究(來(lái)自微信)》

《為何微信、QQ這樣的IM工具不使用GCM服務(wù)推送消息?》

《極光推送系統(tǒng)大規(guī)模高并發(fā)架構(gòu)的技術(shù)實(shí)踐分享》

《從HTTP到MQTT:一個(gè)基于位置服務(wù)的APP數(shù)據(jù)通信實(shí)踐概述》

>>更多同類(lèi)文章 ……

[11] 更多即時(shí)通訊技術(shù)好文分類(lèi):

淘帖 - 即時(shí)通訊開(kāi)發(fā)者社區(qū)!


作者:Jack Jiang(點(diǎn)擊作者姓名進(jìn)入Github)

出處:JackJiang的空間 - 即時(shí)通訊開(kāi)發(fā)者社區(qū)!

交流:歡迎加入即時(shí)通訊開(kāi)發(fā)交流群215891622

討論:即時(shí)通訊網(wǎng) - 即時(shí)通訊開(kāi)發(fā)者社區(qū)!

Jack Jiang同時(shí)是【開(kāi)源原創(chuàng)Java Swing外觀工程BeautyEye】和【開(kāi)源輕量級(jí)移動(dòng)端即時(shí)通訊框架MobileIMSDK】的作者,可前往下載交流。

關(guān)鍵詞:平臺(tái),正式,網(wǎng)絡(luò),移動(dòng)

74
73
25
news
  • 網(wǎng)站
  • 營(yíng)銷(xiāo)
  • 設(shè)計(jì)
  • 運(yùn)營(yíng)
  • 優(yōu)化
  • 效率
  • 專注
  • 電商
  • 方案
  • 推廣
為了最佳展示效果,本站不支持IE9及以下版本的瀏覽器,建議您使用谷歌Chrome瀏覽器。 點(diǎn)擊下載Chrome瀏覽器
關(guān)閉