久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

RESTful API、gRPC 和 GraphQL 有何不同,,如何正確地做技術(shù)選型,?

 正合叔 2021-08-28

圖片

轉(zhuǎn)載自:EAWorld

前言:

架構(gòu)師的主要活動是做出正確的技術(shù)決策。選擇合適的API是一項(xiàng)重要的技術(shù)決策,。那么今天就看看API的選擇問題,。
應(yīng)用程序編程接口(API)是一種計算接口,它定義了多個軟件中介之間的交互,。它定義了可以進(jìn)行的調(diào)用或請求的類型,,如何進(jìn)行調(diào)用,應(yīng)使用的數(shù)據(jù)格式,,遵循的約定等,。它還可以提供擴(kuò)展機(jī)制,以便用戶可以以各種方式擴(kuò)展現(xiàn)有功能,。在不同程度上,。API可以是完全定制的,特定于組件,,也可以基于行業(yè)標(biāo)準(zhǔn)進(jìn)行設(shè)計以確?;ゲ僮餍浴S行〢PI必須記錄在案,,而其它API則經(jīng)過設(shè)計,,以便可以“查詢”它們以確定支持的功能。由于其他組件/系統(tǒng)僅依賴于API,,因此提供API的系統(tǒng)可以(理想地)在API的“后面”更改其內(nèi)部詳細(xì)信息,,而不會影響其用戶。
正如上述的定義所述,API提供了多個軟件之間的交互,。所以我們這里強(qiáng)調(diào)的是交互性,。我們在使用任何的語言開發(fā)一個應(yīng)用的時候,都會提供內(nèi)部的基于該語言的API,,這種內(nèi)部的API不是我們今天要討論的內(nèi)容,,因?yàn)檫@種內(nèi)部的交互不涉及到軟件之間。我們今天要討論的API主要要涉及到系統(tǒng)之間的交互,。對于具體應(yīng)用而言,,更多是進(jìn)程之間(本機(jī)),主機(jī)之間(本網(wǎng)絡(luò)),,服務(wù)之間(可能跨域廣域網(wǎng))的交互,。

目錄:

1、CORBA

2,、XML-RPC / SOAP

3,、REST

4、GraphQL

5,、gRPC


最早在Unix/Linux的編程領(lǐng)域,,提供了進(jìn)程間通信的手段,例如:管道,,信號量,,消息隊列,套接字(Socket)等,。如果你的應(yīng)用是由不同語言編寫的,,那么這里只能選擇Socket通信作為應(yīng)用之間的API手段。但是Socket通信是一種非常低Level的通信手段,,它以底層的數(shù)據(jù)包作為抽象和通信內(nèi)容,,很難維護(hù)和使用。

當(dāng)然還有一些其它的系統(tǒng)間通信的手段例如通過共享文件或者FTP的方式,,同樣面臨著各種不便。我們希望提供一種更高級的交互手段,,直接和我的應(yīng)用的抽象交互,,這些抽象可能是方法,函數(shù)和對象,。于是就有了各種支撐這些需求的API技術(shù),。

早期的進(jìn)程間通信技術(shù)包括:

  • DCOM ( Distributed Component Object Model )分布式組件對象模型,這個是微軟的技術(shù),,只能用于Windows平臺,, 通過網(wǎng)絡(luò)實(shí)現(xiàn)遠(yuǎn)程對象間的通信

  • RMI ( Remote Method Call) Java的遠(yuǎn)程方法調(diào)用,這個是Java自己的RPC,只能用于Java應(yīng)用之間的遠(yuǎn)程調(diào)用,。

  • JNI Java的本地接口,, 支持Java應(yīng)用調(diào)用本地方法,這個是跨越語言障礙的,,但是僅僅局限于Java應(yīng)用調(diào)用其它的本地應(yīng)用,,不具備互操作性,是個單向通道,。

1.CORBA

在1991年一種名叫CORBA ( Common Object Request Broker Architecture ) 的技術(shù)出現(xiàn)了,,我記得我的第一份工作是一個電信網(wǎng)管系統(tǒng)的開發(fā),我們就是利用CORBA來實(shí)現(xiàn)不同的系統(tǒng)之間的通信,。主要涉及C++和Java,。
圖片

