當前位置:首頁 > 公眾號精選 > 后端技術(shù)指南針
[導讀]0. 三分鐘科普 或許,除了寫技術(shù)內(nèi)容,我們還需要一點別的吧,比如自然科學。 所以今天我們來了解一下 Kuiper?Belt,關(guān)于 柯伊伯帶 以下摘自百度百科: 20世紀50年代,一位名叫吉納德·柯伊伯的科學家首先提出在海王星軌道外存在一個小行星帶,其中的星體被稱

0. 三分鐘科普

或許,除了寫技術(shù)內(nèi)容,我們還需要一點別的吧,比如自然科學。

所以今天我們來了解一下 Kuiper Belt,關(guān)于 柯伊伯帶 以下摘自百度百科:

20世紀50年代,一位名叫吉納德·柯伊伯的科學家首先提出在海王星軌道外存在一個小行星帶,其中的星體被稱為KBO(Kuiper Belt Objects)。1992年人類發(fā)現(xiàn)了第一個KBO,今天,我們知道KBO地帶有大約10萬顆直徑超過100公里的星體。此后天文學界就以納德·柯伊伯名字命名此小行星帶。

柯伊伯帶天體,是太陽系形成時遺留下來的一些團塊。在45億年前,有許多這樣的團塊在更接近太陽的地方繞著太陽轉(zhuǎn)動,它們互相碰撞,有的就結(jié)合在一起,形成地球和其他類地行星,以及氣體巨行星的固體核。在遠離太陽的地方,那里的團塊處在深度的冰凍之中,就一直原樣保存了下來。柯伊伯帶天體也許就是這樣的一些遺留物,它們在太陽系剛開始形成的時候就已經(jīng)在那里了。

柯伊伯帶是所知的太陽系的邊界,是太陽系大多數(shù)彗星來源地。有天文學家認為,由于冥王星的大小和柯伊伯帶的小行星的大小相約,所以冥王星應(yīng)該排除在九大行星之列,而歸入柯伊伯帶小行星的行列當中;而冥王星的衛(wèi)星則應(yīng)被當作是冥王星的伴星。

來放一張NASA Science的計算機模擬圖片,畢竟一圖勝千言,先睹為快:

圖片來源:
https://solarsystem.nasa.gov/solar-system/kuiper-belt/overview/

3分鐘科普就先到這里,所以開始正題。

1. 前言

之前一篇文章簡單介紹了RPC框架的一些背景和組成,今天繼續(xù)來深入學習一下gRPC框架,后面計劃把 臉書的Thrift、百度的bRPC騰訊的Tars三個框架都進行學習,敬請期待。

通過本文你將了解到以下內(nèi)容:

  • gRPC起源和簡介
  • gRPC的基本組成和原理
  • gRPC的demo和優(yōu)缺點

圖片來自grpc官網(wǎng)

2. RPC和微服務(wù)化架構(gòu)

在聊RPC之前,有必要簡單了解一下互聯(lián)網(wǎng)工程架構(gòu)的演進之路。

2.1 互聯(lián)網(wǎng)工程架構(gòu)演進簡介

我始終信奉 體量決定架構(gòu)。

隨著流量接入和并發(fā)業(yè)務(wù)量的快速增長,互聯(lián)網(wǎng)工程架構(gòu)經(jīng)歷了單體結(jié)構(gòu)->服務(wù)化SOA架構(gòu)->微服務(wù)化架構(gòu)->服務(wù)網(wǎng)格架構(gòu)等演進過程,如圖:

特別提一下服務(wù)網(wǎng)格化架構(gòu) Service Mesh,我大概是幾個月前聽在阿里云的好友提到這個新名詞,后來查了一下Service Mesh在17年就被提出了,想想我確實是孤陋寡聞井底之蛙了,那就簡單看一下這到底是個什么吧。

可查閱原始外文資料:
《Pattern: Service Mesh》
https://philcalcado.com/2017/08/03/pattern_service_mesh.html

作者Phil Cal?ado的行文風格讓我覺得內(nèi)容舒適,作者把Service Mesh的來龍去脈都說的簡潔清晰,十分推薦閱讀。

