自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一篇帶你從零開始學(xué)微服務(wù)

開發(fā) 架構(gòu)
雖然現(xiàn)在開源的微服務(wù)框架有很多,各種編程語言的都有,花上幾個小時搭建一套可運行的開發(fā)環(huán)境也并不是一件難事。但畢竟微服務(wù)涉及的組件還是挺多的,相比于單體架構(gòu)來說,復(fù)雜度提升了不少。

說起微服務(wù),大家應(yīng)該并不陌生,不只是一線大廠,很多中小規(guī)模團(tuán)隊也已經(jīng)將這項技術(shù)引入并在實際業(yè)務(wù)中落地。

那作為一名開發(fā)人員,應(yīng)該如何學(xué)習(xí)微服務(wù)呢?

雖然現(xiàn)在開源的微服務(wù)框架有很多,各種編程語言的都有,花上幾個小時搭建一套可運行的開發(fā)環(huán)境也并不是一件難事。但畢竟微服務(wù)涉及的組件還是挺多的,相比于單體架構(gòu)來說,復(fù)雜度提升了不少。

不知道你有沒有和我一樣的困擾,有時候想要深入學(xué)習(xí)一下,但卻不知道從什么地方入手,結(jié)果就是對其了解只是浮于表面。

所以我最近看了極客時間的專欄《從 0 開始學(xué)微服務(wù)》,覺得作為入門還是不錯的。

同時,我總結(jié)了專欄中的部分內(nèi)容,并加入一些自己的思考,形成了這篇文章。算是學(xué)習(xí)微服務(wù)的一個大綱,然后再按照這個大綱去深入學(xué)習(xí),不斷充實這套技術(shù)體系。

好了,下面正文開始。

什么是微服務(wù)

微服務(wù)是指開發(fā)應(yīng)用所用的一種架構(gòu)形式。通過微服務(wù),可將大型應(yīng)用分解成多個獨立的組件,其中每個組件都有各自的責(zé)任領(lǐng)域。在處理一個用戶請求時,基于微服務(wù)的應(yīng)用可能會調(diào)用許多內(nèi)部微服務(wù)來共同生成其響應(yīng)。

圖片

微服務(wù)的特點:

  1. 服務(wù)拆分粒度: 小到一個子模塊,只要該模塊依賴的資源與其他模塊都沒有關(guān)系,那么就可以拆分為一個微服務(wù)。
  2. 服務(wù)獨立部署: 每個微服務(wù)都嚴(yán)格遵循獨立打包部署的準(zhǔn)則,互不影響。比如一臺物理機上可以部署多個 Docker 實例,每個 Docker 實例可以部署一個微服務(wù)的代碼。
  3. 服務(wù)獨立維護(hù): 每個微服務(wù)都可以交由一個小團(tuán)隊甚至個人來開發(fā)、測試、發(fā)布和運維,并對整個生命周期負(fù)責(zé)。
  4. 服務(wù)治理能力要求高: 因為拆分為微服務(wù)之后,服務(wù)的數(shù)量變多,因此需要有統(tǒng)一的服務(wù)治理平臺,來對各個服務(wù)進(jìn)行管理。

服務(wù)發(fā)布和引用

想要構(gòu)建微服務(wù),首先要解決的問題是,服務(wù)提供者如何發(fā)布一個服務(wù),服務(wù)消費者如何引用這個服務(wù)。具體來說,就是這個服務(wù)的接口名是什么?調(diào)用這個服務(wù)需要傳遞哪些參數(shù)?接口的返回值是什么類型?以及一些其他接口描述信息。

圖片

最常見的服務(wù)發(fā)布和引用的方式有三種:

  • RESTful API
  • XML 配置
  • IDL 文件

RESTful API

這種方式就比較常見了,主要被用作 HTTP 或者 HTTPS 協(xié)議的接口定義,即使在非微服務(wù)架構(gòu)體系下,也被廣泛采用。而且學(xué)習(xí)成本低,比較適合用作跨業(yè)務(wù)平臺之間的服務(wù)協(xié)議。

XML 配置

這種方式下需要在服務(wù)提供者和服務(wù)消費者之間維持一份對等的 XML 配置文件,來保證服務(wù)調(diào)用。比如提供者維護(hù) server.xml,消費者維護(hù) client.xml。

