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

一篇講解“服務(wù)調(diào)用”的良心之作!

網(wǎng)絡(luò) 通信技術(shù) 開發(fā)工具
這篇文章將我所了解到的解決“服務(wù)調(diào)用”相關(guān)的技術(shù)演進(jìn)歷史簡述一下,純粹一篇科普文。

這篇文章將我所了解到的解決“服務(wù)調(diào)用”相關(guān)的技術(shù)演進(jìn)歷史簡述一下,純粹一篇科普文。

[[270557]]

圖片來自 Pexels

本文專注于演化過程中每一步的為什么(Why)和是什么(What)上面,盡量不在技術(shù)細(xì)節(jié)(How)上面做太多深入。

服務(wù)的三要素

一般而言,一個網(wǎng)絡(luò)服務(wù)包括以下的三個要素:

  • 地址:調(diào)用方根據(jù)地址訪問到網(wǎng)絡(luò)接口。地址包括以下要素:IP地址、服務(wù)端口、服務(wù)協(xié)議(TCP、UDP,etc)。
  • 協(xié)議格式:指的是該協(xié)議都有哪些字段,由接口提供者與協(xié)議調(diào)用者協(xié)商之后確定下來。
  • 協(xié)議名稱:或者叫協(xié)議類型,因?yàn)樵谕粋€服務(wù)監(jiān)聽端口上面,可能同時(shí)提供多種接口服務(wù)于調(diào)用方,這時(shí)候需要協(xié)議類型(名稱)來區(qū)分不同的網(wǎng)絡(luò)接口。

需要說明在服務(wù)地址中:

  • IP 地址提供了在互聯(lián)網(wǎng)上找到這臺機(jī)器的憑證。
  • 協(xié)議以及服務(wù)端口提供了在這臺機(jī)器上找到提供服務(wù)的進(jìn)程的憑證。

這都屬于 TCP/IP 協(xié)議棧的知識點(diǎn),不在這里深入詳述。這里還需要對涉及到服務(wù)相關(guān)的一些名詞做解釋:

  • 服務(wù)實(shí)例:服務(wù)對應(yīng)的 IP 地址加端口的簡稱。需要訪問服務(wù)的時(shí)候,需要先尋址知道該服務(wù)每個運(yùn)行實(shí)例的地址加端口,然后才能建立連接進(jìn)行訪問。
  • 服務(wù)注冊:某個服務(wù)實(shí)例宣稱自己提供了哪些服務(wù),即某個 IP 地址+端口都提供了哪些服務(wù)接口。
  • 服務(wù)發(fā)現(xiàn):調(diào)用方通過某種方式找到服務(wù)提供方,即知道服務(wù)運(yùn)行的 IP 地址加端口。

基于 IP 地址的調(diào)用

最初的網(wǎng)絡(luò)服務(wù),通過原始的 IP 地址暴露給調(diào)用者。這種方式有以下的問題:

  • IP 地址是難于記憶并且無意義的。
  • 另外,從上面的服務(wù)三要素可以看到,IP 地址其實(shí)是一個很底層的概念,直接對應(yīng)了一臺機(jī)器上的一個網(wǎng)絡(luò)接口,如果直接使用IP地址進(jìn)行尋址,更換機(jī)器就變的很麻煩。

“盡量不使用過于底層的概念來提供服務(wù)”,是這個演化流程中的重要原則,好比在今天已經(jīng)很少能夠看到直接用匯編語言編寫代碼的場景了。

取而代之的,就是越來越多的抽象,本文中就展現(xiàn)了服務(wù)調(diào)用這一領(lǐng)域在這個過程中的演進(jìn)流程。

在現(xiàn)在除非是測試階段,否則已經(jīng)不能直接以 IP 地址的形式將服務(wù)提供出去了。

域名系統(tǒng)

前面的 IP 地址是給主機(jī)做為路由器尋址的數(shù)字型標(biāo)識,并不好記憶。

此時(shí)產(chǎn)生了域名系統(tǒng),與單純提供 IP 地址相比,域名系統(tǒng)由于使用有意義的域名來標(biāo)識服務(wù),所以更容易記憶。另外,還可以更改域名所對應(yīng)的 IP 地址,這為變換機(jī)器提供了便利。