那么問題來,Servie Mesh是個啥?看下Service Mesh名詞的提出者Buoyant的CEO William Morgan給的基本定義(譯文):

服務(wù)網(wǎng)格是一個基礎(chǔ)設(shè)施層,用于處理服務(wù)間通信。云原生應(yīng)用有著復雜的服務(wù)拓撲,服務(wù)網(wǎng)格保證請求在這些拓撲中可靠地穿梭。在實際應(yīng)用當中,服務(wù)網(wǎng)格通常是由一系列輕量級的網(wǎng)絡(luò)代理組成的,它們與應(yīng)用程序部署在一起,但對應(yīng)用程序透明。

Service Mesh的目標是做微服務(wù)時代的TCP/IP協(xié)議,屏蔽分布式底層復雜細節(jié),讓開發(fā)者回歸到業(yè)務(wù),就像我們開發(fā)業(yè)務(wù)時不需要關(guān)心TCP/IP這樣的基礎(chǔ)網(wǎng)絡(luò)通信鏈路一樣,在進行微服務(wù)開發(fā)時也無需關(guān)心負載均衡、服務(wù)發(fā)現(xiàn)、認證授權(quán)、監(jiān)控追蹤、流量控制等細節(jié)問題。

Service Mesh野心勃勃,我們拭目以待。

2.2 RPC和微服務(wù)化

重新回到RPC和分布式微服務(wù)化的話題,但是其中涉及很多范疇模糊的概念,我們對此不做文字上的爭辯。

RPC(Remote Procedure Call)遠程過程調(diào)用,通俗來講RPC調(diào)用過程,就是 Server 端實現(xiàn)了一個函數(shù),客戶端使用 RPC 框架提供的接口,調(diào)用這個函數(shù)并獲取返回值的過程,這里的C/S是相對而言的,提供功能的一方稱為服務(wù)端,調(diào)用功能的一方稱為客戶端。

微服務(wù)化框架風格:大服務(wù)拆分為單個小服務(wù),子服務(wù)專注特定業(yè)務(wù)、高內(nèi)聚低耦合,集群化部署獨立開發(fā)/測試,服務(wù)彼此物理獨立但又相互調(diào)用。

分布式微服務(wù)化的體系之下,各個子服務(wù)之間必然存在相互調(diào)用的關(guān)系,隨著微服務(wù)數(shù)量和多樣性的增加,運維成本也在增大,RPC就顯得非常重要,至于為什么這么說,感興趣的讀者可自行查閱RPC和微服務(wù)化的聯(lián)系就可以了。

有的文章說RPC是微服務(wù)化系統(tǒng)的水電燃氣,好像也蠻形象,總之RPC之于微服務(wù)化就是基礎(chǔ)且重要的角色。

嘗試一句話概括:互聯(lián)網(wǎng)業(yè)務(wù)體量的增加促使工程架構(gòu)的演進,微服務(wù)化的時代,傳統(tǒng)的通信方式并不是很適用,所以我們需要一種更加高效、可運維、便捷的數(shù)據(jù)通信和服務(wù)管理框架,這就是RPC框架。

2.3 RPC陣營

生活缺少統(tǒng)一,RPC也是。

從根本上來說,RPC就是為了解決遠程數(shù)據(jù)通信問題,由框架來屏蔽底層細節(jié)從而讓通信雙方專注于業(yè)務(wù)。

從廣義角度來看,面對復雜的微服務(wù)化環(huán)境就會出現(xiàn)服務(wù)治理、服務(wù)發(fā)現(xiàn)、服務(wù)注冊、負載均衡、監(jiān)控警報、日志體系等附加功能,把工作做的更細致便捷。

一個優(yōu)秀的RPC框架除了解決數(shù)據(jù)通信問題以外完整可把控、易用可擴展、高效可運維也十分重要,根據(jù)RPC框架的側(cè)重點不同,可以分為兩大陣營

  • 側(cè)重跨語言調(diào)用
    在一個內(nèi)部系統(tǒng)中可能存在Java/C++/Python/Go等多種語言編寫的程序,所以跨語言調(diào)用在多語言系統(tǒng)中顯得很重要,谷歌的gRPC、Facebook的Thrift、輕量級框架Hessian等

  • 側(cè)重服務(wù)治理運維
    像阿里的dubbo和微博的Motan都是側(cè)重服務(wù)治理類的典型代碼,不過對于跨語言支持性差一些,騰訊的Tars算是兼顧了跨語言和服務(wù)治理的相關(guān)功能。

