當前位置:
首頁 > 科技 > 阿里巴巴微服務與配置中心技術實踐之道

阿里巴巴微服務與配置中心技術實踐之道

接收程序員的 8 點技術早餐

作者|坤宇

編輯|小智

在面向分散式的微服務系統中,如何通過更高效的配置管理方式,幫助微服務系統架構持續「無痛」的演進,動態調整和控制系統的運行時飛行姿態,值得我們好好的在配置管理上重新思考和設計。別讓您的微服務被配置管理「絆」了一跤!

本文是阿里巴巴高級技術專家 @坤宇在 2017 年 QCon 微服務專題演講中關於微服務與配置中心的演講實錄的文字版,演講視頻可以參見:

http://www.infoq.com/cn/presentations/micro-service-and-configuration-center?spm=a2c4e.11153940.blogcont332358.36.30772099lWiw8H。

阿里巴巴集團早在 2007 年進行從 IOE 集中式應用架構升級為互聯網分散式服務化架構的時候,就意識到在分散式環境中,傳統的分散式的、基於配置文件的、應用自包含的配置管理方式將面臨重大挑戰,亟需設計匹配新架構的新的配置管理解決方案,解決諸如分散式服務治理,數據源容災切換,異地多活,預案,限流規則等場景下的配置變更以及熱生效問題,這直接誕生了今天阿里集團內部被廣泛使用的配置中心 ACM(Diamond),而這也是目前世界上最大的配置中心,存儲了超過百萬的生產配置,在集團內部支持了包括淘寶、天貓、菜鳥、阿里雲、高德等全網幾乎阿里所有的應用,每天產生近 10 億次的配置變更推送。

寫在前面

在「史前」單體巨獸型應用時代,配置管理不是什麼大不了的事情,但今天在微服務架構中,配置管理已發生革命性的變化,但業內對這一塊的前沿探索一直處於秘而不宣的狀態,如果我們對這塊沒有過深入的思考和實踐,我們很難真正理解為什麼 Spring Cloud 會提出 Configuration Service 的概念。 在面向分散式的微服務系統中,如何通過更高效的配置管理方式,幫助微服務系統架構持續「無痛」的演進,動態調整和控制系統的運行時飛行姿態,值得我們好好的在配置管理上重新思考和設計。

正 文

我的這個話題只能算是今天微服務架構專題中的一個開胃小菜,可以說我們是直接進入了微服務實幹裡面,即微服務的配置管理這一塊。我不知道在座的有多少人意識到,我們講微服務可能有很多的挑戰,比如像運維啊,測試啊,有很多的跟以前單體應用開發時有不一樣的挑戰,那關於「配置」這個以前我們司空見慣的東西,它也有一些新的挑戰。很多人還沒有意識到,在微服務架構底下,配置管理也會成為一個挑戰。

講到配置管理這個問題域,我們要提到一個核心的概念——「配置」。我們人比較有意思的地方在於,有的時候,一些司空見慣的東西,我們反而缺乏對它本質的思考,那「配置」的本質是什麼東西呢?配置的表象,我們可能知道,一個配置項可能是 key-value,value 可能是一個有限值的集合,配置我們都不陌生,一個系統沒有提供幾個配置參數的話,可能都不好意思上線跟別的系統打招呼,為什麼是這個樣子呢?從我的理解來說,本質上是因為我們人類沒有辦法掌控和預知一切,所以我們映射到軟體系統這個領域,需要人為的預留一些線頭,以便在未來,撥弄這些線頭調整系統的飛行狀態。所以我覺得配置是程序運行時動態調整行為的能力的一種手段,而且這個是上到生產,在運行時想調整行為的幾乎唯一的一個手段。

下面我們來看一個例子,大家可能會對剛才的這一點有一個更直觀的感受。

我們都知道,在生產環境上我們可能把我們的日誌級別調整為 error 級別,但是,在系統出問題我們希望對它 debug 的時候,我們需要動態的調整系統的行為的能力,把日誌級別調整為 debug 級別,這是一個非常簡單的例子。

在單體應用時代,或者說在集中式應用開發時代,我們應用可能就是打成一個包,那在這個包里我們可能提供一些配置文件,當我們的系統上到生產環境之後,如果我們需要修改系統的行為,我們只需要登錄到機器,修改一下配置文件,然後 reload 一下,實際上不是什麼大的負擔。