有了域名之后,調(diào)用方需要訪問某個網(wǎng)絡(luò)服務(wù)時(shí),首先到域名地址服務(wù)中,根據(jù) DNS 協(xié)議將域名解析為相應(yīng)的 IP 地址,再根據(jù)返回的 IP 地址來訪問服務(wù)。

從這里可以看到,由于多了一步到域名地址服務(wù)查詢映射 IP 地址的流程,所以多了一步解析,為了減少這一步帶來的影響,調(diào)用方會緩存解析之后的結(jié)果,在一段時(shí)間內(nèi)不過期,這樣就省去了這一步查詢的代價(jià)。

協(xié)議的接收與解析

以上通過域名系統(tǒng),已經(jīng)解決了服務(wù) IP 地址難以記憶的問題,下面來看協(xié)議格式解析方面的演進(jìn)。

一般而言,一個網(wǎng)絡(luò)協(xié)議包括兩部分:

  • 協(xié)議包頭:這里存儲協(xié)議的元信息(meta infomation),其中可能會包括協(xié)議類型、報(bào)體長度、協(xié)議格式等。

需要說明的是,包頭一般為固定大小,或者有明確的邊界(如 HTTP 協(xié)議中的 \r\n 結(jié)束符),否則無法知道包頭何時(shí)結(jié)束。

  • 協(xié)議包體:具體的協(xié)議內(nèi)容。

無論是 HTTP 協(xié)議,又或者是自定義的二進(jìn)制網(wǎng)絡(luò)協(xié)議,大體都由這兩部分組成。

由于很多時(shí)候不能一口氣接收完畢客戶端的協(xié)議數(shù)據(jù),因此在接收協(xié)議數(shù)據(jù)時(shí),一般采用狀態(tài)機(jī)來做協(xié)議數(shù)據(jù)的接收:

接收完畢了網(wǎng)絡(luò)數(shù)據(jù),在協(xié)議解析方面卻長期停滯不前。一個協(xié)議,有多個字段(field),而這些不同的字段有不同的類型,簡單的 raw 類型(如整型、字符串)還好說,但是遇到復(fù)雜的類型如字典、數(shù)組等就比較麻煩。

當(dāng)時(shí)常見的手段有以下幾種:

  • 使用 json 或者 xml 這樣的數(shù)據(jù)格式。好處是可視性強(qiáng),表達(dá)起上面的復(fù)雜類型也方便,缺陷是容易被破解,傳輸過去的數(shù)據(jù)較大。
  • 自定義二進(jìn)制協(xié)議。每個公司做大了,在這一塊難免有幾個類似的輪子。筆者見過比較典型的是所謂的 TLV 格式(Type-Length-Value)。

自定義二進(jìn)制格式最大的問題出現(xiàn)在協(xié)議聯(lián)調(diào)與協(xié)商的時(shí)候,由于可視性比較弱,有可能這邊少了一個字段那邊多了一個字段,給聯(lián)調(diào)流程帶來麻煩。

上面的問題一直到 Google 的 Protocol Buffer(以下簡稱 PB)出現(xiàn)之后才得到很大的改善。

PB 出現(xiàn)之后,也有很多類似的技術(shù)出現(xiàn),如 Thrift、MsgPack 等,不在這里闡述,將這一類技術(shù)都以 PB 來描述。

與前面的兩種手段相比,PB 具有以下的優(yōu)點(diǎn):

  • 使用 proto 格式文件來定義協(xié)議格式,proto 文件是一個典型的 DSL(domain-specific language)文件,文件中描述了協(xié)議的具體格式,每個字段都是什么類型,哪些是可選字段哪些是必選字段。

有了 proto 文件之后,C\S 兩端是通過這個文件來進(jìn)行協(xié)議的溝通交流的,而不是具體的技術(shù)細(xì)節(jié)。

  • PB 能通過 proto 文件生成各種語言對應(yīng)的序列化反序列化代碼,給跨語言調(diào)用提供了方便。
  • PB 自己能夠?qū)μ囟愋瓦M(jìn)行數(shù)據(jù)壓縮,減少數(shù)據(jù)大小。

服務(wù)網(wǎng)關(guān)