圖片來自網(wǎng)絡(luò):多種rpc框架對比

3. gRPC和Stubby

羅馬不是一天建成的,gRPC也不是。

在谷歌內(nèi)部有一個稱為Stubby的內(nèi)部項目,Stubby是一個通用的RPC框架用來解決谷歌內(nèi)部數(shù)據(jù)中心之間以及數(shù)據(jù)中心之中的微服務(wù)連接問題,這個項目在谷歌內(nèi)部使用了很久,并且有很好的效果。

但是 Stubby 并不基于任何標準,并且與谷歌內(nèi)部基礎(chǔ)設(shè)施緊密耦合,不適合公開發(fā)布。隨著 SPDY、HTTP/2 和 QUIC 的出現(xiàn),公共標準中出現(xiàn)了許多Stubby 沒有提供的其他特性。面對新標準和新特性的出現(xiàn),谷歌決定對Stubby進行改造,以利用新標準化,并將其適用性擴展到移動、物聯(lián)網(wǎng)和云,成為一個外界可用的通用遠程過程調(diào)用框架。

但是這樣的目標設(shè)定并不意味著 gRPC 比 Stubby 更強大,因為 Stubby 是在谷歌內(nèi)部使用多年的系統(tǒng),涉及很多內(nèi)部框架基礎(chǔ),可能是服務(wù)治理/運維/監(jiān)控等。

我們知道 gRPC 是側(cè)重多語言場景的,但是在服務(wù)治理/運維/監(jiān)控等方面并不是很完善,這也就是 gRPC 不能等同于 Stubby 的原因。

畫外音:像Stubby這樣的系統(tǒng)在谷歌使用的很棒,但是這并不意味著Stubby就可以直接開源,相反很難直接開源。

因為優(yōu)秀的系統(tǒng)框架往往依賴很多內(nèi)部的其他組件,要想開源就只能裁剪或者重寫通用化,這樣也就意味著我們拿到的可能是個半成品的開源項目。

為了能讓這個開源項目在自己業(yè)務(wù)中真正run起來,要走的路還是很多,所以找一個通用完善的開源輪子是非常重要的,像阿里的dubbo和騰訊的tars對完整性和易用性都下了很多功夫,是很優(yōu)秀的開源項目。

4. gRPC官方簡介

gRPC的官方網(wǎng)站的一些介紹,為了避免失真,還是老規(guī)矩 中英雙版:

gRPC is a modern open source high performance RPC framework that can run in any environment. It can efficiently connect services in and across data centers with pluggable support for load balancing, tracing, health checking and authentication. It is also applicable in last mile of distributed computing to connect devices, mobile applications and browsers to backend services.

翻譯一下:

gRPC是一個現(xiàn)代的開源高性能RPC框架,可以在任何環(huán)境下運行。它可以高效地連接數(shù)據(jù)中心內(nèi)和數(shù)據(jù)中心之間的服務(wù),并支持負載平衡、跟蹤、運行狀況檢查和身份驗證。它也適用于分布式計算的最后一英里,將設(shè)備、移動應(yīng)用程序和瀏覽器連接到后端服務(wù)。

gRPC的適用場景和核心特征:

The main usage scenarios:
1.Efficiently connecting polyglot services in microservices style architecture
2.Connecting mobile devices, browser clients to backend services 3.Generating efficient client libraries

Core features that make it awesome
1.Idiomatic client libraries in 10 languages
2.Highly efficient on wire and with a simple service definition framework
3.Bi-directional streaming with http/2 based transport
4.Pluggable auth, tracing, load balancing and health checking

翻譯一下:

在微服務(wù)風格的架構(gòu)中高效連接多語言服務(wù),可以將移動設(shè)備、瀏覽器客戶端連接到后端服務(wù),支持10多種語言的客戶端,高效簡單的服務(wù)定義框架,基于http/2傳輸雙向流,可插拔認證、跟蹤、負載平衡和健康檢查。