但是在微服務架構底下,配置文件已經不能滿足整個系統架構對於配置管理的一些需求,我們大概來看一下。

首先,微服務系統天然就是一個分散式系統,那在分散式系統中,我們有沒有可能登陸機器一台一台地改配置文件呢?尤其像現在的分散式系統規模越來越大。第二點,不同的微服務是由不同的團隊,不同的組織去負責開發和維護的,微服務架構給大家承諾的是,每個微服務可以採用不同的技術棧,在這種情況下,我們作為運維人員,作為 Ops,甚至不知道配置文件在哪裡,因為配置文件名,配置文件放置的目錄,可能是五花八門,所以沒有辦法去做基於配置文件的管理。大規模的分散式系統可能部署在不同的機房,有各種部署,那當一個配置改變了之後,這個配置什麼時候生效的,它有沒有生效,有多少機器上,配置變更了,但是失敗了。

這些狀態,通過配置文件是沒辦法明確地把這些狀態暴露出來的,簡單的來說,應用暴露了哪些配置,你依賴的那些三方的服務,其它團隊開發的服務,到底暴露了哪些配置參數,可能這個簡單的問題通過配置文件管理的時候,我們都沒有辦法回答。再不用說分散式系統中某一些子系統我們想一致性的改變它們的行為的話,還有比如配置如何容災,配置文件如果丟失了,我要回滾到某一個歷史版本,這個事情怎麼做?這些都是採用微服務分散式架構給配置管理帶來的挑戰。

下面這張圖,關心微服務的同學應該很熟悉,這個是微服務最早佈道時期的一張比較著名的圖。

這張圖主要說明了在微服務架構下,配置應該集中式的管理。來 QCon 我們當然不是來講開源的解決方案比如 Spring Cloud Config Server 是怎麼做的,我們主要還是想講講阿里在配置中心這個領域的實踐和我們自己的故事,希望能夠給大家帶來一些啟發。可能這中間的實踐和探索我們有成功的也有不成功的,系統通過今天的分享都能給大家帶來一些有益的啟示。

有熟悉淘寶技術體系演進的,大家都知道這大概分成了三個階段,第一個階段是買了一個 LAMP 架構的網站。之後隨著業務的發展,做了一個從 PHP 到 Java 體系的轉變,再之後,業務量越來越大之後,大約在 2007~2008 年,我們淘寶內部開始了一個項目代號為「五彩石」的一個項目,做的一個事情其實就是單體應用的拆分 (微服務方法論里所謂 Monolith First),因為當時已經出現上百人維護一個核心工程的現象,源代碼的衝突非常嚴重,人員的更新速度非常快,因為單體的源代碼庫急劇膨脹之後,新人進來之後老代碼成本高,在老代碼基礎上進行新的開發上手很慢,所以做了這麼一個分散式服務化的拆分。

淘寶的配置中心也是在這次 07、08 年做拆分的時候產生的。服務化之後,首先要解決的是服務發現,所以需要一個服務註冊中心,當時業界還沒有微服務的概念,我們的配置中心也是在註冊中心裏面的,所以這裡也有一個插曲:當時我們的註冊中心叫 ConfigServer,@曉斌的老闆後來吐槽我們說,中國工程師,你們這個英文水平太差了,明明是個註冊中心,你叫 ConfigServer,你說現在叫大家怎麼理解。這也是我們走過的一段彎路,所以後來發現註冊中心和配置中心是 2 個不同的關注點,我們後來很快就把配置中心從註冊中心中拆出來了,現在註冊中心沒有辦法改名了,還是叫 ConfigServer。

雖然我們做配置中心起步的比較早,但是在業界總是有一些神人,他們有超越常人的遠見,我們要講一下下面這兩位老哥:

這兩位老哥 1984 年在 IEEE 上發表了一篇論文,論文的題目就是《分散式系統的動態配置》。1984 年是什麼概念呢,我當時是 3 歲,那時候還在穿開襠褲,可能還在玩泥巴,而我們配置中心的主力架構師,當時還沒有出生。所以做技術,有的時候有些大神通過現象看本質的能力,技術的視野之遠我們不得不佩服。

在這篇論文里,這兩位老哥對分散式系統的理解可能還沒有達到今天的這個層次,當時他們可能也想像不到分散式系統後來發展到今天這麼龐大,這麼複雜。但是他們對動態配置這個領域的問題看得是比較清楚的,就是在一個大型的分散式系統中,你沒有辦法把整個分散式系統停下來,去做一個軟體的、硬體的或者系統的升級。