CORBA和之前提到的DCOM和RMI類似,都提供了遠(yuǎn)程的對象/方法調(diào)用,,但是CORBA是一種與語言和實(shí)現(xiàn)無關(guān)的技術(shù),,我記得我們當(dāng)時的測試腳本使用了TCL,也有CORBA的實(shí)現(xiàn),,也就是說CORBA定了與語言解耦的系統(tǒng)間通信的標(biāo)準(zhǔn),。這個是它的最大的優(yōu)勢。那個年代的應(yīng)用,,采用CORBA作為系統(tǒng)間的通信手段非常普遍,。

開發(fā)CORAB的過程從IDL的定義開始,用戶通過IDL定義了對象,,然后在Server端實(shí)現(xiàn)該對象的應(yīng)用邏輯,,在Client端調(diào)用該對象。

但是CORBA并非沒有缺點(diǎn),,否則我們也不會很少再看見今天的應(yīng)用用CORAB作為API的了,。他的主要問題是:

  • 對象的生命周期管理比較復(fù)雜。遠(yuǎn)程對象的發(fā)現(xiàn),,創(chuàng)建和銷毀都會帶來問題

  • 整個CORAB的架構(gòu)比較復(fù)雜,,看看它的架構(gòu)圖就知道了

總之,今天你要開發(fā)一個引用,,除非要個已有系統(tǒng)交互,,你應(yīng)該不會選擇CORBA。

2.XML-RPC / SOAP

XML-RPC發(fā)表于1998年,,由UserLand Software(UserLand Software)的Dave Winer及Microsoft共同發(fā)表,。后來在新的功能不斷被引入下,這個標(biāo)準(zhǔn)慢慢演變成為今日的SOAP協(xié)議

下面是一個 XML-RPC的請求/響應(yīng)的例子:

<?xml version='1.0'?><methodCall> <methodName>examples.getStateName</methodName> <params> <param> <value><i4>40</i4></value> </param> </params></methodCall><?xml version='1.0'?><methodResponse> <params> <param> <value><string>South Dakota</string></value> </param> </params></methodResponse>
(左右滑動查看全部代碼)

SOAP是 Simple Object Access Protocol 的縮寫,。SOAP為Web服務(wù)提供了Web服務(wù)協(xié)議棧的Messaging Protocol層,。它是一個基于XML的協(xié)議,,由三部分組成:

  1. 一個信封,它定義了消息結(jié)構(gòu)以及如何處理它

  2. 一組用于表達(dá)應(yīng)用程序定義的數(shù)據(jù)類型實(shí)例的編碼規(guī)則

  3. 表示過程調(diào)用和響應(yīng)的約定

SOAP具有三個主要特征

  1. 可擴(kuò)展性(安全性和WS-Addressing在開發(fā)中)

  2. 中立性(SOAP可以通過HTTP,,SMTP,,TCP,UDP等任何協(xié)議進(jìn)行操作)

  3. 獨(dú)立性(SOAP允許任何編程語言)

作為SOAP過程可以執(zhí)行的操作的示例,,應(yīng)用程序可以將SOAP請求發(fā)送到啟用了帶有搜索參數(shù)的Web服務(wù)的服務(wù)器(例如,,房地產(chǎn)價格數(shù)據(jù)庫)。然后,,服務(wù)器返回SOAP響應(yīng)(包含結(jié)果數(shù)據(jù)的XML格式的文檔),,例如價格,位置,,功能,。由于生成的數(shù)據(jù)采用標(biāo)準(zhǔn)化的機(jī)器可解析格式,因此發(fā)出請求的應(yīng)用程序可以直接將其集成,。

SOAP體系結(jié)構(gòu)由以下幾層規(guī)范組成

  • 訊息格式

  • 郵件交換模式(MEP)

  • 底層傳輸協(xié)議綁定

  • 消息處理模型

  • 協(xié)議可擴(kuò)展性

這里是一個SOAP消息的例子:

