1. 程式人生 > >【乾貨】阿里資深無線技術專家孫兵談閒魚社群技術架構演進

【乾貨】阿里資深無線技術專家孫兵談閒魚社群技術架構演進

近期在ArchSummit北京會議上,阿里巴巴資深無線技術專家孫兵(花名酒丐)發表了《網格社群-閒魚技術架構演講》主題演講。孫兵2011年加入阿里巴巴,先後在B2B、淘寶、手機淘寶等部門負責過會員、物流、O2O、導購等系統的架構和研發;目前擔任阿里創新業務閒魚的技術負責人,負責產品的技術研發工作。他從技術負責人的視角來分享閒魚社群的技術架構演變歷程,以及在這個過程中不同階段把握不同重點,通過技術驅動社群架構建立與發展,並且就每個階段的具體實踐給大家帶來精彩的例項分享。

 640?wx_fmt=png
演講全文:

孫兵:非常感謝主持人的介紹。不太習慣北京熱情的霧霾,所以可能講的不那麼好,大家將就著聽。簡單自我介紹一下,我是2011年加入阿里,在阿里五年多的時間經歷了很多業務,開始從會員到物流、從物流到手機淘寶,然後是閒魚,現在我的位置其實是閒魚的技術負責人。一開始我給大家講一下,作為一個架構師,關於驅動你每天工作的願景或者說是使命的問題,或者說這只是一個工作。架構師每天的工作是做架構,架構我們會說要有原則,要有目的,要有解決的問題。但是實際上來說,驅動你去做這些事情真正的理由是什麼?如果沒有這個理由很多事情就沒有出發點,好比說我做架構的目的是怎麼讓我自己快樂,那麼你可能做的這個東西雖然不好用,但是很有技術含量很有設計感。

架構每個人其實都有自己的願景或者出發點,如果出發點不對的話,其實後面講的已經是一些術的選擇,道的這部分其實對於我來說可能是更關鍵的部分。這是你作為架構師的使命。你相信架構可以帶來什麼?或者放大一點,就是作為一個對技術選擇負責的人,你應該相信什麼?選擇什麼?

給大家講一下閒魚,閒魚這個專案是2014年5、6月份開始做的。這個時候已經不是一個很好的時間點,不符合當時阿里巴巴整體的戰略選擇。當時大背景是阿里集中投入開始做無線,傾向集中力量建設幾個大型APP如手機淘寶或支付寶錢包,這是當時的策略。我們當時在招募專案成員的時候給大家講,閒魚的使命是什麼?我們希望做一個P2P的、有交易的社群。很多人覺得,從邏輯上來說還是一件很有機會的事情。當然每個人的出發點都不同,有的覺得這個業務可能讓我得到提升自己的機會,有人覺得這個業務會讓我的年底績效比較好,有人會覺得這是一個新業務,可能我後面有機會可以當上更高職位的領導者。

這些機會有很多,其實一開時招募的人也很多。在做專案kick off的時候,公司的高層會挑戰這個事情,認為作為一個初創團隊需要這麼多人嗎,而且是跟大的戰略不那麼契合。初創專案首先要證明自己是work的,如果你們覺得這是真愛,公司給你選擇的機會,到財年底公司不投任何營銷費用,做到日活一百萬;既然你是相信這個事情,那沒有做到年底0加薪0年終獎。這樣說完以後,第二天走了一半人,一個星期之內再走掉一大部分人,最後留下來相信這個事情的,只有十幾個人。閒魚這兩年的成長過程,經過很多次這樣的洗刷。當時我們抱怨老闆怎麼可以這樣?其實我們回頭想,這件事真正決定了閒魚的基因與做法。閒魚團隊後面的成長也在有意選擇真正相信這件事的人。真正相信的是什麼?我相信最後留下的,每個人會有不同的看法和不同的出發點,甚至想要得到的東西不一樣。但是他已經不是那麼功利,會在做事上有更長遠的選擇。

