日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

grpc是基于http/2协议的高性能的rpc框架

發布時間:2023/12/31 windows 30 coder
生活随笔 收集整理的這篇文章主要介紹了 grpc是基于http/2协议的高性能的rpc框架 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

師傅領進門,修行在個人,跟著官方腳手架demo了grpc后,之后就需要擴展前后知識邊界,下面總結grpc的前世今生和最佳實踐。
https://www.cnblogs.com/JulianHuang/p/14441952.html

  1. grpc是基于http/2協議的高性能的rpc框架
  2. 為什么已經有http? 還需要grpc?
  3. 八股文都說grpc是基于http2的rpc框架,到底利用了http2的什么特性 ?
  4. 一個grpc內存泄漏的例子

grpc是基于http/2協議的高性能的rpc框架。

提取句式中關鍵信息:rpc框架、 http2、 高性能

1.落地賓語-rpc框架

遠程過程調用 remote process call;
程序可以像調用本地函數和本地對象一樣, 達成調用遠程服務的效果(不用意識到是遠程服務),rpc屏蔽了底層的通信細節和打解包細節。

跟許多rpc協議一樣, grpc也是基于IDL(interface define lauguage)來定義服務協議。

rpc的開發模式, 必然強調契約優先, client和server端首先約定service的結構(包括一系列方法的組合、每個方法具體簽名)。
對這個結構的描述,gRPC 默認是用Protocol Buffer去實現的。

syntax = "proto3";

option csharp_namespace = "GrpcAuthor";

package greet;

// 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;
}

rpc框架兩個關鍵通用部件:

  • channel: 通信信道
  • stub: 是client的抽象,中文名叫存根。

① 建立與grcp服務端的通信信道;
② 基于步驟①的信道使用服務名Greet建立grpc服務在客戶端的存根, 就像服務Greet是本地服務一樣;
③ 用步驟②的grpc服務存根發起grpc調用GreeterClient(),就像GreeterClient是本地方法一樣。

var channel = GrpcChannel.ForAddress(
    "http:///my-example-host",
    new GrpcChannelOptions { Credentials = ChannelCredentials.Insecure });
var client = new Greet.GreeterClient(channel);

var response = await client.SayHelloAsync(new HelloRequest { Name = "world" });
 

rpc 是一種久遠的通信框架, http是通信協議。

2. 目前市面流行http, 為什么還需要grpc?

其實rpc框架比 http協議更早出來。
tcp協議于70年代誕生,tcp是一種可靠的、面向連接的、基于字節流的傳輸層協議。

tcp粘包?
關于tcp的定語和修飾詞也很關鍵,正因為是字節流,就如同躺在水流中的0/1串, 這些0/1串是沒有任何邊界的,應用層傳到tcp層的數據不是以消息報為單位向對面主機發送,而是以字節流的形式流淌在tcp層, 在tcp傳輸層由tcp層的協議進行切割和組包, 對端接收的時候沒能正確還原發送端的消息報。
tcp粘包問題并不是tcp協議的弊端,而是我們在應用層發送和接收數據需要對數據分段,而傳輸層是無邊界的0/1串之間的矛盾。

在70到90年代之后,互聯網并不發達,很多都是client、server點對點的傳輸,所以在那個年代rpc很活躍,client、server雙方約定服務結構,以[類本地調用]的形態通信。

90年代,隨著it產業的蓬勃發展,計算機走進了千家萬戶,90年代初期誕生了瀏覽器, 瀏覽器與上面的C/S結構最大的不同是訪問的服務端對象是千萬家不同的服務提供方。

再像C/S那樣一對一提前溝通契約就不合適了, 故瀏覽器和web服務器作為一種特殊的C/S需要約定一種【固定的、能自表述的傳輸格式】, 于是誕生了適用于B/S端的http協議。 http協議不再有rpc雙方已知的本地服務名和服務方法, 服務和服務方法被金演化成對遠程主機的資源請求。

所以,我們該問的不是“既然有HTTP協議,為什么要有RPC”,而是應該問“為什么有rpc,還需要有http”。


從上面的前世今生可以知道, rpc是通信框架,http是通信協議,rpc可以基于tcp,udp,http/2協議來實現。

grpc在眾多rpc框架中脫穎而出,取決于底層的http2基礎設施。

3. grpc到底利用了http/2的什么特性?

回過頭來看grpc的連兩個定語 ① http/2 ② 高性能。

grpc底層傳輸使用http/2,http/2兼容http1.1語義,還有如下優勢

http2 http1.1
用于數據傳輸的二進制分幀 http1.1是基于文本協議
同一tcp連接支持流式傳輸,故支持發送多個并行請求、調用 應答模型:http1.1在一個tcp連接上完成[請求/響應]是串行的
減少網絡使用率的標頭壓縮 頭部帶有大量信息,每次都要重復發送