圖片來自網(wǎng)絡(luò):rpc官網(wǎng)給出的語言支持列表


簡單來說,gRPC是個支持多種語言,可以應(yīng)用在微服務(wù)框架和移動場景并且基于http2傳輸,具備認證/追蹤/負載均衡等綜合功能的RPC框架。

官網(wǎng)上列出的gRPC的使用者包括但不限于:

圖片來自grpc官網(wǎng)

5. gRPC的基礎(chǔ)組成和原理

通用的RPC框架大概可以是這個樣子的:

圖片來自網(wǎng)絡(luò)


基礎(chǔ)的也是最重要的,所以我們先了解一下gRPC是如何進行數(shù)據(jù)通信的:

  • 數(shù)據(jù)內(nèi)容交互格式
    常見的json、xml等是常見的文本類數(shù)據(jù)交換格式,json/xml 也都有各自的優(yōu)缺點,后來又出現(xiàn)了二進制格式,比如 protobuf 等,二進制化傳輸效率更高更安全,同時也需要遵循一些規(guī)范來進行序列化和反序列化,gRPC就是使用protobuf 進行數(shù)據(jù)內(nèi)容交換,當然 protobuf 不僅僅是一直數(shù)據(jù)交互格式語言而是一套規(guī)則和工具,protobuf 也是谷歌出品。

  • 數(shù)據(jù)傳輸協(xié)議
    常見的傳輸協(xié)議有很多:TCP、UDP、Http等,RPC的傳輸協(xié)議也不外乎這幾種,當然還有使用消息隊列 MQ 進行數(shù)據(jù)傳輸?shù)那闆r,大部分RPC協(xié)議是基于TCP協(xié)議進行傳輸?shù)?,gRPC則是基于HTTP協(xié)議傳輸?shù)?,http協(xié)議有1.0、1.1、2.0、3.0等多個版本,不同版本之間的性能差異還是挺大的,gRPC則使用http2進行數(shù)據(jù)傳輸。

5.1 gRPC和HTTP2

我們知道了gRPC使用protobuf進行數(shù)據(jù)封裝(序列化和反序列化),同時使用http2進行數(shù)據(jù)傳輸,那么還是想幾個問題吧。

使用protobuf并不難理解,畢竟是自家產(chǎn)品,而且還很不錯。

但是不禁要問gRPC為啥不使用TCP進行數(shù)據(jù)傳輸呢,emmm... http2也是基于TCP的??!因此問題可以改為gRPC為啥沒有直接使用TCP而是http,并且還是http2呢?

我們試著去探究一下原因:

tcp協(xié)議作為傳輸層協(xié)議,相比http更加底層,我們可以說tcp協(xié)議在傳輸數(shù)據(jù)時支持定制、減少網(wǎng)絡(luò)開銷提供并發(fā)能力,這確實是優(yōu)點,同時也是缺點,協(xié)議的統(tǒng)一和受眾很重要,所以才會出現(xiàn)http這種應(yīng)用層協(xié)議,讓動作變得統(tǒng)一,但是代價可能是開銷更大。

http也有很多版本,之所以選擇了http2和gRPC的目標設(shè)定有很大關(guān)系,gRPC的一個重要場景是移動場景,http2最先在移動場景應(yīng)用同時是經(jīng)過實踐檢驗的標準,并且http2的前身SPDY也和谷歌有非常大的關(guān)系,另外支持http2的客戶端語言也非常多,因此對于數(shù)據(jù)包的處理方案也更加成熟和通用。

之前寫給一篇關(guān)于HTTP2技術(shù)特征的文章,可以進行閱讀:理解HTTP2協(xié)議

總體來說,gRPC 基于 HTTP/2 標準設(shè)計,帶來諸如雙向流、流控、頭部壓縮、單 TCP 連接上的多復用請求等特性。這些特性使得其在移動設(shè)備上表現(xiàn)更好,更省電和節(jié)省空間占用。

6. gRPC的demo