我們上面看了分散式系統給配置管理帶來的一些挑戰以及大概地介紹了一下淘寶的配置中心的發展歷程,淘寶的配置中心發展到今天大概存儲了超過百萬的生產配置,每天要產生幾個億的配置推送,可以說是現在世界大規模上生產的一個配置中心,那我們下面來看一下,配置中心在哪些關鍵的場景下,可以發揮一些關鍵的作用,我這裡舉三個例子,給大家一個直觀的感受,第一個是大促預案:

大促預案是什麼呢?我們知道,當你的系統同時湧進來超過一億人並發訪問的時候,這個系統一定是扛不住的,一定會掛掉,在這個過程中我們講大促有 3 大法寶,彈性,限流,降級。系統的限流和降級本質上來講就是從日常的運行態切換到大促態的一個行為的動態調整,這個本身天然就是配置起到作用的一個相應的場景。隨著大促時間點的臨近,這些分散式系統中,每個子系統會有大大小小的預案,這些預案其實都是以配置的形式去存在的。配置中心會在這個時間軸上,定時地安排執行預案,每個系統哪些功能降級,在什麼時候降級,什麼時候開放哪些專門為大促存在的一些功能,在大促之前的時間點,整個應用發布會封盤,被禁止掉了,已經不允許做任何線上發布了,那在這個時候要切換系統的行為,那就是靠配置中心去做這個事情。

第二個案例是大規模數據容災:

最早淘寶配置中心產生的原因之一就是當時我們要解決大規模數據容災的問題。一般來說,為了高可用,業務可能部署在 2 個機房,現在一般同城雙機房是標配。數據存儲,比如像 mysql,在生成上我們為了高可用,可能會配備一主幾備,主庫是可寫的,備庫可能是只讀的。在生產上可能有幾台機器壞了或者甚至一個機房壞了,出問題、故障了,基礎設置(infrastructure)這一塊,可能有一些事件冒泡到軟體平台 PaaS 這一層,這個時間冒泡一般會到 DBA 團隊的一些資料庫高可用基礎設施,DBA 會根據整個業務系統在機房的部署拓撲,來找到這個壞掉的機房裡的所有的主庫,來做一個主備庫的切換,把備庫切成可寫。在這個過程中,配置中心的作用呢,就是跟 DBA 的高可用切換工具保持聯動,DBA 工具負責資料庫切換,產生數據源配置變更,所有應用基於配置中心監聽各自的數據源配置變更,當產生主備庫切換,配置中心會將數據源配置變更推送到應用,整個過程對應用是透明的,無感知的。應用是不用知道底下機房出問題了,主備庫出現切換了。

第三個例子是異地多活:

現在一些大型的互聯網系統,CDN 後面會有一個統一接入層,包括 PC 和移動端的流量可能都是從這個統一接入層進入到生產的機房的。在這個過程中,統一接入層負責根據前端用戶的屬性,去分配用戶的流量到後端不同的單元。當一個單元掛了之後,這些流量需要無縫地切到其它的業務單元裡面去,這個單元它糅合了機房以及業務域的一些劃分,在這個過程中,配置中心要起到一個關鍵的作用是要在統一接入的機器上,要讓它們對於全局的流量規則達成一個分散式共識,這個實際上是分散式一致性的一個要求。

以上我舉了三個簡單的配置中心在淘寶的生產實際中的運用場景。對這些場景有了一些了解之後,我們來看一下,假設今天我們要去設計一個配置中心,那麼有哪些關鍵的特性或者說哪些關鍵的技術決策點需要去關注。我們上面舉的例子只是 3 個基本的例子,實際上如果你真的把配置統一集中管理起來之後,你會發現業務應用依賴配置中心是會非常瘋狂的,很多的用法和使用方式是你原先根本就想像不到的,比如我們就發現有些應用會把自己的代碼片段放在配置中心中,在關鍵的時候在線上通過注入這些代碼片段來達到改變系統行為的能力。

下面我們講講配置中心設計中的技術決策。