有了前面的演化之后,寫一個簡單的單機(jī)服務(wù)器已經(jīng)不難。然而,當(dāng)隨著訪問量的增大,一臺機(jī)器已經(jīng)不足以支撐所有的請求,此時(shí)就需要橫向擴(kuò)展多加一些業(yè)務(wù)服務(wù)器。

而前面通過域名訪問服務(wù)的架構(gòu)就遇到了問題:如果有多個服務(wù)實(shí)例可以提供相同的服務(wù),那么勢必需要在 DNS 的域名解析中將域名與多個地址進(jìn)行綁定。

這樣的方案就有如下的問題:

  • 如何檢查這些實(shí)例的健康情況,同時(shí)在發(fā)現(xiàn)出現(xiàn)問題的時(shí)候增刪服務(wù)實(shí)例地址?即所謂的服務(wù)高可用問題。
  • 把這些服務(wù)實(shí)例地址都暴露到外網(wǎng),會不會涉及到安全問題?即使可以解決安全問題,那么也需要每臺機(jī)器都做安全策略。
  • 由于 DNS 協(xié)議的特點(diǎn),增刪服務(wù)實(shí)例并不是實(shí)時(shí)的,有時(shí)候會影響到業(yè)務(wù)。

為了解決這些問題,就引入了反向代理網(wǎng)關(guān)這一組件。它提供如下的功能:

  • 負(fù)載均衡功能:根據(jù)某些算法將請求分派到服務(wù)實(shí)例上。
  • 提供管理功能:可以給運(yùn)維管理員增減服務(wù)實(shí)例。
  • 由于它決定了服務(wù)請求流量的走向,因此還可以做更多的其他功能:灰度引流、安全防攻擊(如訪問黑白名單、卸載 SSL 證書)等。

有四層和七層負(fù)載均衡軟件,其中四層負(fù)載均衡這里介紹 LVS,七層負(fù)載均衡介紹 Nginx。

上圖是簡易的 TCP/IP 協(xié)議棧層次圖,其中 LVS 工作在四層,即請求來到 LVS 這里時(shí)是根據(jù)四層協(xié)議來決定請求最終走到哪個服務(wù)實(shí)例。

而 Nginx 工作在七層,主要用于 HTTP 協(xié)議,即根據(jù) HTTP 協(xié)議本身來決定請求的走向。

需要說明的是,Nginx 也可以工作在四層,但是這么用的地方不是很多,可以參考 Nginx 的 Stream 模塊。

做為四層負(fù)載均衡的 LVS

由于 LVS 有好幾種工作模式,并不是每一種我都很清楚,以下表述僅針對 Full NAT 模式,下面的表述或者有誤。

LVS 有如下的組成部分:

  • Direct Server(以下簡稱 DS):前端暴露給客戶端進(jìn)行負(fù)載均衡的服務(wù)器。
  • Virtual IP 地址(以下簡稱 VIP):DS 暴露出去的 IP 地址,做為客戶端請求的地址。
  • Direct IP 地址(以下簡稱 DIP):DS 用于與 Real Server 交互的 IP 地址。
  • Real Server(以下簡稱 RS):后端真正進(jìn)行工作的服務(wù)器,可以橫向擴(kuò)展。
  • Real IP 地址(以下簡稱 RIP):RS 的地址。
  • Client IP 地址(以下簡稱 CIP):Client 的地址。

客戶端進(jìn)行請求時(shí),流程如下:

  • 使用 VIP 地址訪問 DS,此時(shí)的地址二元組為< src:CIP,DST:VIP >。
  • DS 根據(jù)自己的負(fù)載均衡算法,選擇一個 RS 將請求轉(zhuǎn)發(fā)過去,在轉(zhuǎn)發(fā)過去的時(shí)候,修改請求的源 IP 地址為 DIP 地址,讓 RS 看上去認(rèn)為是 DS 在訪問它,此時(shí)的地址二元組為
  • RS 處理并且應(yīng)答該請求,這個回報(bào)的源地址為 RS 的 RIP 地址,目的地址為 DIP 地址,此時(shí)的地址二元組為
  • DS 在收到該應(yīng)答包之后,將報(bào)文應(yīng)答客戶端,此時(shí)修改應(yīng)答報(bào)文的源地址為 VIP 地址,目的地址為 CIP 地址,此時(shí)的地址二元組為

做為七層負(fù)載均衡的 Nginx

