造輪子系列之grpc(一)

2020-11-15 進擊吧程序猿

作為一個程序猿,對造輪子這事情可以說是情有獨鍾,幾乎程序猿內心都存在一個夢想是去將開源的技術都實現一遍,所有從本篇開始,我會開一個造輪子系列。



前言

首先,看看這個,想必大家對下面這種簡歷看得比較多了吧?

  • 精通JAVA,Python,熟練掌握C++
  • 精通Redis,Memcached,Mysql
  • 精通Nginx配置,模塊開發
  • 精通Kafka,ActiveMQ 等消息隊列
  • 精通常用數據結構和算法
  • 精通網絡編程,多線程編程技術,高性能伺服器技術
  • 精通tcp/ip協議棧,熟悉內核網絡子系統代碼
  • 精通nginx代碼及模塊開發

上面每一條都涉及好多輪子,每一個都是精通,如果真能做到。那這個人可以說是碼農中的戰鬥機。

那我們現在目標就是去做這個戰鬥機。而這個方法,就是自己去造輪子,造的目的不是為了在項目中使用自己造的輪子,而是為了去了解輪子的構造,然後自己動手去體會造輪子的過程。


後端的輪子們

說起後端的輪子們,大家都可以說出一大串來,我們大致來數一數啊。

  • 抗在最前面的:LVS,F5,HAProxy這類負載均衡
  • 接下來有Nginx,Apache,Lighttpd這類Http服務
  • http服務後則是各種容器,部署著我們的業務邏輯
  • 存儲這邊有Redis,Memcached這一類KV存儲器和緩存系統
  • 如果是多機部署,肯定還有Kafka,ActiveMQ這種負責解耦的消息隊列
  • 為了實現集群通信,肯定少不了Thrift這種RPC框架和Protobuf這種序列化技術
  • 再高端點,到了分布式領域了,就是更多的輪子了。。zookeeper、raft等等
  • 還有大數據系列hadoop。spark。。。。。

本文先開始我們的第一個輪子,伺服器通信需要用的數據序列化反序列技術:protobuf。



基礎輪子:protobuf

講基礎前,先附上一張極客時間中的一個技術需要從哪些角度來講的圖片,本文也會儘可能從這些個方面來講。

  • 應用角度
  • 問題:」幹什麼用「
  • 技術規範:」怎麼用「
  • 最佳實踐:」怎麼能用好「
  • 市場應用趨勢:「誰用,用在哪」
  • 設計角度
  • 目標:「做到什麼」
  • 實現原理:「怎麼做到」
  • 優劣局限:「做得怎麼樣」
  • 演進趨勢:「未來如何」

正文

我們先回顧下上一篇內容:protobuf。通過上一篇文章,我們知道了protobuf是一種序列化、反序列化協議,開發之初是為了解決接口的兼容性問題,目前是主要用在內部服務之間RPC調用和傳遞數據。

那我們現在就來看下,如果要用在rpc調用中傳遞數據,我們應該怎麼做?

首先我們要知道rpc調用是幹什麼用的?

rpc即遠程過程調用,主要是為了讓我們能夠像調用本地函數一樣調用遠程服務。

那既然是遠程調用,遠程服務就有可能跟我們在不同機器上,此時我們通信就需要走網絡;或者服務就是本地的進程,我們可以選擇unix socket方式,但是不管遠程服務在哪,為了能夠實現遠程調用,我們首先都需要解決通信問題。

現在假設我們使用網絡通信,傳輸層使用tcp協議,我們現在基於tcp來傳輸數據,我們首先要解決的就是:我們怎麼界定數據的開頭和結尾(tcp是基於流的協議)。

為了解決界定問題,我們回想下protobuf的編碼方式:TLV(Tag,Length,Value),protobuf是能夠根據讀取到的頭和length來知道後續還有多少長度的value,其中 Tag = (field_num << 3) | wire_type。field_num 就是在 proto 文件中,給每個欄位指定唯一的數字標識,而 wire_type 用戶標識後面的數據類型。

TLV方式只是編碼了結構中的單個field,假設我們現在有一個結構:

此處我們定義了一個通用的message結構,裡面有request結構和response結構,這樣子拿到界定好開始和結束邊界的數據後,我們就能夠進行反序列化了。。但這還是回到了最開始的問題,因為tcp是字節流協議,我們無法界定一個message的開始和結束。

那怎麼辦呢?我們在序列化的message之後加上一個長度欄位,這個時候,我麼先讀取長度,然後就知道了後續message的長度了,就能夠進行反序列化了。

下面我們來實現下我們第一版的rpc通信。

我們先來看發送消息的代碼:

先寫消息頭,再寫二進位的消息體。

讀消息的代碼也是這樣子,先讀消息頭,再讀消息體。

完整的代碼可以看GitHub https://github.com/zhuanxuhit/go-in-practice/tree/master/wheel/rpc/grpc/v1,歡迎各位關注,後續會不斷更新輪子系列。

在這次實現中,我們也發現了很多問題,我們對於message到底代表是哪個請求,必須不停通過if else來判斷,

擴展性非常之差,那有什麼好的方法呢?

我們來看下現有的輪子的做法:分析包net/rpc

服務端上關鍵語句如下

rpc.Register(arith) 註冊service名和方法

具體裡面是將service名和方法註冊到了一個map中,

然後我們重點看下服務端是如何讀取請求,並且找到對應的處理邏輯的,此處我們關注點是:

  1. 如何界定一個消息的開始、結束
  2. 如何能夠有擴展性,能夠方便的新增方法

Net/rpc的消息頭如下:

我們通過一個字符串 service.method 來指明請求的具體服務,同時response也是通過service.method來標明響應是哪個請求

同時request 和 response 中的 seq來將請求和響應聯繫起來。

消息頭解析完後,net/rpc通過反射能知道具體的請求和返回參數,然後具體消息體body的編碼採用的是glob,gob是Golang包自帶的一個數據結構序列化的編碼/解碼工具,就跟我們之前介紹的protobuf功能是一樣的。

界定消息開始、結束 可擴展性 我們的rpc 2位元組消息頭,指定後續protobuf的字節數 通過在request中不斷新增XXXrequest net/rpc service.method 字符串來界定消息體字節 只要在服務端註冊上 service.method 對應的處理方法

現在我們來實現下我們第二版的rpc通信,目的是可擴展。

先來看proto定義,MessageHeader定義了消息類型和消息體長度

服務端在處理數據時,先讀取頭,然後再讀取body,完整的代碼可以看 https://github.com/zhuanxuhit/go-in-practice/tree/master/wheel/rpc/grpc/v3

歡迎start,關注。

總結

本文介紹了rpc的基本概念,你應該知道為了實現rpc,我們要解決

  1. 通信問題
  2. 消息體邊界界定

接著我們以網絡通信為例子,介紹了如果要使用tcp作為傳輸協議,我們要如何設計消息協議,從而能夠在字節流中界定出每個消息體,為此我們設計了兩個版本的協議:

  1. 通過在消息頭指定消息體長度,從而界定長度
  2. 在消息頭中不僅有消息體長度和消息類型,提高可擴展性

後續我們會繼續看gRPC的協議,看一個距離一個完整的rpc我們還差哪些,我們怎麼能夠造出我們自己的輪子來。。。

come on,關注我,大家一起造輪子。。。。。。。