在接口變更時,需要同時修改這兩個接口描述文件。

IDL 文件

IDL 就是接口描述語言(interface description language)的縮寫,通過一種中立的方式來描述接口,使得在不同的平臺上運行的對象和不同語言編寫的程序可以相互通信交流。

也就是說 IDL 主要是用作跨語言平臺的服務(wù)之間的調(diào)用,有兩種最常用的 IDL:一個是 Facebook 開源的 Thrift 協(xié)議,另一個是 Google 開源的 gRPC 協(xié)議。

小結(jié)

每種方式都有各自的優(yōu)缺點,具體應(yīng)該如何選擇,需要根據(jù)自身的業(yè)務(wù)特點。

描述方式

使用場景

缺點

RESTful API

跨語言平臺,組織內(nèi)外皆可

使用 HTTP 作為通信協(xié)議,相比于 TCP,性能較差

XML 配置

Java 平臺,一般用于組織內(nèi)部

不支持跨語言平臺

IDL 文件

跨語言平臺,組織內(nèi)外皆可

修改和刪除字段不支持向前兼容

注冊中心

服務(wù)拆分之后,服務(wù)的提供者和消費者分別運行在不同的機器上,而且服務(wù)眾多,有幾十個,甚至上百個。這就涉及到一個問題,消費者如何才能找到服務(wù)提供者,這也是注冊中心需要解決的問題。

圖片

注冊中心需要實現(xiàn)哪些 API?

  • 服務(wù)注冊接口: 服務(wù)提供者通過調(diào)用服務(wù)注冊接口來完成服務(wù)注冊。
  • 服務(wù)反注冊接口: 服務(wù)提供者通過調(diào)用服務(wù)反注冊接口來完成服務(wù)注銷。
  • 心跳匯報接口: 服務(wù)提供者通過調(diào)用心跳匯報接口完成節(jié)點存活狀態(tài)上報。
  • 服務(wù)訂閱接口: 服務(wù)消費者通過調(diào)用服務(wù)訂閱接口完成服務(wù)訂閱,獲取可用的服務(wù)提供者節(jié)點列表。
  • 服務(wù)變更查詢接口: 服務(wù)消費者通過調(diào)用服務(wù)變更查詢接口,獲取最新的可用服務(wù)節(jié)點列表。

除此之外,為了便于管理,注冊中心還必須提供一些后臺管理的 API,例如:

  • 服務(wù)查詢接口: 查詢注冊中心當(dāng)前注冊了哪些服務(wù)信息。
  • 服務(wù)修改接口: 修改注冊中心中某一服務(wù)的信息。

配置中心

在拆分為微服務(wù)架構(gòu)前,單體應(yīng)用只需要管理一套配置;而拆分為微服務(wù)后,每一個系統(tǒng)都有自己的配置,并且都各不相同,而且因為服務(wù)治理的需要,有些配置還需要能夠動態(tài)改變,以達(dá)到動態(tài)降級、切流量、擴縮容等目的,所以如何管理配置十分重要。

圖片

配置中心一般包含下面幾個功能:

  • 配置注冊
  • 配置反注冊
  • 配置查看
  • 配置變更訂閱

API 網(wǎng)關(guān)

API 網(wǎng)關(guān)可以被視為一種充當(dāng)應(yīng)用程序服務(wù)和不同客戶端之間的中間件,可以管理許多事情,例如:

  • 路由: 網(wǎng)關(guān)接收所有 API 請求并將它們轉(zhuǎn)發(fā)到目標(biāo)服務(wù)。
  • 記錄日志: 能夠在一處記錄所有請求。
  • 權(quán)限認(rèn)證: 檢查用戶是否有資格訪問該服務(wù),如果沒有,可以拒絕該請求。
  • 性能分析: 估計每個請求的執(zhí)行時間并檢查性能瓶頸。
  • 緩存: 通過在網(wǎng)關(guān)級別處理緩存,可以降低服務(wù)的流量壓力。

事實上,它是作為一個反向代理工作的,客戶端只需要知道系統(tǒng)的網(wǎng)關(guān),應(yīng)用服務(wù)就可以隱藏起來,不直接向其他系統(tǒng)暴露。

圖片