後面的選擇,還是有人選擇離開,覺得付出和回報不成正比,或者這個東西不是他想要的。但是不要緊,留下來的都是相信這個事情的人,這個比較重要。真正相信的是什麼東西?我們希望留下的真愛通常會是什麼?我現在跟別人溝通,發現我很難從別人的角度去說服別人,這個問題太難了,我根本想不到對方想什麼,因為個體差異太大,所以我通常說我怎樣想這個問題,這個問題在我看來是什麼,我只要讓我覺得我自己說的是真話,我可以讓別人感受到。

那麼談我相信的事情,我在阿里五年有很多次想選擇離開換一個地方,包括我進去的時候也沒有想過待很久。過程中也有很多的不爽或者糾結或者怎樣,但是回頭來看我會說,我很享受那樣的一個過程,有機會從0做到1,然後從1到N的過程,這兩個過程我有幸參與。從0到1,從無到有的過程,其實是非常煎熬的過程。通常這個過程可能要一年時間,那個時間你不斷嘗試,不斷被別人鄙視。你做的很多事情都是失敗案例,你探索的都是不成功的道路,所有人都看不起你,所有人都是居高臨下的教你怎麼做。你要學會怎麼在這種情況下生存,並且找到亮光,這個是我很享受的。如果你已經到了這個階段,找到了你真正的成長方式,接下來就是野蠻成長。其實我也有幸經歷了這個過程,包括物流或者手機淘寶,我覺得都是這個過程,就是從千萬級到億級。通常來說這個過程,就是盡情奔跑與碾壓競爭對手,壓死當初看不起我的,拿結果告訴你應該是這樣做的,這個過程也是我很享受的過程。

因為今天分享的是我在閒魚的經歷,首先講一下閒魚是什麼東西?閒魚在大家眼裡面是一個上億商品的貨架,但對你來說根本感受不到那麼多商品。如果有幾千個商品,對你來說就是海量,對你來說,首頁這裡的資訊只是跟你最相關的部分。然後是可能騷擾或有益的提醒,它會跟你產生連線。這個如果是在電商領域就是商品。但是怎麼把有益的商品組織起來,把這些商品活躍起來,並且找到這個商品所需要的人。並且在一些關鍵的時間節點,和這個使用者產生連線,這是一個非常難的過程。每個電商產品整個效率的差異就在這裡。最高效率的淘寶已經把電商的效率做到極致,它的UV價值已經做到令人髮指的地步。

640?wx_fmt=png

那麼在這種情況下,所有的電商產品有意無意的與它產生差異。我們從來沒有選擇做電商的這條道路,我們在做一個共享經濟的社群平臺,這是我們的願景。這個區別最大的地方在哪兒?我會組織使用者,產生使用者和使用者之間的連線。這個差異在我們的產品形態上其實就是魚塘這個產品,這個產品我們會通過地域和興趣把使用者連線在一起。使用者可以成為釋出者也可以成為資訊的收穫者。今天我可能強調的特點會是閒魚線下線上的連線部分,我給大家看到的照片會說明一些東西。

640?wx_fmt=png

在閒魚我們會有線下和線上互動,我們閒魚到現在是一個很小的團隊,線上下做O2O的時候,更多是靠閒魚30萬的塘主進行運營。我們發現這裡進行交易的使用者都是非專業使用者,他通常想要出售的東西,通常不是為了錢。我們在這個點上會發現,當然也是在實際上面運作的時候才發現,通常線上下交易的人是大學生或者有孩子的。有孩子的其實很容易理解,幾個大人在那裡跟人家討價還價,就五塊錢或者六塊錢的事情,其實很沒份。其實大家都是有身份的人,做這個事情很丟臉。但是帶了娃這個事情就會變性,就會變成我讓我的小孩參與一個社會實踐活動,讓他理解金錢的重要性,讓他知道什麼東西都是有代價的。大學生就會更明顯,其實這個裡面通常是交友,通常交換的東西超過交換的本身,比如說教課書或者是師姐的一床被子。我下面講的是跟技術相關的部分。