http2的二進制分幀、流式傳輸 能力支撐了grpc框架近乎本地的實時服務互調;

http2的多路復用(單tcp連接上并發多個請求,不多占文件描述符)、二進制編碼協議、頭部壓縮支撐了grpc本地互調的高性能。

這里要指出:

  • HTTP/2 上的通信只需要在一個TCP連接完成,在這個連接上可見的形態是幀frame和流stream。

  • 而消息(或者說業務調用,業務上的邏輯發送單位)由一或多個幀組成,這些幀可以亂序發送,然后根據每個幀首部的流標識符重新組裝。

  • "gRPC雙向流通信streaming"與"http2的流式stream傳輸"是一個東西嗎?
    http2流式傳輸stream是一種底層的傳輸方式,其作用是支撐單連接多路復用 。
    grpc流式通信streaming,更接近業務通信級別的通信方式,grpc流式通信可用于替代高性能場景下的一元gRPC調用。

我們假設HTTP/2協議中1次RPC請求使用1個并發Stream,每個RPC消息又可 通過幀體中 Length-Prefixed Message 頭部確立了邊界,這樣,在 Stream 中連續地發送多個 DATA 幀,就可以實現流模式 RPC。
https://juejin.cn/post/7249522846211801147

tcp連接現在是性能瓶頸

底層的http2協議給予了grpc很大的性能表現,但同時也帶來了新的性能瓶頸, 現在現在壓力給到了tcp連接。

通常情況下,一個HTTP/2 tcp連接中流的數量是有限制的,一般服務器默認為100,不同的語言有不同的應對策略。

.net

.net tcp連接上默認流數量為100,當該連接中的grpc調用導致到達"連接流的限制",新的grpc調用會進行排隊,這個時候會出現因Concurrent stream=100引起的性能問題。

.NET引入了EnableMultipleHttp2Connections可在此時產生新的連接對象。

var channel = GrpcChannel.ForAddress("https://localhost", new GrpcChannelOptions
{
    HttpHandler = new SocketsHttpHandler
    {
        EnableMultipleHttp2Connections = true,

        // ...configure other handler settings
    }
});

golang

[golang tcp連接上流數量的默認限制也是100](https://github.com/grpc/grpc-go/blob/master/internal/transport/http2_client.go)defaultMaxStreamsClient =100.
可通過ServerOption: MaxConcurrentStreams修改, 從實現上默認的并發流的限制,被設計成池的概念,

類似與C# 也有利用tcp連接池來規避該問題的方案, 按下不表。
https://segmentfault.com/a/1190000041716350?utm_source=sf-similar-article
https://github.com/shimingyah/pool

我們先來分析grpc基于http2 stream概念發起調用的源碼。

創建一個gRPC 客戶端連接,會創建的幾個協程:

1)transport.loopyWriter.run 往服務端發送數據協程

2)transport.http2Client.reader 讀取服務端數據協程

http2Client的基礎結構

// 源碼所在文件:google.golang.org/grpc/http2_client.go
// http2Client 實現了接口 ClientTransport
// http2Client implements the ClientTransport interface with HTTP2.
type http2Client struct {
  conn net.Conn       // underlying communication channel
  loopy *loopyWriter  // 生產和消費關聯的隊列在這里面,所在文件:controlbuf.go

  // controlBuf delivers all the control related tasks (e.g., window
	// updates, reset streams, and various settings) to the controller.
	controlBuf *controlBuffer // 所在文件:controlbuf.go
  
  maxConcurrentStreams  uint32
  streamQuota           int64
  streamsQuotaAvailable chan struct{}
  waitingStreams        uint32
  
  initialWindowSize int32
}

type controlBuffer struct {
  list *itemList // 隊列
}

type loopyWriter struct {
  // 關聯上 controlBuffer,
  // 消費 controlBuffer 中的隊列 list,
  // 生產 由http2Client通過controlBuffer 進行。
  cbuf *controlBuffer
}

創建grpc客戶端的行為

func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts ConnectOptions, onPrefaceReceipt func(), onGoAway func(GoAwayReason), onClose func()) (_ *http2Client, err error) {
  conn, err := dial(connectCtx, opts.Dialer, addr.Addr)
  t.controlBuf = newControlBuffer(t.ctxDone) // 含發送隊列的初始化

  if t.keepaliveEnabled {
		t.kpDormancyCond = sync.NewCond(&t.mu)
		go t.keepalive() // 保活協程
	}
  
  // Start the reader goroutine for incoming message. Each transport has
	// a dedicated goroutine which reads HTTP2 frame from network. Then it
	// dispatches the frame to the corresponding stream entity.
  go t.reader()
  
  // Send connection preface to server.
	n, err := t.conn.Write(clientPreface)
  
  go func() {
    t.loopy = newLoopyWriter(clientSide, t.framer, t.controlBuf, t.bdpEst)
    err := t.loopy.run()
  }
}