POST /InStock HTTP/1.1Host: www.Content-Type: application/soap+xml; charset=utf-8Content-Length: 299SOAPAction: 'http://www./2003/05/soap-envelope'<?xml version='1.0'?><soap:Envelope xmlns:soap='http://www./2003/05/soap-envelope' xmlns:m='http://www.'> <soap:Header> </soap:Header> <soap:Body>   <m:GetStockPrice>     <m:StockName>T</m:StockName>   </m:GetStockPrice> </soap:Body></soap:Envelope>
(左右滑動查看全部代碼)

相比較XML-RPC,,它的功能更多,當(dāng)然消息結(jié)構(gòu)也更復(fù)雜,。

SOAP是W3C推薦的Webservice標(biāo)準(zhǔn),,一度也是非常的流行,但是我們看到基于XML的消息比較復(fù)雜,,消息本身因?yàn)閄ML的原因,,有相當(dāng)多的開銷。于是后面又有了基于JSON的RPC格式,。但總的來說,,SOAP也已經(jīng)是昨日黃花,當(dāng)今的應(yīng)用構(gòu)建,,你選它的概率應(yīng)該也不大了,。

3.REST

REST是當(dāng)今最為流行的API。因?yàn)榇罅康腤eb應(yīng)用采用REST作為其API的選擇,。REST是 Representational State Transfer 的縮寫,。是Roy Thomas Fielding博士于2000年在他的博士論文中提出來的一種萬維網(wǎng)軟件架構(gòu)風(fēng)格。

目的是便于不同軟件/程序在網(wǎng)絡(luò)(例如互聯(lián)網(wǎng))中互相傳遞信息,。表現(xiàn)層狀態(tài)轉(zhuǎn)換是根基于超文本傳輸協(xié)議(HTTP)之上而確定的一組約束和屬性,,是一種設(shè)計提供萬維網(wǎng)絡(luò)服務(wù)的軟件構(gòu)建風(fēng)格。

符合或兼容于這種架構(gòu)風(fēng)格(簡稱為 REST 或 RESTful)的網(wǎng)絡(luò)服務(wù),,允許客戶端發(fā)出以統(tǒng)一資源標(biāo)識符訪問和操作網(wǎng)絡(luò)資源的請求,而與預(yù)先定義好的無狀態(tài)操作集一致化,。因此表現(xiàn)層狀態(tài)轉(zhuǎn)換提供了在互聯(lián)網(wǎng)絡(luò)的計算系統(tǒng)之間,,彼此資源可交互使用的協(xié)作性質(zhì)(interoperability),。

相對于其它種類的網(wǎng)絡(luò)服務(wù),例如SOAP服務(wù),,則是以本身所定義的操作集,,來訪問網(wǎng)絡(luò)上的資源。目前在三種主流的Web服務(wù)實(shí)現(xiàn)方案中,,因?yàn)镽EST模式與復(fù)雜的SOAP和XML-RPC相比更加簡潔,,越來越多的Web服務(wù)開始采用REST風(fēng)格設(shè)計和實(shí)現(xiàn)。所以我們可以看到軟件的發(fā)展,,大體是從復(fù)雜變得簡單,,只有簡單的東西才會變得更有生命力。
圖片
為了使任何應(yīng)用程序真正實(shí)現(xiàn)RESTful,,必須遵循六個體系結(jié)構(gòu)約束
  • 統(tǒng)一接口:意味著必須向Web應(yīng)用程序中的API使用者提供API接口,。

  • 客戶端服務(wù)器:客戶端和服務(wù)器必須彼此獨(dú)立,并且客戶端應(yīng)僅知道資源的URI,。

  • 無狀態(tài):服務(wù)器不得存儲與客戶端請求相關(guān)的任何內(nèi)容,。客戶端負(fù)責(zé)維護(hù)應(yīng)用程序的狀態(tài),。

  • 可緩存的:資源必須可緩存,。

  • 分層系統(tǒng):體系結(jié)構(gòu)必須是分層的,這意味著體系結(jié)構(gòu)的組件可以位于多個服務(wù)器中,。

  • 按需代碼:客戶端必須能夠獲取可執(zhí)行代碼作為響應(yīng),。這是一個可選約束。