如果沒有 API 網(wǎng)關(guān),可能需要在每個服務(wù)中做一些橫切關(guān)注點,比如想記錄服務(wù)的請求和響應(yīng)。此外,如果應(yīng)用程序由多個服務(wù)組成,客戶端需要知道每個服務(wù)地址,并且在更改服務(wù)地址的情況下,需要更新多個地方。

負(fù)載均衡

微服務(wù)架構(gòu)擁有很好的可擴展性,我們能夠通過運行更多服務(wù)實例來處理更多請求,但問題是,哪個實例應(yīng)該接收請求,或客戶端如何知道哪個服務(wù)實例應(yīng)該處理請求?

這些問題的答案是負(fù)載均衡。負(fù)載均衡是高可用網(wǎng)絡(luò)基礎(chǔ)架構(gòu)的關(guān)鍵組件,通常用于將工作負(fù)載分布到多個服務(wù)器來提高網(wǎng)站、應(yīng)用、數(shù)據(jù)庫或其他服務(wù)的性能和可靠性。

圖片

常用的負(fù)載均衡算法有一下五種:

隨機算法

顧名思義就是從可用的服務(wù)節(jié)點中,隨機挑選一個節(jié)點來訪問。

實現(xiàn)比較簡單,在請求量遠(yuǎn)超可用服務(wù)節(jié)點數(shù)量的情況下,各個服務(wù)節(jié)點被訪問的概率基本相同,主要應(yīng)用在各個服務(wù)節(jié)點的性能差異不大的情況下。

輪詢算法

跟隨機算法類似,各個服務(wù)節(jié)點被訪問的概率也基本相同,也主要應(yīng)用在各個服務(wù)節(jié)點性能差異不大的情況下。

加權(quán)輪詢算法

在輪詢算法基礎(chǔ)上的改進(jìn),可以通過給每個節(jié)點設(shè)置不同的權(quán)重來控制訪問的概率,因此主要被用在服務(wù)節(jié)點性能差異比較大的情況。

比如經(jīng)常會出現(xiàn)一種情況,因為采購時間的不同,新的服務(wù)節(jié)點的性能往往要高于舊的節(jié)點,這個時候可以給新的節(jié)點設(shè)置更高的權(quán)重,讓它承擔(dān)更多的請求,充分發(fā)揮新節(jié)點的性能優(yōu)勢。

最少活躍連接算法

與加權(quán)輪詢算法預(yù)先定義好每個節(jié)點的訪問權(quán)重不同,采用最少活躍連接算法,客戶端同服務(wù)端節(jié)點的連接數(shù)是在時刻變化的,理論上連接數(shù)越少代表此時服務(wù)端節(jié)點越空閑,選擇最空閑的節(jié)點發(fā)起請求,能獲取更快的響應(yīng)速度。

尤其在服務(wù)端節(jié)點性能差異較大,而又不好做到預(yù)先定義權(quán)重時,采用最少活躍連接算法是比較好的選擇。

一致性 hash 算法

因為它能夠保證同一個客戶端的請求始終訪問同一個服務(wù)節(jié)點,所以適合服務(wù)端節(jié)點處理不同客戶端請求差異較大的場景。

比如服務(wù)端緩存里保存著客戶端的請求結(jié)果,如果同一客戶端一直訪問一個服務(wù)節(jié)點,那么就可以一直從緩存中獲取數(shù)據(jù)。

服務(wù)監(jiān)控

不管是單體架構(gòu),還是微服務(wù)架構(gòu),監(jiān)控都是必不可少的。只不過微服務(wù)架構(gòu)更加復(fù)雜,監(jiān)控起來也就更加不容易。

對于一個微服務(wù)來說,必須明確要監(jiān)控哪些對象、哪些指標(biāo),并且還要從不同的維度進(jìn)行監(jiān)控,才能掌握微服務(wù)的調(diào)用情況。

圖片

監(jiān)控對象

監(jiān)控對象可以分為四個層次,由上到下可歸納為:

  • 用戶端監(jiān)控: 通常是指業(yè)務(wù)直接對用戶提供的功能的監(jiān)控。
  • 接口監(jiān)控: 通常是指業(yè)務(wù)提供的功能所依賴的具體 RPC 接口的監(jiān)控。
  • 資源監(jiān)控: 通常是指某個接口依賴的資源的監(jiān)控。
  • 基礎(chǔ)監(jiān)控: 通常是指對服務(wù)器本身的健康狀況的監(jiān)控。主要包括 CPU 利用率、內(nèi)存使用量、I/O 讀寫量、網(wǎng)卡帶寬等。

