那曲檬骨新材料有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

正確使用gRPC與GraphQL

汽車電子技術 ? 來源:洛倫·桑茲-拉姆肖 ? 作者:洛倫·桑茲-拉姆肖 ? 2022-12-08 15:47 ? 次閱讀

TLDR:使用 GraphQL 進行客戶端-服務器通信,使用 gRPC 進行服務器到服務器通信。有關此規(guī)則的例外情況,請參閱“判定”部分。

我已經閱讀了很多關于這兩種協(xié)議的比較,并想寫一個全面和公正的協(xié)議。(好吧,就像我和我的審稿人所能做到的那樣公正

。我的靈感來自connect-web(一個可以在瀏覽器中使用的TypeScript gRPC客戶端)的發(fā)布,以及一篇名為GraphQL的流行HN帖子有點糟糕。我個人在第7 層之上構建的通信協(xié)議歷史:

REST(Rails and Express)

DDP(Meteor's WebSocket Protocol)

GraphQL(我寫了一本書)

gRPC(我在Temporal 使用))

背景

gRPC由 Google 于 2016 年發(fā)布,是一種高效且開發(fā)人員友好的服務器到服務器通信方法。GraphQL由 Meta 于 2015 年發(fā)布,作為一種高效且開發(fā)人員友好的客戶端-服務器通信方法。它們都比 REST 具有顯著的優(yōu)勢,并且有很多共同點。我們將用大部分時間比較它們的特征,然后總結每個協(xié)議的優(yōu)點和缺點。最后,我們將知道為什么每個都非常適合其預期域,以及何時可能希望在另一個域中使用一個。

比較 gRPC 和 GraphQL 特性

界面設計

gRPC 和 GraphQL 都是接口描述語言 (IDL),用于描述兩臺計算機如何相互通信。它們跨不同的編程語言工作,我們可以使用 codegen 工具來生成多種語言的類型化接口。IDL 抽象出傳輸層;GraphQL 與傳輸無關,但通常通過 HTTP 使用,而 gRPC 使用 HTTP/2。我們不需要了解傳輸級的詳細信息,例如 REST 中的方法、路徑、查詢參數(shù)和正文格式。我們只需要知道使用更高級別的客戶端庫與之通信的單個端點。

消息格式

郵件大小很重要,因為較小的郵件通常通過網(wǎng)絡發(fā)送所需的時間較短。gRPC 使用協(xié)議緩沖區(qū)(又名 protobufs),這是一種只包含值的二進制格式,而 GraphQL 使用 JSON,它是基于文本的,除了值之外還包括字段名稱。二進制格式與較少的信息相結合通常會導致 gRPC 消息小于 GraphQL 消息。(雖然高效的二進制格式在 GraphQL 中是可行的,但它很少使用,并且不受大多數(shù)庫和工具的支持。

影響消息大小的另一個方面是過度獲取:我們是可以只請求特定字段還是始終接收所有字段(我們不需要的“過度提取”字段)。GraphQL 總是在請求中指定需要哪些字段,而在 gRPC 中,我們可以將FieldMask用作請求的可重用過濾器。

gRPC 二進制格式的另一個好處是,與 GraphQL 的文本消息相比,消息的序列化和解析速度更快。缺點是它比人類可讀的 JSON 更難查看和調試。我們默認使用 protobuf 的JSON 格式,以獲得開發(fā)人員體驗的可見性優(yōu)勢。(這失去了二進制格式帶來的效率,但更重視效率的用戶可以切換到二進制。

違約

gRPC 也不在消息中包含默認值,GraphQL 可以對參數(shù)執(zhí)行此操作,但不能對請求字段或響應類型執(zhí)行此操作。這是 gRPC 消息較小的另一個因素。它還會影響使用 gRPC API 的 DX。將輸入字段保留為未設置和將其設置為默認值之間沒有區(qū)別,默認值基于字段的類型。所有布爾值默認為 false,所有數(shù)字和枚舉默認為 0。我們不能將“behavior”枚舉輸入字段默認為“BEHAVIOR_FOO = 2”——我們必須將默認值放在第一位(“BEHAVIOR_FOO = 0”),這意味著它將來將始終是默認值,或者我們遵循推薦的做法,即使用“BEHAVIOR_UNSPECIFIED = 0”枚舉值:

enum Behavior {
  BEHAVIOR_UNSPECIFIED = 0;
  BEHAVIOR_FOO = 1;
  BEHAVIOR_BAR = 2;
}

API 提供者需要傳達 whatmeans(通過記錄“未指定將使用默認行為,這是當前”),消費者需要考慮服務器默認行為將來是否會發(fā)生變化(如果服務器將 offer/ 0 值保存在消費者正在創(chuàng)建的某個業(yè)務實體中,并且服務器稍后更改了默認行為, 實體將開始以不同的方式行事)以及是否需要這樣做。如果不需要,客戶端需要將值設置為當前默認值。下面是一個示例方案:UNSPECIFIEDFOOUNSPECIFIED

service ExampleGrpcService {
  rpc CreateEntity (CreateEntityRequest) returns (CreateEntityResponse) {}
}

message CreateEntityRequest {
  string name = 1;
  Behavior behavior = 2;
}

如果我們這樣做:

const request = new CreateEntityRequest({ name: “my entity” })
service.CreateEntity(request)

我們將發(fā)送,根據(jù)服務器實現(xiàn)和未來的更改,這可能意味著現(xiàn)在和以后?;蛘呶覀兛梢宰觯築EHAVIOR_UNSPECIFIEDBEHAVIOR_FOOBEHAVIOR_BAR

const request = new CreateEntityRequest({ name: “my entity”, behavior: Behavior.BEHAVIOR_FOO })
service.CreateEntity(request)

可以肯定的是,該行為被存儲為“將保留”。FOOFOO

等效的 GraphQL 模式將是:

type Mutation {
  createEntity(name: String, behavior: Behavior = FOO): Entity
}

enum Behavior {
  FOO
  BAR
}

當我們不在請求中包含時,服務器代碼將接收并將 FOO 存儲為值,與上述架構中的默認值匹配。behavior= FOO

graphqlClient.request(`
  mutation  {
    createEntity(name: “my entity”)
  }
`

知道如果未提供字段會發(fā)生什么情況,它比 gRPC 版本更簡單,我們不需要考慮是否自己傳遞默認值。

其他類型的默認值還有其他怪癖。對于數(shù)字,有時默認值 0 是有效值,有時表示不同的默認值。對于布爾值,默認的 false 會導致負命名字段。當我們在編碼時命名布爾變量時,我們使用正名稱。例如,我們通常會聲明而不是。人們通常發(fā)現(xiàn)前者更具可讀性,因為后者需要額外的步驟來理解雙重否定(“是,所以它是可重試的”)。但是,如果我們有一個 gRPC API,我們希望默認狀態(tài)是可重試的,那么我們必須命名該字段,因為 anfield 的默認值將是,就像 gRPC 中的所有布爾值一樣。let retryable = truelet nonRetryable = falsenotRetryablefalsenonRetryableretryablefalse

請求格式

在 gRPC 中,我們一次調用一個方法。如果我們需要的數(shù)據(jù)多于單個方法提供的數(shù)據(jù),則需要調用多個方法。如果我們需要來自第一個方法的響應數(shù)據(jù),以便知道下一步要調用哪個方法,那么我們將連續(xù)進行多次往返。除非我們與服務器位于同一數(shù)據(jù)中心,否則會導致明顯的延遲。此問題稱為獲取不足。

這是 GraphQL 旨在解決的問題之一。在高延遲移動電話連接中,能夠在單個請求中獲取所需的所有數(shù)據(jù)尤為重要。在 GraphQL 中,我們發(fā)送一個字符串(稱為文檔)以及我們的請求,其中包含我們要調用的所有方法(稱為查詢和突變)以及基于第一級結果所需的所有嵌套數(shù)據(jù)。某些嵌套數(shù)據(jù)可能需要從服務器到數(shù)據(jù)庫的后續(xù)請求,但它們通常位于同一數(shù)據(jù)中心,該數(shù)據(jù)中心應具有亞毫秒級的網(wǎng)絡延遲。

GraphQL 的請求靈活性讓前端和后端團隊變得不那么耦合。前端開發(fā)人員可以向其請求添加更多查詢或嵌套結果字段,而不是前端開發(fā)人員等待后端開發(fā)人員向方法的響應添加更多數(shù)據(jù)(以便客戶端可以在單個請求中接收數(shù)據(jù))。當有一個覆蓋組織整個數(shù)據(jù)圖的 GraphQL API 時,前端團隊在等待后端更改時被阻止的頻率要低得多。

事實上,GraphQL 請求指定了所有需要的數(shù)據(jù)字段,這意味著客戶端可以使用聲明性數(shù)據(jù)獲取:而不是命令性獲取數(shù)據(jù)(如調用 'grpcClient.callMethod()“),我們在視圖組件旁邊聲明我們需要的數(shù)據(jù),GraphQL 客戶端庫將這些部分組合成一個請求,并在響應到達時和稍后數(shù)據(jù)更改時將數(shù)據(jù)提供給組件。Web 開發(fā)中視圖庫的并行是使用 React 而不是 jQuery:聲明我們的組件應該是什么樣子,并在數(shù)據(jù)更改時自動更新它們,而不是使用 jQuery 強制操作 DOM。

GraphQL 的請求格式的另一個影響是提高了可見性:服務器可以看到請求的每個字段。我們可以跟蹤字段使用情況并查看客戶端何時停止使用已棄用的字段,以便我們知道何時可以刪除它們,而不是永遠支持我們說要刪除的內容。跟蹤內置于Apollo GraphOS和Stellate等常用工具中。

向前兼容性

gRPC 和 GraphQL 都有很好的前向兼容性;也就是說,很容易在不破壞現(xiàn)有客戶端的情況下更新服務器。這對于可能已過時的移動應用程序尤其重要,但對于在服務器更新后繼續(xù)工作,用戶瀏覽器選項卡中加載的SPA也是必需的。

在 gRPC 中,可以通過對字段進行數(shù)字排序、添加具有新編號的字段以及不更改現(xiàn)有字段的類型/編號來保持向前兼容性。在 GraphQL 中,您可以添加字段,使用 '@deprecated“' 指令棄用舊字段(并讓它們正常工作),并避免更改必需的可選參數(shù)。

運輸

gRPC 和 GraphQL 都支持服務器將數(shù)據(jù)流式傳輸?shù)?/strong>客戶端:gRPC 具有服務器流式處理,GraphQL 具有訂閱和指令 @defer,@stream 和 @live。gRPC 的 HTTP/2 還支持客戶端和雙向流式處理(盡管當一側是瀏覽器時,我們不能進行雙向流式處理)。HTTP/2 還通過多路復用提高了性能。

gRPC 在網(wǎng)絡故障時具有內置的重試功能,而在 GraphQL 中,它可能包含在特定的客戶端庫中,例如 Apollo Client 的RetryLink。gRPC 也有內置的截止日期。

運輸也有一些限制。gRPC 無法使用大多數(shù)在 HTTP 標頭上運行的 API 代理,如Apigee Edge,當客戶端是瀏覽器時,我們需要使用gRPC-Web 代理或Connect(雖然現(xiàn)代瀏覽器確實支持 HTTP/2,但沒有瀏覽器API允許對請求進行足夠的控制)。默認情況下,GraphQL 不適用于 GET 緩存:大部分 HTTP 緩存適用于GET 請求,大多數(shù) GraphQL 庫默認使用 POST。 GraphQL 有許多使用 GET 的選項,包括將操作放在查詢參數(shù)中(當操作字符串不太長時可行)、構建時持久化查詢(通常只與私有 API 一起使用), 和自動持久化查詢??梢栽谧侄渭墑e提供緩存指令(整個響應中的最短值用于 Cache-Control 標頭的“max-age”)。

架構和類型

GraphQL 有一個架構,服務器為客戶端開發(fā)人員發(fā)布并用于處理請求。它定義了所有可能的查詢和突變,以及所有數(shù)據(jù)類型及其相互關系(圖形)。通過該架構,可以輕松合并來自多個服務的數(shù)據(jù)。GraphQL 具有模式拼接(命令性地將多個 GraphQL API 組合成一個代理部分模式的 API)和聯(lián)合(每個下游 API聲明如何關聯(lián)共享類型,網(wǎng)關通過向下游 API 發(fā)出請求并組合結果來自動解析請求)的概念,用于創(chuàng)建超圖(我們所有數(shù)據(jù)的圖表,結合了較小的子圖/部分模式)。還有一些庫將其他協(xié)議代理到 GraphQL,包括 gRPC。

隨著 GraphQL 的模式而來的是進一步發(fā)展的內省:能夠以標準方式查詢服務器以確定其功能。所有 GraphQL 服務器庫都有內省功能,并且有基于內省的高級工具,如GraphiQL、使用graphql-eslint 的請求 linting 和Apollo Studio,其中包括具有字段自動完成、linting、自動生成的文檔和搜索功能的查詢 IDE。gRPC 具有反射,但它沒有那么普遍,并且使用它的工具較少。

GraphQL 模式啟用了反應式規(guī)范化客戶端緩存:因為每個(嵌套)對象都有一個類型字段,所以類型在不同的查詢之間共享,我們可以告訴客戶端將哪個字段用作每種類型的 ID,客戶端可以存儲規(guī)范化的數(shù)據(jù)對象。這使高級客戶端功能(如查詢結果或觸發(fā)更新的樂觀更新)能夠查看依賴于包含同一對象的不同查詢的組件。

gRPC 和 GraphQL 類型之間存在一些差異:

gRPC 版本 3(截至撰寫本文時的最新版本)沒有必填字段:相反,每個字段都有一個默認值。在 GraphQL 中,服務器可以區(qū)分值存在和不存在 (null),并且架構可以指示參數(shù)必須存在或響應字段將始終存在。

在 gRPC 中,沒有標準方法可以知道方法是否會改變狀態(tài)(與 GraphQL,它分離查詢和突變)。

映射在 gRPC 中受支持,但在 GraphQL 中不受支持:如果你的數(shù)據(jù)類型像 '{[key: string] : T}',你需要對整個事情使用 JSON 字符串類型。

GraphQL 的模式和靈活查詢的一個缺點是,公共 API 的速率限制更為復雜(對于私有 API,我們可以將持久查詢列入允許列表)。由于我們可以在單個請求中包含任意數(shù)量的查詢,并且這些查詢可以請求任意嵌套的數(shù)據(jù),因此我們不能只限制來自客戶端的請求數(shù)量或將成本分配給不同的方法。我們需要對整個操作實現(xiàn)成本分析速率限制,例如通過使用graphql-cost-analysis庫對單個字段成本求和并將它們傳遞給泄漏桶算法。

總結

以下是我們涵蓋的主題摘要:

gRPC 和 GraphQL 之間的相似之處

帶代碼生成的類型化接口

抽象出網(wǎng)絡層

可以有 JSON 響應

服務器流式傳輸

良好的向前兼容性

可以避免過度提取

gRPC

優(yōu)勢

二進制格式:

通過網(wǎng)絡更快地傳輸

更快的序列化、解析和驗證

但是,比 JSON 更難查看和調試

HTTP/2:

多路復用

客戶端和雙向流式處理

內置重試和截止時間

弱點

需要代理或連接才能從瀏覽器使用

無法使用大多數(shù) API 代理

沒有標準方法可以知道方法是否會改變狀態(tài)

圖QL

優(yōu)勢

客戶端確定它要返回哪些數(shù)據(jù)字段。結果:

無欠取

團隊解耦

提高可見性

更輕松地合并來自多個服務的數(shù)據(jù)

進一步發(fā)展的內省和工具

聲明性數(shù)據(jù)提取

反應式規(guī)范化客戶端緩存

Weaknesses

If we already have gRPC services that can be exposed to the public, it takes more backend work to add a GraphQL server.

HTTP GET caching doesn’t work by default.

Rate limiting is more complex for public APIs.

Maps aren’t supported.

Inefficient text-based transport

Verdict

Server-to-server

In server-to-server communication, where low latency is often important, and more types of streaming are sometimes necessary, gRPC is the clear standard. However, there are cases in which we may find some of the benefits of GraphQL more important:

We’re using GraphQL federation or schema stitching to create a supergraph of all our business data and decide to have GraphQL subgraphs published by each service. We create two supergraph endpoints: one external to be called by clients and one internal to be called by services. In this case, it may not be worth it for services to also expose a gRPC API, because they can all be conveniently reached through the supergraph.

We know our services’ data fields are going to be changing and want field-level visibility on usage so that we can remove old deprecated fields (and aren’t stuck with maintaining them forever).

還有一個問題是,我們是否應該自己進行服務器到服務器的通信。對于數(shù)據(jù)獲取(GraphQL 的查詢),這是獲得響應的最快方式,但對于修改數(shù)據(jù)(突變),像 Martin Fowler 的“同步調用被認為是有害的”(見此處的側欄)導致使用異步、事件驅動的架構,在服務之間編排或編排。微服務模式建議在大多數(shù)情況下使用后者,為了保持 DX 和開發(fā)速度,我們需要一個基于代碼的業(yè)務流程協(xié)調程序,而不是基于 DSL 的業(yè)務流程協(xié)調程序。一旦我們使用像 Temporal 這樣的基于代碼的業(yè)務流程協(xié)調程序,我們就不再自己發(fā)出網(wǎng)絡請求 — 平臺會為我們可靠地處理它。在我看來,這就是未來。

客戶端-服務器

在客戶端-服務器通信中,延遲很高。我們希望能夠在一次往返中獲取所需的所有數(shù)據(jù),靈活地為不同的視圖獲取哪些數(shù)據(jù),并具有強大的緩存功能,因此 GraphQL 是明顯的贏家。但是,在某些情況下,我們可能會選擇改用 gRPC:

我們已經有一個可以使用的 gRPC API,在它前面添加一個 GraphQL 服務器的成本不值得。

JSON 不適合數(shù)據(jù)(例如,我們正在發(fā)送大量二進制數(shù)據(jù))。

感謝Marc-André Giroux,Uri Goldshtein,Sashko Stubailo,Morgan Kestner,Andrew Ingram,Lenny Burdette,Martin Bonnin,James Watkins-Harvey,Josh Wise,Patrick Rachford和Jay Miller閱讀本文的草稿。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • Google
    +關注

    關注

    5

    文章

    1772

    瀏覽量

    57807
  • 二進制
    +關注

    關注

    2

    文章

    796

    瀏覽量

    41757
  • 服務器
    +關注

    關注

    12

    文章

    9308

    瀏覽量

    86071
  • API
    API
    +關注

    關注

    2

    文章

    1511

    瀏覽量

    62400
  • GraphQL
    +關注

    關注

    0

    文章

    14

    瀏覽量

    580
收藏 人收藏

    評論

    相關推薦

    GRPC的基礎使用方法

    gRPC 是 Google 開源的高性能、通用的 RPC 框架,它采用了基于 HTTP/2 協(xié)議的二進制傳輸協(xié)議,支持多種語言,包括 Rust。Rust 語言 GRPC 模塊是一個用于 Rust
    的頭像 發(fā)表于 09-19 16:08 ?1021次閱讀

    GraphQL API的核心和解析器函數(shù)實現(xiàn)schema

    介紹GraphQL服務端開發(fā)
    發(fā)表于 02-26 16:50

    REST、gRPCGraphQL及WebHook的對比和選型

    首先REST--Resource Representational State Transfer, 中文直譯就是資源在網(wǎng)絡中以某種表現(xiàn)形式進行狀態(tài)轉移。
    發(fā)表于 06-13 10:34 ?2519次閱讀

    Dubbo 在跨語言和協(xié)議穿透性方向的探索:支持 HTTP/2 gRPC

    Dubbo 在跨語言和協(xié)議穿透性方向上的探索:支持 HTTP/2 gRPC 和 Protobuf 本文整理自劉軍在 Dubbo 成都 meetup 上分享的《Dubbo 在多語言和協(xié)議穿透性方向
    發(fā)表于 12-02 23:07 ?3880次閱讀
    Dubbo 在跨語言和協(xié)議穿透性方向的探索:支持 HTTP/2 <b class='flag-5'>gRPC</b>

    谷歌開源高性能通用RPC框架gRPC

    谷歌開源了 gRPC-Kotlin/JVM,讓開發(fā)者可以在 Kotlin 項目中更方便地使用 gRPC,以更簡單的方式構建可靠的網(wǎng)絡連接服務。
    的頭像 發(fā)表于 04-20 14:43 ?2807次閱讀
    谷歌開源高性能通用RPC框架<b class='flag-5'>gRPC</b>

    GraphQL APIs實現(xiàn)監(jiān)控的步驟

    作為REST的另一種選擇,GraphQL自2015年發(fā)布以來,為前端開發(fā)人員提供了他們渴望已久的靈活性。他們可以通過一次性查詢,來定義所有需要的數(shù)據(jù),并能夠一次性地“打包”獲取,進而大幅減少了等待的時間。
    的頭像 發(fā)表于 06-28 14:16 ?1797次閱讀

    Spring認證_什么是Spring GraphQL

    Spring GraphQL 為構建在 GraphQL Java 上的 Spring 應用程序提供支持。兩個團隊之間的聯(lián)合聯(lián)合。我們的共同理念是少固執(zhí)己見,更專注于全面和廣泛的支持。 Spring
    的頭像 發(fā)表于 08-06 14:30 ?767次閱讀
    Spring認證_什么是Spring <b class='flag-5'>GraphQL</b>

    Spring認證_什么是Spring GraphQL?

    數(shù)據(jù)整合 Spring GraphQL 支持使用 Querydsl 通過 Spring Data Querydsl 擴展 來獲取數(shù)據(jù)。Querydsl 提供了一種靈活但類型安全的方法,通過使用注釋
    的頭像 發(fā)表于 08-09 11:31 ?668次閱讀
    Spring認證_什么是Spring <b class='flag-5'>GraphQL</b>?

    「Spring認證」什么是Spring GraphQL?

    這個項目建立在 Boot 2.x 上,但它應該與最新的 Boot2.4.x5 相關。 要創(chuàng)建項目,請轉到start.spring.io并為要使用的GraphQL傳輸選擇啟動器: 啟動機 運輸 執(zhí)行
    的頭像 發(fā)表于 08-10 14:08 ?865次閱讀
    「Spring認證」什么是Spring <b class='flag-5'>GraphQL</b>?

    IP知識百科之什么是gRPC

    gRPC Google遠程過程調用(Google Remote Procedure Call,gRPC)協(xié)議是谷歌發(fā)布的高性能、通用的開源RPC軟件框架。gRPC提供了多種編程語言,同時gRP
    的頭像 發(fā)表于 11-16 15:13 ?3346次閱讀

    可從GraphQL查詢生成Java模型的Apollo HarmonyOS

    概要 Apollo HarmonyOS 是一個 GraphQL 客戶端,可以從 GraphQL 查詢生成 Java 模型。這些模型為您提供了與 GraphQL 服務器一起使用的類型安全 API
    發(fā)表于 04-12 09:15 ?4次下載

    gRPC-Nebula微服務框架

    ./oschina_soft/grpc-nebula.zip
    發(fā)表于 06-22 14:59 ?0次下載
    <b class='flag-5'>gRPC</b>-Nebula微服務框架

    gRPC-Web訪問gRPC服務的Web客戶端

    ./oschina_soft/grpc-web.zip
    發(fā)表于 06-22 09:25 ?0次下載
    <b class='flag-5'>gRPC</b>-Web訪問<b class='flag-5'>gRPC</b>服務的Web客戶端

    什么是gRPC

    相信大家對RPC協(xié)議都有一定的了解,并且或多或少都會在項目中涉及,但可能都和小編類似,都是直接使用平臺封裝的插件,對于其中的原理不是很了解,今天借此機會和大家分享下最近接觸的RPC框架-grpc
    的頭像 發(fā)表于 10-07 16:24 ?760次閱讀

    使用go語言實現(xiàn)一個grpc攔截器

    在開發(fā)grpc服務時,我們經常會遇到一些通用的需求,比如:日志、鏈路追蹤、鑒權等。這些需求可以通過grpc攔截器來實現(xiàn)。本文使用go語言來實現(xiàn)一個 grpc一元模式(Unary)攔截器,上報鏈路追蹤信息。
    的頭像 發(fā)表于 12-18 10:13 ?738次閱讀
    使用go語言實現(xiàn)一個<b class='flag-5'>grpc</b>攔截器
    百家乐投注程式| 澳门皇冠娱乐城| 太阳城百家乐官网娱乐开户| 百家乐是多少个庄闲| 棋牌娱乐| 百家乐官网路单下| 大发888优惠活动| 缅甸百家乐官网玩家吗| 百家乐皇室百家乐| 网上百家乐官网有假的吗| 百家乐庄闲和各| 忻州市| 百家乐赌博机假在哪里| 易博彩票网| 百家乐园sun811.com| 百家乐官网只打一种牌型| 百家乐赔率计算| 百家乐官网事电影| 状元百家乐的玩法技巧和规则| 娱乐城百家乐官网可以代理吗 | 网上百家乐官网如何作假| 678百家乐博彩赌场娱乐网规则| 澳门百家乐官网家用保险柜 | 缅甸百家乐网络赌博解谜| 黄金城百家乐官网游戏| 红宝石百家乐的玩法技巧和规则| 百家乐官网桌保险| 大发888注册送58元| 澳门百家乐官网手机软件| 青海省| 如何玩百家乐的玩法技巧和规则| 网络百家乐官网的信誉| 大发888真人真钱网址| 百家乐游戏策略| 大发888开户| 百家乐娱乐城公司| 海立方百家乐官网赢钱| 申博太阳城娱乐网| 做生意的门的方向| 百家乐官网牌机的破解法| 大发888游戏平台寒怕|