基于REST的Web服務(wù)被稱為RESTful Web服務(wù),。在這些應(yīng)用程序中,,每個組件都是一種資源,可以使用HTTP標(biāo)準(zhǔn)方法通過公共接口訪問這些資源,。以下四種HTTP方法通常用于基于REST的體系結(jié)構(gòu)中:
  • GET-對資源的只讀訪問,。

  • POST —創(chuàng)建一個新資源。

  • DELETE—刪除資源,。

  • PUT-更新現(xiàn)有資源/創(chuàng)建新資源,。

RESTFul風(fēng)格API所有的操作都是一個動詞,對應(yīng)HTTP請求的一種類型,。每一個操作都定義了對操作的資源的某種行為,。這種抽象,特別適合相當(dāng)多的Web應(yīng)用,,后臺是一個數(shù)據(jù)庫,,每一個REST的端點(diǎn)對應(yīng)了一張數(shù)據(jù)庫的表,很自然的利用REST操作來實(shí)現(xiàn)表的增刪查改,。

當(dāng)然RESTFul的風(fēng)格也有它的不足
  • 不是所有的應(yīng)用操作都可以用資源的增刪查改來對應(yīng),,在實(shí)際的開發(fā)中經(jīng)常會需要把一個操作映射為一個資源這種不倫不類的行為,。
  • REST是同步服務(wù),如果需要可能要引入回調(diào)機(jī)制,。例如Webhook,。
  • REST只提供客戶端調(diào)用服務(wù)器的選項(xiàng),不支持服務(wù)器端發(fā)起請求,。
于是新的API類型會出現(xiàn)來解決這些問題,。

4.GraphQL

GraphQL是一個開源的API數(shù)據(jù)查詢和操作語言及實(shí)現(xiàn)為了實(shí)現(xiàn)上述操作的相應(yīng)運(yùn)行環(huán)境。2012年,,GraphQL由Facebook內(nèi)部開發(fā),,2015年公開公布。2018年11月7日,,F(xiàn)acebook將GraphQL項(xiàng)目轉(zhuǎn)移到新成立的GraphQL基金會 ,。

GraphQL規(guī)范概述了5條設(shè)計原則,這使其成為現(xiàn)代前端開發(fā)的精心設(shè)計的解決方案,。讓我們研究一下GraphQL的設(shè)計原則,。
  • 查詢是分層結(jié)構(gòu)的,具有分層和嵌套字段,,查詢與響應(yīng)數(shù)據(jù)一對一匹配,。查詢和響應(yīng)的形狀像樹,可以查詢每個項(xiàng)目的其他嵌套字段,。

  • 該結(jié)構(gòu)以產(chǎn)品為中心,,著重于前端希望如何接收數(shù)據(jù),并構(gòu)建交付所需的運(yùn)行時,。這樣一來,,就可以向后端請求一個所需的所有數(shù)據(jù),然后讓服務(wù)器根據(jù)GraphQL的規(guī)范從不同的端點(diǎn)獲取數(shù)據(jù),。

  • 它使用特定于應(yīng)用程序的類型系統(tǒng),,使開發(fā)人員能夠確保查詢使用有效類型,并且在執(zhí)行之前在語法上正確,。

  • GraphQL查詢是在客戶端指定的,,因此客戶端確切知道它將以什么格式接收數(shù)據(jù)。

  • 帶有GraphQL的服務(wù)器結(jié)構(gòu)必須是自包含的,,或者可由GraphQL本身查詢,。這將啟用功能強(qiáng)大的開發(fā)人員工具,例如GraphiQL或GraphQL Playground,,這兩種工具都將使開發(fā)人員能夠準(zhǔn)確查看哪些查詢和字段可供他們在服務(wù)器中使用,。

像RESTful API一樣,GraphQL API旨在處理HTTP請求并提供對這些請求的響應(yīng),。但是,,相似之處到此結(jié)束,。在REST API建立在請求方法和端點(diǎn)之間的連接上的情況下,GraphQL API設(shè)計為僅使用一個始終通過POST請求查詢的端點(diǎn),,通常使用URL yourdomain.com/graphql。

達(dá)到GraphQL端點(diǎn)后,,客戶端請求的負(fù)擔(dān)將完全在請求主體內(nèi)處理,。該請求主體必須遵守GraphQL規(guī)范,并且API必須具有適當(dāng)?shù)姆?wù)器端邏輯來處理這些請求并提供適當(dāng)?shù)捻憫?yīng),。與RESTful API相比,,這提供了更流暢的客戶端體驗(yàn),后者可能要求客戶端對多個數(shù)據(jù)進(jìn)行多次請求,,并在數(shù)據(jù)返回后進(jìn)行操作,。