監(jiān)控指標(biāo)

搞清楚要監(jiān)控的對象之后,需要監(jiān)控具體哪些指標(biāo)呢?

  • 請求量: 請求量監(jiān)控分為兩個維度,一個是實時請求量,一個是統(tǒng)計請求量。實時請求量用 QPS(Queries Per Second)即每秒查詢次數(shù)來衡量,它反映了服務(wù)調(diào)用的實時變化情況。統(tǒng)計請求量一般用 PV(Page View)即一段時間內(nèi)用戶的訪問量來衡量,比如一天的 PV 代表了服務(wù)一天的請求量,通常用來統(tǒng)計報表。
  • 響應(yīng)時間: 大多數(shù)情況下,可以用一段時間內(nèi)所有調(diào)用的平均耗時來反映請求的響應(yīng)時間。但它只代表了請求的平均快慢情況,有時候我們更關(guān)心慢請求的數(shù)量。為此需要把響應(yīng)時間劃分為多個區(qū)間,比如 0~10ms、10ms~50ms、50ms~100ms、100ms~500ms、500ms 以上這五個區(qū)間,其中 500ms 以上這個區(qū)間內(nèi)的請求數(shù)就代表了慢請求量,正常情況下,這個區(qū)間內(nèi)的請求數(shù)應(yīng)該接近于 0;在出現(xiàn)問題時,這個區(qū)間內(nèi)的請求數(shù)會大幅增加,可能平均耗時并不能反映出這一變化。
  • 錯誤率: 錯誤率的監(jiān)控通常用一段時間內(nèi)調(diào)用失敗的次數(shù)占調(diào)用總次數(shù)的比率來衡量,比如對于接口的錯誤率一般用接口返回錯誤碼為 503 的比率來表示。

監(jiān)控維度

一般來說,要從多個維度來對業(yè)務(wù)進(jìn)行監(jiān)控,包括下面幾個維度:

  • 全局維度: 從整體角度監(jiān)控對象的的請求量、平均耗時以及錯誤率,全局維度的監(jiān)控一般是為了讓你對監(jiān)控對象的調(diào)用情況有個整體了解。
  • 分機房維度: 一般為了業(yè)務(wù)的高可用性,服務(wù)通常部署在不止一個機房,因為不同機房地域的不同,同一個監(jiān)控對象的各種指標(biāo)可能會相差很大,所以需要深入到機房內(nèi)部去了解。
  • 單機維度: 即便是在同一個機房內(nèi)部,可能由于采購年份和批次的不同,位于不同機器上的同一個監(jiān)控對象的各種指標(biāo)也會有很大差異。一般來說,新采購的機器通常由于成本更低,配置也更高,在同等請求量的情況下,可能表現(xiàn)出較大的性能差異,因此也需要從單機維度去監(jiān)控同一個對象。
  • 時間維度: 同一個監(jiān)控對象,在每天的同一時刻各種指標(biāo)通常也不會一樣,這種差異要么是由業(yè)務(wù)變更導(dǎo)致,要么是運營活動導(dǎo)致。為了了解監(jiān)控對象各種指標(biāo)的變化,通常需要與一天前、一周前、一個月前,甚至三個月前做比較。
  • 核心維度: 業(yè)務(wù)上一般會依據(jù)重要性程度對監(jiān)控對象進(jìn)行分級,最簡單的是分成核心業(yè)務(wù)和非核心業(yè)務(wù)。核心業(yè)務(wù)和非核心業(yè)務(wù)在部署上必須隔離,分開監(jiān)控,這樣才能對核心業(yè)務(wù)做重點保障。

服務(wù)追蹤

在調(diào)試單體應(yīng)用時,非常直觀容易。但是在微服務(wù)架構(gòu)上,因為一個請求可能會通過不同的服務(wù),而不同的服務(wù)又不在一個地方,這使得調(diào)試和跟蹤變得困難。

所以服務(wù)追蹤是分布式系統(tǒng)中必不可少的功能,它能夠幫助我們查詢一次用戶請求在系統(tǒng)中的具體執(zhí)行路徑,以及每一條路徑的上下游的詳細(xì)情況,對于追查問題十分有用。