在開始展開討論之前,需要簡單說一下正向代理和反向代理。

所謂的正向代理(proxy),我的理解就是在客戶端處的代理。如瀏覽器中的可以配置的訪問某些網(wǎng)站的代理,就屬于正向代理,但是一般而言不會說正向代理而是代理,即默認(rèn)代理都是正向的。

而反向代理(reverse proxy),就是擋在服務(wù)器端前面的代理,比如前面 LVS 中的 DS 服務(wù)器就屬于一種反向代理。

為什么需要反向代理,大體的原因有以下的考量:

  • 負(fù)載均衡:希望在這個反向代理的服務(wù)器中,將請求均衡的分發(fā)到后面的服務(wù)器中。
  • 安全:不想向客戶端暴露太多的服務(wù)器地址,統(tǒng)一接入到這個反向代理服務(wù)器中,在這里做限流、安全控制等。
  • 由于統(tǒng)一接入了客戶端的請求,所以在反向代理的接入層可以做更多的控制策略,比如灰度流量發(fā)布、權(quán)重控制等等。

反向代理與所謂的 Gateway、網(wǎng)關(guān)等,我認(rèn)為沒有太多的差異,只是叫法不同而已,做的事情都是類似的。

Nginx 應(yīng)該是現(xiàn)在用的最多的 HTTP 七層負(fù)載均衡軟件,在 Nginx 中,可以通過在配置的 Server 塊中定義一個域名,然后將該域名的請求綁定到對應(yīng)的 Upstream 中,而實(shí)現(xiàn)轉(zhuǎn)發(fā)請求到這些 Upstream 的效果。