圖片

如上圖的例子,用戶通過RESTFul的API來請求數(shù)據(jù),,需要兩個GET請求,,先獲取Assets,再通過AssetID獲取comments,。而通過GraphQL,,用戶只需要描述需要請求的數(shù)據(jù)的結(jié)構(gòu)和條件,就可以通過一個請求獲取全部所需要的數(shù)據(jù),,簡化了客戶端與服務(wù)器的交互,。

GraphQL提供的性能優(yōu)于REST API,可以為前端開發(fā)人員帶來回報,。使用GraphQL規(guī)范創(chuàng)建服務(wù)器可能需要更多設(shè)置和編寫預(yù)測性服務(wù)器端邏輯來解析和處理請求,。盡管GraphQL的安裝成本可能會高于傳統(tǒng)的REST架構(gòu),但更具可維護(hù)性的代碼,,強(qiáng)大的開發(fā)工具以及簡化的客戶端查詢,,這些都是不錯的收益。

除了靈活性這個最大的優(yōu)點(diǎn)外,,GraphQL還有以下的優(yōu)點(diǎn)

  • 聲明性的數(shù)據(jù)獲取,,避免了客戶端和服務(wù)器端的額外交互

  • 優(yōu)秀的開發(fā)體驗(yàn),不需要版本控制,,因?yàn)橐胄碌淖侄尾粫绊懙紸PI查詢,。同時客戶端和服務(wù)器端的團(tuán)隊可以并行的獨(dú)立工作。

  • 強(qiáng)類型的GraphQL模式使得代碼可預(yù)測,,并及早發(fā)現(xiàn)錯誤,。

當(dāng)然,GraphQL也不是沒有缺點(diǎn)

  • 使用GraphQL,,如果您需要查找有關(guān)列表或記錄集合的信息,,則處理起來會很棘手,。例如,如果您想獲取包含其地址的用戶列表的詳細(xì)信息,,則它將執(zhí)行n + 1個查詢,。一個用于用戶列表,然后n查詢每個用戶的地址?,F(xiàn)在它會嚴(yán)重影響性能,,因此必須非常小心地處理它。

  • 很難緩存,,緩存API響應(yīng)的目的主要是為了更快地從將來的請求中獲取響應(yīng),。與GraphQL不同,RESTful API可以利用HTTP規(guī)范中內(nèi)置的緩存,。正如前面提到的,,GraphQL查詢可以請求資源的任何字段,因此緩存本質(zhì)上是困難的,。

5.gRPC

gRPC是一個開源的遠(yuǎn)程過程調(diào)用框架,,用于在服務(wù)之間進(jìn)行高性能的通信。這是將以不同語言編寫的服務(wù)與可插拔支持(用于負(fù)載平衡,,跟蹤,,運(yùn)行狀況檢查和身份驗(yàn)證)相連接的有效方法。默認(rèn)情況下,,gRPC使用Protobuf(協(xié)議緩沖區(qū))序列化結(jié)構(gòu)化數(shù)據(jù),。通常,對于微服務(wù)體系結(jié)構(gòu),,gRPC被認(rèn)為是REST協(xié)議的更好替代方案,。gRPC中的' g'可以歸因于最初開發(fā)該技術(shù)的Google。

gRPC是對傳統(tǒng)RPC框架的改編,。那么,,它與現(xiàn)有的RPC框架有何不同?

最重要的區(qū)別是gRPC使用protobuf 協(xié)議緩沖區(qū)作為接口定義語言進(jìn)行序列化和通信,,而不是JSON / XML,。協(xié)議緩沖區(qū)可以描述數(shù)據(jù)的結(jié)構(gòu),并且可以從該描述中生成代碼,,以生成或解析表示結(jié)構(gòu)化數(shù)據(jù)的字節(jié)流,。這就是為什么gRPC首選多語言(使用不同技術(shù)實(shí)現(xiàn))的Web應(yīng)用程序的原因。二進(jìn)制數(shù)據(jù)格式使通信更輕松,。gRPC也可以與其他數(shù)據(jù)格式一起使用,,但是首選的是protobuf。