它的核心理念就是調(diào)用鏈:通過一個全局唯一的 ID 將分布在各個服務(wù)節(jié)點上的同一次請求串聯(lián)起來,從而還原原有的調(diào)用關(guān)系,可以追蹤系統(tǒng)問題、分析調(diào)用數(shù)據(jù)并統(tǒng)計各種系統(tǒng)指標(biāo)。


  • traceId: 用于標(biāo)識某一次具體的請求 ID。當(dāng)用戶的請求進(jìn)入系統(tǒng)后,會在 RPC 調(diào)用網(wǎng)絡(luò)的第一層生成一個全局唯一的 traceId,并且會隨著每一層的 RPC 調(diào)用,不斷往后傳遞,這樣的話通過 traceId 就可以把一次用戶請求在系統(tǒng)中調(diào)用的路徑串聯(lián)起來。
  • spanId: 用于標(biāo)識一次 RPC 調(diào)用在分布式請求中的位置。當(dāng)用戶的請求進(jìn)入系統(tǒng)后,處在 RPC 調(diào)用網(wǎng)絡(luò)的第一層 A 時 spanId 初始值是 0,進(jìn)入下一層 RPC 調(diào)用 B 的時候 spanId 是 0.1,繼續(xù)進(jìn)入下一層 RPC 調(diào)用 C 時 spanId 是 0.1.1,而與 B 處在同一層的 RPC 調(diào)用 E 的 spanId 是 0.2,這樣的話通過 spanId 就可以定位某一次 RPC 請求在系統(tǒng)調(diào)用中所處的位置,以及它的上下游依賴分別是誰。
  • annotation: 用于業(yè)務(wù)自定義埋點數(shù)據(jù),可以是業(yè)務(wù)感興趣的想上傳到后端的數(shù)據(jù),比如一次請求的用戶 UID。

小結(jié)一下,traceId 是用于串聯(lián)某一次請求在系統(tǒng)中經(jīng)過的所有路徑,spanId 是用于區(qū)分系統(tǒng)不同服務(wù)之間調(diào)用的先后關(guān)系,而 annotation 是用于業(yè)務(wù)自定義一些自己感興趣的數(shù)據(jù),在上傳 traceId 和 spanId 這些基本信息之外,添加一些自己感興趣的信息。

故障處理

系統(tǒng)故障是避免不了的,雖然微服務(wù)架構(gòu)做了服務(wù)拆分,不至于像單體架構(gòu)那樣整體崩潰,但由于其整體復(fù)雜度也大大提升,故障處理也更加困難。

圖片

限流

顧名思義,限流就是限制流量。通常情況下,系統(tǒng)能夠承載的流量根據(jù)集群規(guī)模的大小是固定的,可以稱之為系統(tǒng)的最大容量。

當(dāng)真實流量超過了系統(tǒng)的最大容量后,就會導(dǎo)致系統(tǒng)響應(yīng)變慢,服務(wù)調(diào)用出現(xiàn)大量超時,反映給用戶的感覺就是卡頓、無響應(yīng)。

所以,應(yīng)該根據(jù)系統(tǒng)的最大容量,給系統(tǒng)設(shè)置一個閾值,超過這個閾值的請求會被自動拋棄,這樣的話可以最大限度地保證系統(tǒng)提供的服務(wù)正常。

熔斷

熔斷和限流還不太一樣,上面我們可以看到限流是控制請求速率,只要還能承受,那么都會處理,但熔斷不是。

在一條調(diào)用鏈上,如果發(fā)現(xiàn)某個服務(wù)異常,比如響應(yīng)超時。那么調(diào)用者為了避免過多請求導(dǎo)致資源消耗過大,最終引發(fā)系統(tǒng)雪崩,會直接返回錯誤,而不是瘋狂調(diào)用這個服務(wù)。

降級

什么是降級呢?降級就是通過停止系統(tǒng)中的某些功能,來保證系統(tǒng)整體的可用性。

降級可以說是一種被動防御的措施,為什么這么說呢?因為它一般是系統(tǒng)已經(jīng)出現(xiàn)故障后所采取的一種止損措施。

容器化

單體應(yīng)用拆分成多個微服務(wù)后,能夠?qū)崿F(xiàn)快速開發(fā)迭代,但隨之帶來的問題是測試和運維部署成本的提升。