如:

  1. upstream hello { 
  2.        server A:11001; 
  3.        server B:11001; 
  4. location / { 
  5.             root   html; 
  6.             index  index.html index.htm; 
  7.             proxy_pass http://hello; 

這是最簡單的 Nginx 反向代理配置,實(shí)際線上一個接入層背后可能有多個域名,如果配置變動的很大,每次域名以及對應(yīng)的 Upstream 的配置修改都需要人工干預(yù),效率會很慢。

這時(shí)候就要提到一個叫 DevOps 的名詞了,我的理解就是開發(fā)各種便于自動化運(yùn)維工具的工程師。

有了上面的分析,此時(shí)一個提供七層 HTTP 訪問接口的服務(wù)架構(gòu)大體是這樣的:

服務(wù)發(fā)現(xiàn)與 RPC

前面已經(jīng)解決單機(jī)服務(wù)器對外提供服務(wù)的大部分問題,來簡單回顧:

  • 域名系統(tǒng)解決了需要記住復(fù)雜的數(shù)字 IP 地址的問題。
  • PB 類軟件庫的出現(xiàn)解決協(xié)議定義解析的痛點(diǎn)。
  • 網(wǎng)關(guān)類組件解決客戶端接入以及服務(wù)器橫向擴(kuò)展等一系列問題。

然而一個服務(wù),通常并不見得只由本身提供服務(wù)就可以,服務(wù)過程中可能還涉及到查詢其他服務(wù)的流程,常見的如數(shù)據(jù)類服務(wù)如 MySQL、Redis 等。

這一類供服務(wù)內(nèi)調(diào)用查詢的服務(wù)被稱為內(nèi)部的服務(wù),通常并不直接暴露到外網(wǎng)去。

面向公網(wǎng)的服務(wù),一般都是以域名的形式提供給外部調(diào)用者,然而對于服務(wù)內(nèi)部之間的互相調(diào)用,域名形式還不夠,其原因在于:

  • DNS 服務(wù)發(fā)現(xiàn)的粒度太粗,只能到 IP 地址級別,而服務(wù)的端口還需要用戶自己維護(hù)。
  • 對于服務(wù)的健康狀況的檢查,DNS 的檢查還不夠,需要運(yùn)維的參與。
  • DNS 對于服務(wù)狀態(tài)的收集很欠缺,而服務(wù)狀態(tài)最終應(yīng)該是反過來影響服務(wù)被調(diào)用情況的。
  • DNS 的變更需要人工的參與,不夠智能以及自動化。

綜上,內(nèi)網(wǎng)間的服務(wù)調(diào)用,通常而言會自己實(shí)現(xiàn)一套“服務(wù)發(fā)現(xiàn)”類的系統(tǒng),其包括以下幾個組件:

  • 服務(wù)發(fā)現(xiàn)系統(tǒng):用于提供服務(wù)的尋址、注冊能力,以及對服務(wù)狀態(tài)進(jìn)行統(tǒng)計(jì)匯總,根據(jù)服務(wù)情況更改服務(wù)的調(diào)用情況。

比如,某個服務(wù)實(shí)例的響應(yīng)慢了,此時(shí)分配給該實(shí)例的流量響應(yīng)的就會少一些。

而由于這個系統(tǒng)能提供服務(wù)的尋址能力,所以一些尋址策略就可以在這里做,比如灰度某些特定的流量只能到某些特定的實(shí)例上,比如可以配置每個實(shí)例的流量權(quán)重等。

  • 一套與該服務(wù)系統(tǒng)搭配使用的 RPC 庫。

RPC 庫提供以下功能:

  • 服務(wù)提供方:使用 RPC 庫注冊自己的服務(wù)到服務(wù)發(fā)現(xiàn)系統(tǒng),另外上報(bào)自己的服務(wù)情況。
  • 服務(wù)調(diào)用方:使用 RPC 庫進(jìn)行服務(wù)尋址,實(shí)時(shí)從服務(wù)發(fā)現(xiàn)系統(tǒng)那邊獲取最新的服務(wù)調(diào)度策略。
  • 提供協(xié)議的序列化、反序列化功能,負(fù)載均衡的調(diào)用策略、熔斷限流等安全訪問策略,這部分對于服務(wù)的提供方以及調(diào)用方都適用。

有了這套服務(wù)發(fā)現(xiàn)系統(tǒng)以及搭配使用的 RPC 庫之后,來看看現(xiàn)在的服務(wù)調(diào)用是什么樣的:

  • 寫業(yè)務(wù)邏輯的,再也不用關(guān)注服務(wù)地址、協(xié)議解析、服務(wù)調(diào)度、自身服務(wù)情況上報(bào)等等與業(yè)務(wù)邏輯本身并沒有太多關(guān)系的工作,專注于業(yè)務(wù)邏輯即可。
  • 服務(wù)發(fā)現(xiàn)系統(tǒng)一般還有與之搭配的管理后臺界面,可以通過這里對服務(wù)的策略進(jìn)行修改查看等操作。
  • 對應(yīng)的還會有服務(wù)監(jiān)控系統(tǒng),對應(yīng)的這是一臺實(shí)時(shí)采集服務(wù)數(shù)據(jù)進(jìn)行計(jì)算的系統(tǒng),有了這套系統(tǒng)服務(wù)質(zhì)量如何一目了然。
  • 服務(wù)健康狀態(tài)的檢查完全自動化,在狀況不好的時(shí)候?qū)Ψ?wù)進(jìn)行降級處理,人工干預(yù)變少,更加智能以及自動化。

現(xiàn)在服務(wù)的架構(gòu)又演進(jìn)成了這樣:

Service Mesh

架構(gòu)發(fā)展到上面的程度,實(shí)際上已經(jīng)能夠解決大部分的問題了。這兩年又出現(xiàn)了一個很火的概念:Service Mesh,中文翻譯為“服務(wù)網(wǎng)格”,來看看它又能解決什么問題。

前面的服務(wù)發(fā)現(xiàn)系統(tǒng)中,需要一個與之配套的 RPC 庫,然而這又會有如下的問題:

  • 如果需要支持多語言,該怎么做?每個語言實(shí)現(xiàn)一個對應(yīng)的 RPC 庫嗎?
  • 庫的升級很麻煩,比如 RPC 庫本身出了安全漏洞,比如需要升級版本,一般推動業(yè)務(wù)方去做這個升級是很難的,尤其是系統(tǒng)做大了之后。

可以看到,由于 RPC 庫是嵌入到進(jìn)程之中的組件,所以以上問題很麻煩,于是就想出了一個辦法:將原先的一個進(jìn)程拆分成兩個進(jìn)程。

如下圖所示:

在服務(wù) Mesh 化之前,服務(wù)調(diào)用方實(shí)例通過自己內(nèi)部的 RPC 庫來與服務(wù)提供方實(shí)例進(jìn)行通信。