在github上grpc的相關(guān)example有多個版本,看了下c++和python,代碼基本差不多,不過要想運行起來,還要裝一些依賴包,需要折騰一下才行。

好在github上的相關(guān)說明寫的很詳細(這也是相對的emmm...),試一下就知道了。

粘個python的demo工程,主體就三部分:proto文件、client、server。

圖片來自網(wǎng)絡(luò):基于gRPC的C/S交互簡圖

我們通過修改.proto文件,然后使用grpc工具來生成client和service調(diào)用的文件:

這里簡單提一下protobuf,這是一種序列化和反序列化工具,同時也是一門idl語言,protobuf有自己特定的語法,我們可以在其中進行修改增加功能,之后使用proto的相關(guān)工具編譯器生成對應(yīng)語言的代碼,比如c++或者python,從而做到語言無關(guān),可擴展性確實好了很多,常被當作一種跨語言的序列化/反序列化方案。

環(huán)境安裝和代碼執(zhí)行詳細步驟可參考:

gRPC快速入門-python版
https://grpc.io/docs/quickstart/python/

greeter_server.py

from concurrent import futures
import logging

import grpc

import helloworld_pb2
import helloworld_pb2_grpc


class Greeter(helloworld_pb2_grpc.GreeterServicer):

    def SayHello(self, request, context):
        return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)


def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
    server.add_insecure_port('[::]:50051')
    server.start()
    server.wait_for_termination()


if __name__ == '__main__':
    logging.basicConfig()
    serve()

greeter_client.py

from __future__ import print_function
import logging

import grpc

import helloworld_pb2
import helloworld_pb2_grpc


def run():
    # NOTE(gRPC Python Team): .close() is possible on a channel and should be
    # used in circumstances in which the with statement does not fit the needs
    # of the code.
    with grpc.insecure_channel('localhost:50051'as channel:
        stub = helloworld_pb2_grpc.GreeterStub(channel)
        response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'))
    print("Greeter client received: " + response.message)


if __name__ == '__main__':
    logging.basicConfig()
    run()

helloworld.proto

syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

References

  • https://grpc.io/blog/principles/
  • https://www.infoq.cn/article/2016/09/gRPC1-0-Google-RPC
  • http://www.kancloud.cn:8080/dargon/stack_development/1134466
  • https://juejin.im/post/5cff855c518825612f412526
  • https://www.jianshu.com/p/4e0633a1a37a
  • https://www.sohu.com/a/271150652_468635
  • https://zhuanlan.zhihu.com/p/100709206
  • https://tech.meituan.com/2019/08/08/large-scale-microservice-communication-framework.html
  • https://cloud.tencent.com/developer/article/1461684
  • http://ddrv.cn/a/180301
  • https://docs.microsoft.com/zh-cn/aspnet/core/grpc/comparison?view=aspnetcore-3.0&viewFallbackFrom=aspnetcore-1.1
  • https://www.codercto.com/a/26880.html
  • https://blog.csdn.net/zhougb3/article/details/80403125
  • https://zhuanlan.zhihu.com/p/61901608
  • https://www.jianshu.com/p/e23e3e74538e
  • https://ketao1989.github.io/2016/12/10/rpc-theory-in-action/

寫在最后

最近有一些工作上的調(diào)整,為了在新崗位快速適應(yīng)并站穩(wěn)腳跟,寫文章的時間越來越少了,差不多每天早上寫1個小時晚上寫1個小時,但是仍然覺得有點黑白顛倒,不是很適應(yīng)目前的作息節(jié)奏,么得辦法干就完了,加油整。

工程類的文章比較寬泛但是也不好寫,之前嘗試過寫leetcode的題目,會比較快大約半天可以寫一篇(當然不存在動畫之類的,不擅長也不打算嘗試)。

工程能力和算法能力同樣重要,但是目前兩方面的知識儲備和能力都相差很多,所以這個號會持續(xù)更新,雖然慢但不會斷。

最后依然是:感謝各位讀者的閱讀,秉承 若批評不自由則贊美無意義 的觀點,歡迎指出存疑或者明顯錯誤的地方,在此表示感謝。

Learning by doing 完結(jié)

免責聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
關(guān)閉
關(guān)閉