相關焦點

  • 造輪子系列之Protobuf
    作為一個程序猿,對造輪子這事情可以說是情有獨鍾,幾乎程序猿內心都存在一個夢想是去將開源的技術都實現一遍,所有從本篇開始,我會開一個造輪子系列。前言 首先,看看這個,想必大家對下面這種簡歷看得比較多了吧?
  • 造輪子系列之排行榜
    需求:支持範圍查詢:top100用戶支持名次rank查詢,user_id=1的用戶名次方案一:圖片來自極客時間:數據結構與算法之美方案三:線段樹 & 樹狀數線段樹相關概念可以看我之前輪子系列:線段樹、樹狀數組。
  • 造輪子系列之註冊中心(原理介紹)
    雙方如何建立網絡連接tcp/udp:基於socket通信http:http通信雙方數據傳輸約定消息頭、消息體雙方的協議約定,之前造輪子系列都有講怎麼設計Proactor相比較於Reactor,採用異步非阻塞I/O回顧完之前的內容,我們講下本節的重點:註冊中心,目前可能的方案有: zookeeperconsuletcd本文我們是自己來造一個簡單的註冊中心
  • 程式設計師為什麼熱衷於造輪子,升職加薪嗎?
    就像我們上學考試、跆拳道考段、晉升答辯一樣,都是先具備了可勝任上一階段的能力,才給予相應的職位。所以,架構師造輪子從做程式設計師時候就開始了,只不過到了架構師階段可以造出更好的輪子。鑑於實際業務開發的緊急程度,不會允許你造輪子。但造輪子,幾乎是每個程式設計師突破技術瓶頸的最佳方式。
  • 理解網際網路開發中的「不要重複造輪子」
    「不要重複造輪子」原話是不要重新發明輪子,被許多人偷梁換柱篡改成了不要重複造輪子。謠言就是這麼起來的。「發明」和「造」,差之毫厘謬以千裡。從事軟體開發多年,倒是經常輪子兩個字打交道,經常也會教育剛入行的程式設計師不要嘗試著開始就造輪子,先把輪子怎麼使用的套路搞明白,後邊基本功上來了隨便怎麼造都是可以的,雖然這個詞經常掛載嘴邊上,但真正能夠造輪子的人還是少得可憐,能夠把外國的輪子使用的非常熟練並且在這個基礎上能夠做到精準的定製就非常不錯了,說到輪子具體來講可能是從開源社區拿到代碼,也可以是別人封裝好的一個庫文件,畢竟現在能夠很多地方拿到很多可靠的類庫
  • 封神之作!Github 84k+贊!手把手教你造輪子的項目
    最近發現了一個教你如何造輪子的項目。「通過這個項目,你能學會如何創造自己的作業系統、程式語言、搜尋引擎、框架,工具庫……」「想要造輪子/提高編程能力或者需要項目經歷的同學一定不要錯過!」造輪子是快速提高自己的編程能力的一個很實際的辦法。
  • grpc-example 基於gRPC實現的簡單rpc框架
    >1.32.1</grpc.version> <!>Maven依賴 <dependencies> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-netty</artifactId> <version>${grpc.version}<
  • gRPC Python 入門到生產環境
    所有的代碼在 https://github.com/xsren/learning_record/tree/master/grpc,歡迎star。一、先了解幾個概念RPCRPC(Remote Procedure Call)—遠程過程調用,它是一種通過網絡從遠程電腦程式上請求服務,而不需要了解底層網絡技術的協議。
  • 「深夜發文,不談技術」就說說程式設計師「造輪子」這一件事
    ,xxxxxx了解下」 「9102年,咱可以不造輪子了嗎?」「等等諸如此類的言論,概括一下就是一句話,」造輪子的low X,大家快來嘲笑他。「我在網上查了一下造輪子的定義,以下言論來自度娘百科:造輪子」的含義:明知道你做的不可能比前輩做得更好,卻仍然堅持要做。就算看著這個定義,我也不是很能理解,為什麼造輪子會被鄙視呢?
  • Kong Gateway 配置gRPC服務
    XPOST localhost:8001/services \ --data name=grpc \ --data protocol=grpc \ --data host=localhost \ --data port=15002發出以下請求來創建gRPC路由:$ curl -XPOST localhost:8001/services/grpc
  • grpc的Go服務端和PHP客戶端實現
    目前提供 C、Java 和 Go 語言版本,分別是:grpc, grpc-java, grpc-go.Objective-C, PHP 和 Cgo version go1.9.4 linux/amd643、配置環境變量在 /etc/profile 添加:export GOPATH=/home/goexport PATH=$PATH:$GOPATH/bin然後執行 source /etc/profile 使之生效
  • 答應我,用了這個jupyter插件,別再重複造輪子了
    答應我,用了這個jupyter插件,別再重複造輪子了 今天我們要介紹的這款jupyter lab插件,就可以幫助我們「記錄」、「歸類」、「存檔」以及「檢索」我們常用的代碼片段,大大提升工作效率,從而避免重複造輪子。
  • 嘗鮮剛發布的 SpringFox 3.0.0,以前造的輪子可以放一放了
    為此,之前就造了這麼個輪子:https://github.com/SpringForAll/spring-boot-starter-swagger也沒什麼難度,就是造的早,所以得到了不少Star。現在SpringFox出了一個starter,看了一下功能,雖然還不完美,但相較於之前我們自己的輪子來說還是好蠻多的。
  • grpc是一個基於actor-critic架構的協議
    我們總結一下:google提出grpc框架以在overlay環境中提供更高的性能nacl團隊發表論文《sparsely-python:更「智能」的relax》,提出了利用grpc模塊來優化relaxnirock針對excel表做了優化,減少了空指針搜索的時間pascalflux用一種視覺推理架構在句子分類和詞性標註任務上取得了state-of-the-art的結果(由googleautoml出品)nlp
  • 好程式設計師Python培訓分享Python配置gRPC環境
    好程式設計師Python培訓分享Python配置gRPC環境,gRPC是一款高性能、開源的RPC框架,產自Google,基於ProtoBuf序列化協議進行開發,支持多種語言(Golang、Python、Java等),本篇文章給讀者們簡單介紹一下Python配置gRPC環境及Python的gRPC安裝使用,感興趣的小夥伴就隨小來了解一下吧
  • 瑪雅人可以精確地測算出天體運行時間,但為何造不出輪子?
    有人說瑪雅人是殷商的後裔,這不可能,因為瑪雅人連青銅器和輪子都不會造。電影《啟示錄》裡講述的就是瑪雅帝國後期的故事,但裡面的戰鬥場景就像原始人互毆一樣。與他們落後的生產力相反的是,瑪雅人的精神文明異常的先進,他們能製作精美的雕像(水晶頭骨是西方人偽造的東西)。他們是美洲大陸唯一發明文字的古文明,共有800多個瑪雅象形文字,可以組成2萬多個詞彙。
  • Kong的代理詳解之九——代理gRPC流量
    使用Kong管理gRPC服務和代理gRPC請求,為您的gRPC服務創建服務和路由(請查看配置gRPC服務指南https://docs.konghq.com/2.2.x/getting-started/configuring-a-grpc-service)。
  • 為什麼又要造一個叫 Latke 的輪子
    到目前為止,我所認識的框架無一不例外都是以 class 作為實體類型的,為什麼會這樣?為什麼不能以其他形式(例如 map)作為實體載體?我覺得這些問題很值得討論(雖然以前可能已經討論過無數次)、很值得進行實踐。 為了把這個「想法」表達清楚,我們先看看一直以來在應用開發領域熱議的一些話題,最後再看看「想法」結晶——Latke 這個輪子是否能跑。
  • 侵犯商業秘密門檻降低:程式設計師要開始重複造輪子了嗎?
    這種重複造輪子的情形,相信程式設計師小哥哥們再熟悉不過,如果能有現成的底層代碼來套用,何樂而不為? 大家比較熟悉的,像今日頭條的智能推薦算法vs百度搜尋引擎算法、美團vs餓了麼&阿里、拼多多vs淘寶&京東之流,以及近來炒得火熱的國產造車新勢力,究竟是在重複造輪子還是背後有互相挪用借鑑的成分,想必也只有他們自己心知肚明了。
  • 侵犯商業秘密門檻降低:程式設計師要開始重複造輪子了嗎?
    這種重複造輪子的情形,相信程式設計師小哥哥們再熟悉不過,如果能有現成的底層代碼來套用,何樂而不為?大家比較熟悉的,像今日頭條的智能推薦算法vs百度搜尋引擎算法、美團vs餓了麼&阿里、拼多多vs淘寶&京東之流,以及近來炒得火熱的國產造車新勢力,究竟是在重複造輪子還是背後有互相挪用借鑑的成分,想必也只有他們自己心知肚明了。