所有的技術架構的演進跟業務形態都是強相關的,你處於什麼階段要解決什麼問題?首先描繪一下我們開始的業務架構的模型。我們看一下我們最開始的閒魚的架構其實很簡單。這個架構的背景是什麼?當時閒魚的人,整個開發是十人的狀態。很不幸的事情就是沒有測試,閒魚最開始上線就是這樣子,我們沒有測試直接上線。開發工程師做好了以後就直接上線,我們也沒有很大的能力去做很多的基礎的架構的工作。我們更多是在複用淘寶PC或者手機淘寶相關的工程結構。

640?wx_fmt=png

這個階段裡面,我們有自己的核心關注點,這個階段的架構原則是什麼?就是用速度換質量。我們其實是在犧牲線上質量來換取更快的開發速度,基本上我們是想到一個功能,想到一個可能性我們就希望它立刻可以體現在線上。那麼在這個過程中,我們會遇到一個很悲催的事情,客戶端發版並不是我想要它多快就可以多快,開發可以一下午打包發出去。但是這個做不到,因為當時2014年Apple審APP速度非常慢,一般來說是3到7天,有時候比這個時間還長,如果中間拒審可能兩個禮拜才上線,這是一個非常痛苦的過程。動態性,其實這個階段就是我們在找真正適合我們的商業模式,到底是什麼?使用者可以產生共鳴的點在哪兒?動態性這個問題上面,我們並沒有使用特別複雜的技術方式解決這個問題。

我們使用的技術方法,即使我扔上去也不能改變蘋果審的速度。所以我們選擇了HyBird的架構,我們選擇用H5解決這個問題的動態性。基於此我們在下面做一個,其實我這裡藍色部分就是我關注的幾個點。一個是URLRoute這個裝置,不知道大家有沒有理解。這個手淘應該講了很多次,我們會利用客戶端將所有請求路由到一個H5的連線。這個裝置會通過URLRoute通過URI Schema到達到真正的客戶端的一個頁面,如果找不到對應的時限就會用H5的實現來做它的打底。如果這個部分native沒有開發出來,就用H5版本頂上去。這樣的話,安卓和IOS的版本不同步的問題解決了,因為安卓通常比較快,這個時候上去安卓已經有了,跟它對應的裝置就是開關中心。

開關中心這個東西就是我們為了實現一些靈活的配置情況下,我們需要一些針對這個流程做一些配置。可能需要將某一個路由進行轉接,也可能需要再額外加一個呼叫的引數,甚至加版本或者人群的分割。其實都是客戶端的動態改變,它可以到開關中心進行調整。

通過開關中心已經實現我們想要跑多快就跑多塊,不用擔心釋出跟版本錄用迭代不匹配的問題。我的版本發多了會有多個版本的問題,在多個版本的問題我怎麼實現服務端的問題,這個引數可能不存在,其實這裡我們會基於一個閘道器的多版本相容的體制,每個API的訪問都會加上版本號,在相同API不同版本的實現是通過一層一層複用的機制,保證對上一個版本的支援。其實在服務端我們會做一個通行的老版本,基於此我們會利用開關中心跟ABtest的關係,我們會切分成進行測試的分口,通過這個下發到每個客戶端,在不同的人群裡面,它的介面表現和資料表現是不同,實現一個端上的動態測試。這是我們第一個階段,其實就是說整體的試錯的過程。