第一個點,我們都知道,做一個分散式系統本身我們要有一個基本的意識,那就是系統一定會掛,而且是在你想像不到的時間點掛。作為一個配置中心,當所有的系統都依賴你去做配置管理的時候,就必須回答一個問題:當你掛了,其它人怎麼辦?所以一定要仔細地去看這個場景底下我們怎麼去處理。這個裡面對配置中心有幾個關鍵的技術決策點,從邏輯上來說其它業務系統對於配置中心的依賴應該是一個弱依賴,做分散式系統的相信很多人都應該知道強弱依賴的一個概念。

為什麼是弱依賴?最基本的一個道理,當業務系統即依賴配置中心的這些系統,當它們不需要調整系統行為能力的時候,它其實是不用 care 這個時候配置中心服務到底在不在的,所以當我的配置中心服務掛掉的時候,影響應該是有限的。也就是說這時候業務系統該做的業務還是在做,只要不做一些系統行為的調整,你的系統應該能正常的跑。要達成這一點,這裡面就是說配置中心提供的客戶端或者 SDK 其實應該實現客戶端緩存。

還有一個就是配置應該是稀疏變更的,沒有人會不斷的調整系統的行為玩兒,比如一會把日誌級別調整為 error 一會調整為 trace,這麼玩是不對的,在稀疏變更的這個條件下,客戶端緩存的價值是巨大的,如果一個數據變化約頻繁,那麼做緩存得到的價值越小。所在在配置管理這個場景,客戶端緩存就能達到 2 個方面的訴求,1 個是剛才說的容災,配置中心掛了,應用可以從本地客戶端的緩存該重啟還可以重啟,另外也可以通過緩存達到改善性能的目的,從容災的另一個角度來看,配置本身的存儲需要容災。配置是不能丟的,好多應用我的各項配置好不容易調整好了,然後換了一撥人來維護應用,可能他們根本都不知道這些配置都是幹嘛的,這是你作為一個配置中心,你把人家的配置搞丟了,應用可能就起不來,甚至找不回來了,這個是不允許的。

第二點,配置中心關鍵的是 SLA。我們知道每個系統的 SLA 都很重要,配置中心的 SLA 講究的是推送,推送的時延和推送的成功率,根據我們的經驗,配置的推送,推送到依賴的業務方進程,雖然越快越好,但如果配置中心做不到,一般上限 3 秒以內是 ok 的。因為基於人登錄多台機器上去改配置然後生效一般都是超過 3 秒的。比如一個配置變更要推送到 1000 台機器,那麼每台機器上配置生效的時間在 3 秒內是 ok 的。

推送的成功率是 SLA 的另一個方面,比如說 10000 台機器,我能達到只有 100 台機器可能配置變更沒有推送到,那一般在這個場景和規模下也是 ok 的。當然所有的 SLA 要求是越高越好,比如淘寶的配置中心現在基本要求是推送時延在 200ms 內,成功率要在 4 個 9 的。如果配置中心 SLA 達不到要求,那麼大家是不敢從本來很可靠的配置文件,切換到外部依賴的配置中心的。

配置中心技術決策第三點是灰度。有些配置就像家裡的電源開關一樣,我按開關不會發生什麼大事,但有些開關對於公司是核武器級別的,比如像全局路由規則,全局的限流規則,可能一個按鈕下去,公司就炸了,就是全局的流量都進不來了,或者像上面說的整個單元的路由規則都亂了,這個時候可能就造成大的社會事件了。在這種場景下實際上就是要求配置中心有灰度的功能,什麼意思呢?就是我先推一個配置到幾台機器上試一試,要給業務方這種能力,而且這個灰度能力跟業務方發布時的灰度的能力應該是解耦的,因為應用已經在線上跑了,這個時候我們不用做發布,我們是動態的修改系統的行為能力,也就是說配置中心在支持業務本身的灰度發布之外也要支持配置的單獨的灰度的能力。

最後一個,是當我們把配置放在配置中心集中管控之後,實際上這裡也涉及一個 DevOps 相關的話題,也就是說,以前單體應用時代,很多的線上運維操作,比如配置的變更可能是由運維人員來完成的。在微服務時代,在配置集中到配置中心管理平台之後,很多配置可以交給系統的開發人員自己去負責配置的變更。

