前言
?溝通服務(wù)間接口內(nèi)容(尤其是前后端接口),是非常讓人頭疼的事。極其容易扯皮。接口文檔寫起來也很痛苦,每個字段的改動都需要及時更新,否則就會出問題。服務(wù)端通信如果用rpc通信的話,一般會有proto或者thrift文件。這個文件很長時間里被我們當成接口文檔用,用著用著發(fā)現(xiàn),真tm好用。既減少了扯皮,還不用寫接口文檔。那可不可以用grpc和前端通信那,一開始我們的做法是用grpc-gateway。把grpc的接口映射成http接口。但這種方式需要編譯gateway的pb文件,對服務(wù)也是有侵入的。后來隨著我在公司的時間越來越長,接手的服務(wù)越來越多(經(jīng)常需要發(fā)版的項目就有十幾個),這種方式維護起來十分糟心,后一直想尋求一種一勞永逸的解決方法? ?本人之前很長一段時間從事saas,paas的開發(fā)。對于一些服務(wù)而言,既要提供grpc訪問的能力,也要對外提供http訪問的能力(做saas就是這么卑微)。并且這種需求通常不是一開始就提出來的,而是對一個已經(jīng)穩(wěn)定運行的龐大的服務(wù)做改造。而這會導致爬屎山,鑒權(quán)不一致等一系列問題。那有沒有一種無侵入的協(xié)議轉(zhuǎn)換能力? ? grpc是基于http2協(xié)議,而http2是長連接。這對k8s部署的服務(wù)非常不友好。在這我猜肯定有很多小伙伴說可以用linked,istio等基于Service Mesh的解決方案。一是這些技術(shù)是近兩年才穩(wěn)定下來的,以前問題很多,根本不敢用,當然現(xiàn)在istio已經(jīng)流行起來了,可以很完美的做到grpc的負載均衡和很優(yōu)秀的流量管理。但依然存在不滿足實際需求的情況,比如對grpc流量做精細過濾,細到每個請求的精準控制。這種二次開發(fā)的需求是很難在istio上完成。尤其是對一些小公司而言?;诤芏嘣虻目紤],最終誕生了搞一個grpc動態(tài)代理的想法,并初步實現(xiàn)。grpc
? 在云原生,容器化,微服務(wù)的大背景下。rpc也徹底奠定了服務(wù)間通信協(xié)議的霸主地位。眾多rpc框架中g(shù)rpc和thrift是最流行最受歡迎的rpc框架。在實際開發(fā)中,我兩個框架都有深入的使用過。相較而言,我更喜歡grpc的風格。背靠google大樹(已經(jīng)是CNCF孵化項目),多語言都支持,基于protobuf極致編碼和急速傳輸,等等優(yōu)點就不一一詳述。有興趣的可以看grpc官網(wǎng),上面吹的比我吹的好。實踐
github地址
https://github.com/woshihaoren4/grpc-proxy第一步
先將代碼clone下來到本地,我這里用的mac系統(tǒng) 因為編譯需要cargo環(huán)境,需要先安裝rust,參考教程:https://www.rust-lang.org/zh-CN/上面有很詳細的中文教程。我安裝的是:rustc 1.66.0 (69f9c33d7 2022-12-12)
版本第二步
先進入項目根目錄,運行起測試例子./example/helloworld server 沒有權(quán)限的話,需要先加權(quán)限,然后再運行 chmod +x ./example/helloworld 這個例子使用golang編寫的簡單的grpc服務(wù),實現(xiàn)上沒有啥特殊的部分,值得注意的是需要給grpc服務(wù)加上反射
//grpc的HelloWorld方法實現(xiàn),就是在字符串上加一個 world func (s *Service) HelloWorld(ctx context.Context, req *proto.HelloWorldRequest) (*proto.HelloWorldResponse, error) { return &proto.HelloWorldResponse{Response: req.Request + " world"}, nil } //這里相當于main函數(shù) func server(ctx *wdevent.Context) error { ls, _ := net.Listen("tcp", ":8888") gs := grpc.NewServer() proto.RegisterHelloWorldServiceServer(gs, new(Service)) reflection.Register(gs) logrus.Infoln("grpc server start workd ....") gs.Serve(ls) return nil } 再看一下pb文件,需要注意的是在option里指明 需要映射的http的路徑和方法
syntax = "proto3"; package proto; option go_package = "./proto"; import "google/api/annotations.proto"; // HelloWorld Service service HelloWorldService { rpc HelloWorld(HelloWorldRequest) returns (HelloWorldResponse){ option (google.api.http) = { post: "/api/v2/hello" body: "*" }; }; } message HelloWorldRequest { string request = 1; } message HelloWorldResponse { string response = 1; }
第三步
修改配置文件如下,路徑:./src/config/config.toml。當前項目中的配置文件已經(jīng)寫好了這些內(nèi)容,不需要再配置什么了。當然不放心也可以查看一下。[[proxy_sink]] name = "hello" addr = "127.0.0.1:8888"
- 需要在addr中指明上面服務(wù)的地址和端口。
第四步
另起終端,編譯并運行項目cargo run -- run 國內(nèi)沒有科學上網(wǎng)的話會有些慢,主要是下載包比較慢,可以用清華源或者其他的,教程參考:https://www.w3cschool.cn/cargo_guide/cargo_guide-uxdg3l62.html 服務(wù)啟動后會打印如下日志,說明服務(wù)啟動成功
測試
發(fā)起一個http請求curl --location --request POST 'http://127.0.0.1:6789/api/v2/hello' --header 'Content-Type: application/json' --data-raw '{ "request": "hello" }' 可以看到返回內(nèi)容:
{"response": "hello world"}
并且在代理服務(wù)上產(chǎn)生訪問日志:?到這里一個簡單的演示就成功了結(jié)構(gòu)和原理
主要是根據(jù)grpc的反射的描述,生成http路由,并動態(tài)完成json和proto的映射。更進一步的原理和結(jié)構(gòu),未完待續(xù)~尾語
當前版本還只是一個比較初級的版本,功能還很初級。還有很多功能需要完善,架構(gòu)也可能會有大的變動,所有上一節(jié)并沒有詳細描述。作者預計但不承諾會繼續(xù)完成下面的內(nèi)容。- restful支持:這個功能是P0級,在我go版本的grpc動態(tài)代理服務(wù)中經(jīng)常被用到,在可預計的規(guī)劃里一定會實現(xiàn)。
- 事件系統(tǒng):該功能是為了方便二次開發(fā),很有必要。也有可能用中間件模式,類似traefik
- 負載均衡/sidecar:負載均衡是為了用在服務(wù)網(wǎng)關(guān)上,sidecar是用在pod里,二者會選一個實現(xiàn),我傾向于前者,和我之前寫的rust-ingress聯(lián)動上。這里自薦一波rust-ingress項目:https://gitee.com/yutiandou/rust-ingress
- 性能優(yōu)化,這個會一直持續(xù)做下去,歡迎有性能極致追求的小伙伴能夠共同前進
- 實時反射:目前是通過配置文件,在啟動的時候加載服務(wù)源。好的(懶人)方案是proto文件變化后能夠?qū)崟r監(jiān)控到,下一步會完成這個功能。
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。
舉報投訴
-
通信協(xié)議
+關(guān)注
關(guān)注
28文章
899瀏覽量
40348 -
HTTP
+關(guān)注
關(guān)注
0文章
510瀏覽量
31357 -
編碼
+關(guān)注
關(guān)注
6文章
951瀏覽量
54882
原文標題:尾語
文章出處:【微信號:Rust語言中文社區(qū),微信公眾號:Rust語言中文社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
GRPC的基礎(chǔ)使用方法
語言的 gRPC 客戶端和服務(wù)器實現(xiàn),它提供了一個簡單易用的 API,可以方便地創(chuàng)建和使用 gRPC 服務(wù)。 基礎(chǔ)用法 創(chuàng)建
JDK動態(tài)代理的原理
在Java中,動態(tài)代理是一種機制,允許在運行時動態(tài)地創(chuàng)建代理對象來代替某個實際對象,從而在其前后執(zhí)行額外的邏輯。 為什么JDK
特斯拉馬斯克稱在城市里搞飛行汽車是個愚蠢的想法
馬斯克稱在城市里搞飛行汽車是個愚蠢的想法。同時,他還提到了自己的地下隧道計劃,馬斯克認為這項計劃雖然也非常瘋狂,但比飛行汽車好多了。
發(fā)表于 02-18 11:24
?1123次閱讀
java的動態(tài)代理機制和作用
的我們的功能,我們更需要學習的是其底層是怎么樣的一個原理,而AOP的原理就是java的動態(tài)代理機制,所以本篇隨筆就是對java的動態(tài)機制進行
發(fā)表于 09-27 14:37
?0次下載
java動態(tài)代理分析
定義:為其他對象提供一種代理以控制對這個對象的訪問。 動態(tài)代理使用 java動態(tài)代理機制以巧妙的
發(fā)表于 09-27 15:14
?0次下載
java動態(tài)代理機制詳解的類和接口描述
的我們的功能,我們更需要學習的是其底層是怎么樣的一個原理,而AOP的原理就是java的動態(tài)代理機制,所以本篇隨筆就是對java的動態(tài)機制進行
發(fā)表于 09-28 13:33
?0次下載
java的動態(tài)代理
代理類的對象與一個委托類的對象關(guān)聯(lián),代理類的對象本身并不真正實現(xiàn)服務(wù),而是通過調(diào)用委托類的對象的相關(guān)方法,來提供特定的服務(wù)。 按照
發(fā)表于 03-12 14:12
?0次下載
基于JDK和CGLB分別實現(xiàn)的動態(tài)代理
本文檔內(nèi)容介紹了基于JDK和CGLB分別實現(xiàn)的動態(tài)代理及源代碼
發(fā)表于 03-12 14:56
?0次下載
什么是動態(tài)ip代理電腦軟件?
動態(tài)IP代理計算機軟件是計算機瀏覽器和Web群集服務(wù)器之間的網(wǎng)絡(luò)服務(wù)器。如果使用動態(tài)IP代理計算機軟件訪問Internet,則計算機瀏覽器不會立即轉(zhuǎn)到Web網(wǎng)絡(luò)服務(wù)器來檢索網(wǎng)頁,而是僅
發(fā)表于 01-14 18:06
?981次閱讀
IP知識百科之什么是gRPC
對網(wǎng)絡(luò)設(shè)備進行配置和管理的一種方法。 gRPC vs REST REST(Representational State Transfer)表征狀態(tài)轉(zhuǎn)移,是一種軟件架構(gòu)風格,同樣為管理和配置網(wǎng)絡(luò)設(shè)備提供
正確使用gRPC與GraphQL
TLDR:使用 GraphQL 進行客戶端-服務(wù)器通信,使用 gRPC 進行服務(wù)器到服務(wù)器通信。有關(guān)此規(guī)則的例外情況,請參閱“判定”部分。 我已經(jīng)閱讀了很多關(guān)于這兩種協(xié)議的比較,并想寫一個
Golang實現(xiàn)一個簡單的http代理
本文詳細介紹了Golang 實現(xiàn) http 代理的實現(xiàn),在實際業(yè)務(wù)中有需求的同學可以學起來了!
mybatis接口動態(tài)代理原理
MyBatis是一款輕量級的Java持久化框架,它通過XML或注解配置的方式,將數(shù)據(jù)庫操作與SQL語句解耦,提供了一種簡單、靈活的數(shù)據(jù)訪問方式。在MyBatis中,使用動態(tài)代理技術(shù)來
使用go語言實現(xiàn)一個grpc攔截器
在開發(fā)grpc服務(wù)時,我們經(jīng)常會遇到一些通用的需求,比如:日志、鏈路追蹤、鑒權(quán)等。這些需求可以通過grpc攔截器來實現(xiàn)。本文使用go語言來實現(xiàn)
評論