我們在端上的介面,比較痛苦的事情是做活動,運營他們可以想起來的日子都可以做活動,這個活動他們希望有一個前端的入口,最好是首頁或者關鍵的資源頁能夠動態投放相關內容。通常來說這個問題其實解法是,你把全網可以挖出資源位的地方都出來預置好。對於我們剛開始做一個APP的時候,去哪裡挖資源位,其實是把整個複雜度提升了。這種情況我們選擇了一個動態挖資源位的方法,其實就是Poplayer,我們會進行頁面切換,它會根據當前切換的頁面進行頁面的載入,它有一定的透明度。比如說在首頁上面,聖誕節加一個聖誕老人或者雪橇,其實這個資源位我可以通過Poplayer加上去,這個牽扯到一個前後端配合的工程技術裝置。

接下來我們會說, 比較勉強進入到0.1的階段,就是發展階段。我們認為對於我們來說我們整個的交易在過億的時間節點,我們認為我們做到0.1的狀態。這個階段我們整個系統的架構原則是什麼?我們會發現其實我們已經能夠比較模糊的看到了商業的模式,或者是使用者的價值點。在這個狀態的時候,對我來說架構的挑戰就是效率和能力的問題。這個地方還要提一下對於效率的開發,開發效率,研發工程師關注效率永遠不是錯誤的事情。但是你關注效率的目的有不同,有的同學會說我關注效率的目的是讓整體的成本降下來,但是這個階段來我們關注的不是成本,而是我有機會做更多的有可能的事情。

640?wx_fmt=png

在這個階段我怎樣提升架構?架構原則是說你怎樣提升效率?我的架構原則其實就是沒有溝通的協作是效率最高的。就是在你不改變整體的生產工具的先進性的情況下來改變生產方式。在我看來就是沒有任何的溝通,是最有效率的開發方式。在這個地方我們會更加關注整個的前後端的協同的協議和約定和契約和工具的自動化。這個時間點,藍色部分我們會發現,比如說我們在活動這一端會有MBaas的裝置,你客戶端想要儲存使用者參與這個抽獎或者使用者進入這個頁面有一個點贊工作,這是一次性的工作你不要來煩服務商量。在後端不需要增加任何介面就可以實現這樣的業務,這是一次性業務。在我們這裡我們會提供一個MBaas的結構,這個裝置不需要關注服務端到底有什麼東西?

我們在客戶端開發關注兩個點,一個是說我新做一個功能或者說新做一個頁面,新做這個頁面整個的組裝它需要哪些元件進行組裝?在這種情況下其實是對於業務的邏輯,將原有的UI元件進行組裝。這是一個開發過程,第二個過程是說我對原有的介面的重新梳理我需要加一個功能,或者加一個點讚的按紐。這兩個邏輯我們會規範到元件的完善過程中,另外一個就是業務的邏輯梳理。

我們現在的做法其實是組裝邏輯會下沉到服務端,客戶端它沒有業務邏輯,只在服務端有邏輯。整個你看到的這些資料這些資料的組裝模式其實都是服務端下發,客戶端只提供介面能力的組裝,它解析然後進行渲染,但是它不理解這裡面是什麼?

640?wx_fmt=png

客戶端更多的工作是支援更多互動的基礎的UI元件和動態適配性。這個過程中我們強調的就是整個的事件驅動的開發模型和整個UI元件庫的建立。在服務端因為我們會將大量的一次性工作拋棄了以後,使我們有時間做一些新場景的探索,包括怎樣線上跟線下的銜接?這個部分後面會講到。更多的其實是在資料上的應用,在前面已經說了,其實幾億條商品使用者不關心,關心的是幾十條和我產生連線的內容。

640?wx_fmt=png

現在的閒魚的技術架構,我們認為現在已經接近了到1的過程。在這個狀態的時候其實我們會更加關注的是我們當初的願景的實現的過程。我們怎樣可以讓更多的業務在我們這個共享經濟平臺上能夠落地?我能真正的可以成為一個平臺?在這種情況下其實我想要的事情,已經遠遠超出我們自己的能力。這種情況下野心大於能力的時候,只能選擇我可能去做更多的更基礎的一些規劃。然後把更多的可能性更多的動態性留給二方或者三方完成。這個裡面我們做的更多的事情是對外整個的連線的協議的梳理和呼叫協議的梳理。那麼這個裡面我們會演化成,在容器這端我們演化成Service Bus,這個類似服務端的ESB。我們在客戶端裡面會基於原生的訊息的和服務呼叫的方式,通過服務呼叫。