同樣,gRPC建立在HTTP / 2之上,,它支持雙向通信以及傳統(tǒng)的請求/響應(yīng),。gRPC允許服務(wù)器和客戶端之間的松散耦合。在實(shí)踐中,,客戶端打開與gRPC服務(wù)器的長期連接,,并且將為每個RPC調(diào)用打開一個新的HTTP / 2流。

圖片

如上圖所示,,gRPC支持不同模式的客戶端和服務(wù)器端的通信方式,,極大的方便了不同的互操作能力。

與使用JSON(主要是JSON)的REST不同,,gRPC使用Protobuf,這是編碼數(shù)據(jù)的更好方法,。由于JSON是基于文本的格式,,因此它比protobuf格式的壓縮數(shù)據(jù)要重得多。

與REST相比,,gRPC的另一個顯著改進(jìn)是它使用HTTP 2作為其傳輸協(xié)議,。REST使用的HTTP 1.1基本上是一個請求-響應(yīng)模型。gRPC利用HTTP 2的雙向通信功能以及傳統(tǒng)的響應(yīng)請求結(jié)構(gòu),。在HTTP 1.1中,,當(dāng)多個請求來自多個客戶端時,它們將被一一處理,。這會降低系統(tǒng)速度,。HTTP 2允許多路復(fù)用,因此可以同時處理多個請求和響應(yīng),。

gRPC的開發(fā)模式和之前提到的CORBA有些類似,。Protobuf充當(dāng)了IDL的角色,然后利用工具生成各種語言的代碼,,最后在生成的代碼上實(shí)現(xiàn)服務(wù)器端和客戶端的邏輯,。

圖片

gRPC的優(yōu)點(diǎn)是:

  • 出色的性能,因?yàn)椴捎胮rotobuf編碼和http/2

  • 支持服務(wù)器端和客戶端的雙向通信

  • 易用,,相比REST開發(fā),,需要更少的代碼

缺點(diǎn)

  • 更陡峭的學(xué)習(xí)曲線

  • 支持的語言的種類沒有REST多,當(dāng)然它還在發(fā)展中

  • 因?yàn)樾枰狿rotobuf的編譯,,這帶來了服務(wù)器和客戶端一定的耦合,,因?yàn)榻涌谧儎拥臅r候需要重新編譯生成代碼。對于REST,,基于不同的工具鏈可能有不同的解決方案

因?yàn)槠涓咝阅?,gRPC更適合被用于系統(tǒng)內(nèi)部組件的通信選擇。在下圖的微服務(wù)架構(gòu)中,對外的服務(wù)采用了REST或者GraphQL的API,,而內(nèi)部微服務(wù)之間使用的是gRPC,。

圖片

5.總結(jié)

好了,看了這么多的API選擇之后,,我們做一個小結(jié),。

系統(tǒng)間的API選項(xiàng)經(jīng)過多年的發(fā)展,現(xiàn)階段的主流是RESTful API,,gRPC 和GraphQL,。具體怎么選擇,要結(jié)合你的業(yè)務(wù)上下文,,我的推薦是:

  1. 對外提供的公開服務(wù),,首選RESTFul API,因?yàn)樗浅3墒旆€(wěn)定和流行,,語言和工具鏈的支持都很好,。

  2. 如果你希望加速應(yīng)用的客戶端開發(fā),GraphQL是個不錯的選擇,,提供良好的性能和靈活性

  3. 如果你的應(yīng)用特別看重性能,,而且主要是內(nèi)部系統(tǒng)之間的交互,建議考慮gRPC
圖片
Python貓技術(shù)交流群開放啦,!群里既有國內(nèi)一二線大廠在職員工,,也有國內(nèi)外高校在讀學(xué)生,既有十多年碼齡的編程老鳥,,也有中小學(xué)剛剛?cè)腴T的新人,,學(xué)習(xí)氛圍良好!想入群的同學(xué),,請在公號內(nèi)回復(fù)『交流群』,,獲取貓哥的微信(謝絕廣告黨,非誠勿擾?。﹡


    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多