特別說明:
每一次 gRPC 調用,客戶端均會創建一個新的 Stream,
該特性使得同一 gRPC 連接可以同時處理多個調用。請求的發送并不是同步的,而是基于隊列的異步發送。

// 源碼所在文件:internal/transport/controlbuf.go
func (l *loopyWriter) run() (err error) {
  // 通過 get 間接調用 dequeue 和 dequeueAll
  for {
    it, err := l.cbuf.get(true)
    if err != nil {
			return err
		}
		if err = l.handle(it); err != nil {
			return err
		}
		if _, err = l.processData(); err != nil {
			return err
		}
  }
}

每一個gRPC客戶端連接均有一個自己的隊列,gRPC 并沒有直接限定隊列大小,所以如果不加任何限制則會內存暴漲,直到OOM發生。

這里我們結合內存泄漏的案例加深tcp連接在grpc調用中的獨特作用。

go func() {
		for {
			ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
			defer cancel()
			resp, err := c.election.Leader(ctx)
			if err != nil {
				log.WithError(err).Errorf("get leader error. test")
			} else {
				log.Infof("get test leader success :  %s", string(resp.Kvs[0].Value))
			}
			 // cancel()
		}
	}()

pprof 顯示這個election.Leader函數導致的內存持續增長。

bug表象

etcd v3 發起的請求為grpc請求,

  • 因為從closed信道能持續讀取零值,形成死循環。

  • 死循環中,用于上下文釋放資源的defer cancel() 無法得到執行,因為是在函數級別。

  • 每次grpc調用均形成緩慢內存泄漏。

總結

以上是生活随笔為你收集整理的grpc是基于http/2协议的高性能的rpc框架的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 免费中文字幕日韩 | av免费播放网站 | 日韩精品激情 | 黑人100部av解禁片 | 国产美女网 | 精品人妻中文无码av在线 | 亚洲日本一区二区三区 | 日日夜夜天天 | 无码无套少妇毛多18pxxxx | 成人av在线网站 | 中文在线资源 | 成人天堂噜噜噜 | 色久综合网 | 天堂av观看 | 日操干 | 美女脱了内裤喂我喝尿视频 | 亚洲AV无码国产精品国产剧情 | 免费看91 | 天天操夜夜操狠狠操 | 熟女肥臀白浆大屁股一区二区 | 国产成人精| 色欲狠狠躁天天躁无码中文字幕 | 男人的天堂av网 | 亚洲一级影院 | 波多野吉衣av | 国产女人高潮时对白 | 99热这里都是精品 | 三级中文字幕 | 国产精品va | 免费在线看污视频 | 日韩网站在线观看 | 久久精品高清视频 | 国产亚洲一区二区在线 | av最新地址 | 亚洲一区二区日韩欧美 | 天天综合亚洲 | 99福利视频 | 91久久久久 | 成人欧美一区二区三区小说 | 爆乳熟妇一区二区三区霸乳 | 亚洲va国产天堂va久久 en | 日韩欧美一级在线 | 中文免费av| 国产精品免费观看视频 | 久久久久亚洲av成人网人人软件 | 福利姬在线观看 | missav | 免费高清av在线看 | 久久婷婷影院 | 人妖干美女 | 精品国产乱码久久久久夜深人妻 | 免费一级黄 | 午夜91视频 | 日本欧美在线播放 | 国产男女啪啪 | 国产精品我不卡 | 欧美一区二区三区黄色 | 亚洲精品无人区 | 神马影院午夜伦理 | 在线观看免费大片 | 久久福利免费视频 | 成人毛片软件 | 日本视频色 | 阿v天堂2018 俄罗斯丰满熟妇hd av色吧 | 亚欧成人精品 | 国产丝袜自拍 | 国产毛片毛片毛片毛片毛片 | 美女视频一区二区三区 | 亚洲一区二区三区四区五区六区 | 久久久精品在线 | 枫可怜av | 一本一道无码中文字幕精品热 | www.色黄| 中文字幕久久久久久久 | 亚洲精品久久久乳夜夜欧美 | 欧美精品日韩精品 | 综合久久精品 | 超碰.com | 在线色网 | 日韩电影一区二区三区四区 | 波多野结衣家庭主妇 | 岛国av中文字幕 | 亚洲男人天堂2024 | 性做久久久久久久 | 91香蕉国产 | 久久精品一区二区三 | 日本欧美中文字幕 | 成人毛片在线视频 | 日韩精品2| 伊人久久精品视频 | 日韩精品一区二区电影 | 就要日就要操 | 视频一区国产精品 | 黄色激情在线观看 | 欧美老少做受xxxx高潮 | 少妇性高潮视频 | 成人羞羞在线观看网站 | 人人看人人插 | 在线黄色免费网站 | 国产三级精品在线观看 |