640?wx_fmt=png

這一層我們的Service Bus是有一個包裝的,我們不會讓使用者上層的呼叫程式碼直接訪問Service Bus,我們會在這個上面做一個SDK,來屏敝各個版本之間的差異性,來保證它的相容性。我們會把自己的基礎的展示能力,整個結構化一個Parser,這樣一個架構來解析未來在介面上展示的型別,使得未來我們擴充套件到其他業務型別的時候,不需要所有的參與者,都要從頭開始做對應的展示的基礎元件和至上的組裝。

這個就是跟服務端對應上面是有一個模型,服務端要提供資料接入,在端上面能夠展出來。在資料這一層我們會更加跟演算法的能力的銜接,其實我們通過兩條通路。一條路是實時的資料的流入,是基於我們在客戶端上面的日誌,這是分鐘級日誌實時反饋到我們的演算法平臺,然後包括業務資料直接打進我們的演算法平臺,然後拉到我們的搜尋演算法整個的機制裡面。這裡比較詳細的會說一個閒魚的架構演進,整體就是由我們的容器的中心跟訊息的訂閱釋出機制和我們前端最主要的展示結合,形成一個前端架構。

640?wx_fmt=png

前面講的是說端上的架構,這一頁其實是因為寫完了以後,服務端的同學不是很開心,希望我加一頁。其實我覺得服務端的架構其實在過去阿里的分享,也分享的很多。這裡加的更多是說我們在資料上面的整個的資料的流向,怎樣去跟演算法進行結合,進行離線和增量資料的實時匯聚,跟前端整個打通的一個機制。

640?wx_fmt=png640?wx_fmt=png

我們在線上線下的聯動會遇到一個問題。這個問題在O2O行業已經講了好幾年,真正做成的業務可能到現在也沒有,難就難在沒有實現真正的線下線上聯動。我們到這裡也會遇到了同樣的問題,這就是線下使用者身份識別,並且把使用者的線上資料跟線下行為銜接起來,這個問題對於我們來說很難解決。這個人到這裡我能知道他是誰,對我來說是一個最難的過程。這個部分我們會做了一套身份識別和裝置的校驗機制,對使用者進行識別,並且進行反向的互動,結合訪問量進行使用者的訪問量互動。

640?wx_fmt=png

最後給大家說一下資料驅動的開發的工作方式。其實很多同學都會說,我是相信的。但是實際上真正在做事情的時候,可能大家又會按照習慣邏輯說我覺得這樣做會更好,這樣我們會陷入無休止的糾纏,PD說我覺得怎樣,但技術覺得不靠譜,然後就會說我覺得這個不怎樣,那個又會說那個怎樣。大家都是在說感覺,那麼在這種情況下我們到底有什麼樣的機會可以讓我們整個做事的內容能夠迴歸到我們最開始的願景?對我來說是比較關鍵的。我們現在的做法是,整個產品KPI,整個核心資料的KPI,它全部指向我自己的關鍵訴求。

對我們來說現在的關鍵訴求就是使用者規模。這個場景如果跟使用者規模不相干,它的關聯性,如果偏弱。那麼我會讓位給另外一個產品,這是我在產品迭代裡面的原則。我們發現首頁的資源效率是不同,應該給誰更多流量?我們會做整個產品組合的最佳收益點。這個流程包括整個資料的挖掘,因為很多收益不是單目標決策,是多目標決策。我們是追求它的空間距離的問題。那麼在這裡我們怎樣去選擇我們的最大獲益點?獲益點我們找到了以後,我們希望整個的結果是可以通過數字去表達,我做一件事情,整個的結果是可以進行預測的。這個方法這個方案是有一個持續迭代和修改,在線上需要提供ABtest和迭代的能力,讓我看一下這些資料是否能夠在線上復現,就是樣本空間裡面證明的是正確的,在整個的實際的使用者空間裡面證明它是可復現的。