而容器技術(shù)正好可以很好的解決這些問題,目前最流行的當(dāng)屬 Docker 莫屬。

圖片

微服務(wù)容器化運維主要涉及到以下幾點:

  • 鏡像倉庫
  • 容器調(diào)度
  • 服務(wù)編排

鏡像倉庫

鏡像倉庫的概念其實跟 Git 代碼倉庫類似,就是有一個集中存儲的地方,把鏡像存儲在這里,在服務(wù)發(fā)布的時候,各個服務(wù)器都訪問這個集中存儲來拉取鏡像,然后啟動容器。

容器調(diào)度

這個階段主要是解決在哪些機器上啟動容器的問題,特別是規(guī)模比較大的公司,一般有物理機集群,虛擬機集群,私有云和公有云。對接這么多不同的平臺,難度還是不小的。

需要統(tǒng)一管理來自不同集群的機器權(quán)限管理、成本核算以及環(huán)境初始化等操作,這個時候就需要有一個統(tǒng)一的層來完成這個操作。

很顯然,靠人工是肯定不行的,需要搭建統(tǒng)一的部署運維平臺。

服務(wù)編排

大部分情況下,微服務(wù)之間是相互獨立的,在進(jìn)行容器調(diào)度的時候不需要考慮彼此。

但有時候也會存在一些場景,比如服務(wù) A 調(diào)度的前提必須是先有服務(wù) B,這樣的話就要求在進(jìn)行容器調(diào)度的時候,還需要考慮服務(wù)之間的依賴關(guān)系。

Service Mesh

Service Mesh 的概念最早是由 Buoyant 公司的 CEO William Morgan 提出,他給出的服務(wù)網(wǎng)格的定義是:

A service mesh is a dedicated infrastructure layer for handling service-to-service communication. It’s responsible for the reliable delivery of requests through the complex topology of services that comprise a modern, cloud native application. In practice, the service mesh is typically implemented as an array of lightweight network proxies that are deployed alongside application code, without the application needing to be aware.

被很多人定義為下一代的微服務(wù)架構(gòu)。

圖片

目前,Service Mesh 的代表產(chǎn)品當(dāng)屬 Google 和 IBM 的 lstio。

Istio 的架構(gòu)可以說由兩部分組成,分別是 Proxy 和 Control Plane。

  • Proxy: 與應(yīng)用程序部署在同一個主機上,應(yīng)用程序之間的調(diào)用都通過 Proxy 來轉(zhuǎn)發(fā),目前支持 HTTP/1.1、HTTP/2、gRPC 以及 TCP 請求。
  • Control Plane: 與 Proxy 通信,來實現(xiàn)各種服務(wù)治理功能,包括三個基本組件:Pilot、Mixer 以及 Citadel。
責(zé)任編輯:姜華 來源: AlwaysBeta
相關(guān)推薦

2021-01-08 10:24:32

Python項目基礎(chǔ)

2022-02-22 08:15:59

微服務(wù)架構(gòu)單體架構(gòu)

2024-05-21 09:26:54

微服務(wù)DDD建模架構(gòu)

2015-10-22 14:32:44

微服務(wù)PaaS應(yīng)用開發(fā)

2024-08-01 11:21:52

2022-02-16 22:57:57

Mitmproxy抓包工具

2024-12-09 09:44:34

機器學(xué)習(xí)模型分類器

2021-05-20 06:57:16

RabbitMQ開源消息

2023-04-20 08:00:00

ES搜索引擎MySQL

2015-08-24 14:59:06

Java線程

2015-08-26 10:01:20

iOS開發(fā)

2024-07-30 09:22:44

PostgreSQL數(shù)據(jù)庫工具

2015-11-17 16:11:07

Code Review

2018-04-18 07:01:59

Docker容器虛擬機

2019-01-18 12:39:45

云計算PaaS公有云

2020-07-02 15:32:23

Kubernetes容器架構(gòu)

2024-12-06 17:02:26

2021-06-16 08:28:25

unary 方法函數(shù)技術(shù)

2022-03-10 08:31:51

REST接口規(guī)范設(shè)計Restful架構(gòu)

2025-01-17 07:00:00

點贊
收藏

51CTO技術(shù)棧公眾號