另外配置中心需要提供配置變更審計的能力,在一個大型的分散式系統可能每天都有故障產生,故障我們知道常常都是由一個變更引起的,變更包括幾個方面,包括代碼的變更,配置的變更,配置中心一定要提供說當前這個時間點,有哪些系統變更了哪些關鍵的配置,這個能力實際上是要有的。另外一個場景比如說像大促,封盤了,不允許有任何人在線上配置的變更,除了像剛才說的像大促預案這種計劃內的配置變更,這種時候,因為配置中心是配置管理的一個集中式的入口,很容易就達到這個目的。那以分散的配置文件的方式以前是沒法做到的。

這裡我們沒有具體的講某個技術棧,因為我覺得很多的選型時根據自己的需要,選什麼都可以。但是作為一個可以上大規模生產的配置中心,我覺得這些一定是要有,一個是配置的存儲,剛才講過配置是不能丟的,所以如果說完全基於內存緩存做肯定是不靠譜的,比如我們幾個配置的副本,怎麼做配置存儲的容災的切換。

第二個,當基於微服務的架構起來之後,所有的業務系統都依賴配置中心的時候,可能數據中心的所有機器都與配置中心有連接,如果只選一個存儲,可能是無法支持這麼大量的讀的,所以上面可能需要一個可以橫向擴展的緩存集群里,再上面你要解決的是配置一定要有一致性,能在各個緩存節點上快速的將配置值達到一個一致的一個狀態,然後你需要把配置中心的服務開放成一個 service。

在客戶端來講基本上有 2 種模式,一種是 SDK 或者說客戶端 API,這個為什麼我們一般不通過配置中心暴露 Restful 服務,讓業務方直接調用 Restful 介面呢?就像剛才說的,客戶端從容災的角度來說,你是需要客戶端緩存的。這種場景下,配置中心最好提供成熟的客戶端 SDK,把客戶端容災考慮好,不用每個業務方自己都要考慮容災。

考慮客戶端緩存,第二種模式是 agent 模式。現在這種模式是越來越重要的,它會在每個業務機器上有一個自己的 agent,業務的進程和 agent 之間要麼通過進程間通信,要麼通過本地一個標準的目錄,通過本地文件來做配置變更的消費。配置中心客戶端與服務端之間,除了我們常見的拉取的模式,配置中心一定要實現推的模式,技術實現方式無所謂,可以用 http2.0、long polling、websocket,但推的模型一定要有。因為配置有了變更之後,你是要推送到業務放的,以為這樣是最實時的,另外客戶端要實現訂閱的模式,跟消息系統很類似的,一般配置中心也是一個 PUB-SUB 系統,那他跟消息系統的區別是什麼呢?消息系統是一個消息消費完了,會從消息伺服器上刪掉了,但是配置有可能存 3 年 5 年,配置變更消費完,配置還是在的。

接下來我們看一下,業界的現狀。業界的現狀也是在從配置文件逐漸轉向中心化的管理配置,然後逐漸發展到不再是以文件的思路去管理配置,這裡左邊是一些業界著名的客戶端 SDK,比如像第一個 OWNER,最早的時候它也是以配置文件的方式在做一些配置方面的編程的模型,後來它也逐漸地跟像 zookeeper 這些做相應的集成,也就是說開始支持配置中心的這種模式。

業界也是近年開始逐漸進行配置中心的實踐,可能沒有我們開始地那麼早,比如像 Spring Cloud Config,但是我目前還沒有看到大規模採用它到生產上的一些分享,所以不知道在我上面提到的一些比如容災,比如 SLA 以及關於配置的一些關鍵的特性的表現,它只是把以前應用自己管理配置搬到了 git 集中化管理,可能你可以通過它提供的 Spring Cloud Bus 做一些配置的推送,配置的存儲這一塊的選型很多都是 ok 的,也五花八門,有 etcd,redis,s3,git 這些都有。

我們看了發展到現在的配置中心的狀況,配置管理這一塊未來會有哪些趨勢,在這裡一些方面我們也在實踐,比如容器技術現在在生產上已經逐漸在採用了。我記得去年看到一個數字,docker 已經在全世界有 30% 的生產環境上採用了,docker+ 微服務也給大家提供了一個想像空間是我的一個微服務,因為它本身比較小,掛了以後我們可以很快的在數據中心的其它機器上拉起來,這樣可以做到彈性,橫向擴展。但在這裡一個關鍵的點,你的應用在 A 機器上暴露的服務,如果掛了,它切到 B 機器上,但是它在 A 機器上有一些狀態,這些狀態遷移是很困難的。