資料這塊更敏感,實在是沒有辦法舉這個例子,這個裡面都是很敏感的資料。但是我可以說幾個案例,這幾個案例包括我怎樣去留住新使用者?我想所有做APP的同學可能都會關心這個問題,每個新使用者的引入成本,便宜的幾塊錢,最貴的幾百塊錢,這個新使用者怎樣留下來?這是一個最要命的問題。如果新使用者留不住,這個APP永遠沒有成長機會。這個裡面我們分析流失的路徑,然後可以強化它的行為。比如說舉個例子,一開始所有人都會覺得讓使用者進行一次交易,會使他的流失降到最低。我們認為這個特徵是最有效的特徵,所有的行為都會指向讓使用者完成一個交易。當然這個有很多方法,比如成交成本更低的操作,可以讓他完成交易。

    最後我們發現這不是最有效的使用者留存。我們反而發現一個使用者連續來三天,比你完成一筆交易,整個貢獻的效率更高。這只是一個發現,大家不用直接搬回去用。我就講這些,謝謝大家!

Q&A

Q1:剛才提到有一個針對SDK的支援,我想知道這一層,能不能介紹一下。因為我們知道每一個SDK它是有很多新的功能組合,也有很多老的功能,然後是怎樣抽象出來的?剛才提到有一個H5的支援,這一層的功能是把活動實現,然後從後端打通到前端,我也想知道這一層,能不能稍微介紹一下。

孫兵:首先確認一下問題。第一個問題是說介面的相容問題。我們其實每一次版本的釋出,我們會把這個版本打在配置檔案裡面,所有API的版本是一個通用版本,我們不需要定義每個API的版本是什麼?我只要告訴你這個程式的版本號。然後到我們服務端,我們所有的請求我都會告訴你這個APP的版本是什麼?這個APP的版本預設在服務端的時候,會選擇跟它最接近的上一個版本,跟它間隔是最小的那個版本。如果他覺得我有必要為這個版本做一個升級,因為可能有更多的引數,或者需要更多的反饋,那麼我在這個版本里面加一個針對這個版本的適配。這個其實對整個服務端整個的改寫成本會降很低,因為預設的版本不需要做任何動作。如果我覺得這個版本之後需要額外做一些事情,我就需要在這個版本里面會做新的版本API動作。

第二個問題是說後端不用管前端的MBaas的結構,MBaas的結構,現在在連結裡面也有公有的MBaas,它的原理很簡單,就是前端需要後端提供儲存服務,或者一個計算。這個儲存服務,客戶端在第一次申請的時候,給他動態的建立他所需要的schema,你進行操作的時候,所有的邏輯包括+1-1,或者你想加一個動態的贊,這個你可以在後端進行操作。因為客戶端跟你個人相關,我不需要關注群體邏輯,這可以用MBaas的結構來做,其實就是有一個對應的服務端結構,這是根據你的請求去動態建立的schema。

Q2:第一個問題是服務端有很多程式碼,然後用覆蓋這個方式來做程式碼支援。

孫兵:會覆蓋掉上一個版本,通常來說。

Q3:第二個問題,其實主要是針對個人,這個解決方案不能解決每個個人使用者他的計算,他的計算是不同的。

孫兵:聚合是比較難的。我們會有一些通行的介面,我們會用搜索解決大量的個性化的資料,我們會有一個通用的搜尋介面,這個就是所有的可以進行索引的索引詞,可以用搜索查詢解決這個問題,但是聚合計算要單列了。

Java高階架構乾貨|交流640?wx_fmt=png640?wx_fmt=png長按,識別二維碼,加關注640?wx_fmt=png轉載是一種動力 分享是一種美德