在服務(wù) Mesh 化之后,會與服務(wù)調(diào)用方同機(jī)部署一個 Local Proxy 也就是 Service Mesh 的 Proxy。

此時(shí)服務(wù)調(diào)用的流量會先走到這個 Proxy,再由它完成原先 RPC 庫響應(yīng)的工作。

至于如何實(shí)現(xiàn)這個流量的劫持,答案是采用 Iptables,將特定端口的流量轉(zhuǎn)發(fā)到 Proxy 上面即可。

有了這一層的分拆,將業(yè)務(wù)服務(wù)與負(fù)責(zé) RPC 庫作用的 Proxy 分開來,上面的兩個痛點(diǎn)問題就變成了對每臺物理機(jī)上面的 Mesh Proxy 的升級維護(hù)問題。

多語言也不是問題了,因?yàn)槎际峭ㄟ^網(wǎng)絡(luò)調(diào)用完成的 RPC 通信,而不是進(jìn)程內(nèi)使用 RPC 庫。

然而這個方案并不是什么問題都沒有的,最大的問題在于,多了這一層的調(diào)用之后,勢必有影響原來的響應(yīng)時(shí)間。

截止目前(2019 年 6 月),Service Mesh 仍然還是一個概念大于實(shí)際的產(chǎn)品。

從上面的演進(jìn)歷史可以看到,所謂的“中間層理論”,即“Any problem in computer science can be solved by another layer of indirection(計(jì)算機(jī)科學(xué)領(lǐng)域的任何問題都可以通過增加一個間接的中間層來解決)”在這個過程中被廣泛使用。

比如為了解決 IP 地址難于記憶的問題,引入了域名系統(tǒng),比如為了解決負(fù)載均衡問題引入了網(wǎng)關(guān),等等。

然而每引入一個中間層,勢必帶來另外的影響,比如 Service Mesh 多一次到 Proxy 的調(diào)用,如何權(quán)衡又是另外的問題了。

另外,回到最開始的服務(wù)三要素中,可以看到整個演化的歷史也是逐漸屏蔽了下層組件的流程,比如:

  • 域名的出現(xiàn)屏蔽了 IP 地址。
  • 服務(wù)發(fā)現(xiàn)系統(tǒng)屏蔽協(xié)議及端口號。
  • PB 類序列化庫屏蔽了使用者自己對協(xié)議的解析。

可以看到,演進(jìn)流程讓業(yè)務(wù)開發(fā)者更加專注在業(yè)務(wù)邏輯上,這類的演進(jìn)流程不只發(fā)生在今天,也不會僅僅發(fā)生在今天,未來類似的演進(jìn)也將再次發(fā)生。

作者:codedump

簡介:多年從事互聯(lián)網(wǎng)服務(wù)器后臺開發(fā)工作??稍L問作者博客:https://www.codedump.info/,閱讀更多文章。

 

責(zé)任編輯:武曉燕 來源: 高可用架構(gòu)
相關(guān)推薦

2021-10-11 11:08:33

HDFS快照系統(tǒng)

2021-09-05 07:55:36

Lsm核心實(shí)現(xiàn)

2024-01-09 12:06:55

MVCC并發(fā)控制MySQL

2019-04-26 13:25:06

服務(wù)器開發(fā)工具

2021-03-10 08:54:44

芯片網(wǎng)絡(luò)芯片RTL8201

2021-09-15 19:05:16

數(shù)據(jù)開源項(xiàng)目

2023-02-20 09:55:00

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

2015-10-22 14:32:44

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

2024-05-09 09:41:45

2021-07-12 06:11:14

SkyWalking 儀表板UI篇

2022-10-26 07:39:36

MVCC數(shù)據(jù)庫RR

2022-12-19 08:14:30

注解開發(fā)配置

2022-01-02 08:43:46

Python

2021-05-20 06:57:16

RabbitMQ開源消息

2023-04-20 08:00:00

ES搜索引擎MySQL

2022-02-07 11:01:23

ZooKeeper

2021-08-01 07:19:16

語言OpenrestyNginx

2022-06-30 22:53:18

數(shù)據(jù)結(jié)構(gòu)算法

2021-08-11 07:02:21

npm包管理器工具

2021-10-26 10:40:26

代理模式虛擬
點(diǎn)贊
收藏

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