所在在這種架構里給我們提了一個訴求,那就是應用有狀態的部分和無狀態的部分實際上是要分離的。也就是現在從大的架構層面方面說就是存儲計算分離,我的服務的有狀態的部分是落在存儲裡面,服務的無狀態部分只是個計算。當出現某個節點掛掉了之後,我只需要在另一個地方把這個計算拉起來,然後把存儲里的狀態重新 load 回來,這樣我們就可以達到彈性水平擴展的這種能力。

這種場景下,配置就是一種狀態,我在這台機器上曾把開關從 ON 切成 OFF,這就是一種狀態,這個狀態當它切到另一個 server 的時候,它是帶不過去的,如果想帶過去比較麻煩,也就是說你的調度必須記得每個機器上的配置的狀態。

所以我們現在在實踐的是說,我們認為將來一個應用程序會分成三個部分,第一個你的源代碼可能是在 github 裡面,你的應用的鏡像,docker 鏡像可能是在 docker hub 裡面,而你的配置從源代碼裡面切出來之後,是放在一個 cfg hub 裡面,而這個 cfg hub 其實就是一個配置中心。

這樣做的一個好處是,我們知道 docker 給大家承諾的是一個鏡像,到處運行,跟 java 曾經承諾的一樣,實際上如果你仔細審視你的應用程序的話,你會發現配置這個東西不行,它是強環境屬性的,就是每個環境呢有它自己的值,比如舉個例子來說,在測試環境中我們的線程池可能設置的很小,我們的系統可能很多的 docker 容器擠在一台物理機器上,那生產的超賣比可能就沒這麼多,這帶來一個問題就是說你要想達到一個鏡像導出運行,那就要把你的配置從鏡像中抽取出去來,單獨放在一個地方,這樣你才能做到生產、測試、預發還有很多很多的環境都是一個鏡像,然後起來的時候呢從配置中心把相應環境的配置給它拉下來然後組成一個完整的服務。

我們主要介紹了應用進程級別的配置,其實從去年亞馬遜雲計算大會上就提到在雲上怎麼做配置管理,他們的想法關於配置管理的外延更大,他們認為不光是應用進程,與雲計算相關的所有的資源,包括 IaaS 層,包括諸如用戶安全組啊等這些資源全都是可以通過配置去驅動的。我這次來參加 QCon 的大會的時候,看到亞馬遜的展台,他們有一個叫做 AWS Config 的這麼一個產品,在他的最受環境的 30 個亞馬遜產品評選中,他跟亞馬遜的著名的 DynamoDB 的受歡迎程度是一樣的,用戶採用率高達 35%,我們也是覺得未來在雲上所有的配置,不光是應用配置,包括基礎資源的配置也是集中化的管理的。

最後,我們對本次演講做一下小結, 我們今天介紹了大型的分散式微服務系統給配置管理帶來的挑戰,然後我們對淘寶配置中心實踐中的一些場景示例,我們基於這些示例解析了大規模生產的配置中心應該考慮的關鍵特性,以及展望了一下配置管理技術發展的未來趨勢。

來 QCon 演講一定是來表達我們自己的一個觀點或者根據我們的實踐得到的一個看法,這個觀點不一定對,或者說在你們那裡不一定對或者適用,但是這確實是我們的觀點,肺腑之言,那就是

最後配置中心這個東西,它沒有高精尖的技術,難懂的演算法,海量的數據,做這個東西只需要一個精神就夠了,那就是做一件事,把它做好!

謝謝大家。

作者介紹

郭平,淘寶花名:坤宇,現就職於阿里巴巴中間件技術部,軟負載與配置中心產品線負責人,高級技術專家,近 16 年軟體從業經歷,曾是國內 JEE&Oracle 中間件領域資深專家,在大中型企業級複雜系統架構和構建領域有豐富的實戰經驗和血淚教訓,個人在職業生涯中,做過測試,跑過售前,做過諮詢,干過售後,雖然帶著技術團隊,但現在仍然是一個碼農的「芯」,平時熱愛鑽研各種技術,對深入體驗技術如何更好的助推商業成功,拓展商業邊界尤為著迷。

今日薦文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 InfoQ 的精彩文章:

1月20 日,2017 年技術圈年會上海站邀你共聚
2017互聯網技術人薪資報告,你搬的磚夠繞地球幾圈?

TAG:InfoQ |