01 RPC簡介原理及用Go實現乙個RPC

2022-07-01 09:39:09 字數 4894 閱讀 2677

rpc簡介

本地過程呼叫

// 正常情況下程式的執行和呼叫情況。例如有如下go語言**:

package main

import "fmt"

func main()

func add(a int,b int) int

在上述的go語言**中,我們定義了乙個add方法用於實現兩個數相加的功能,在main方法中通過呼叫add方法實現了計算兩個變數之和的操作。整個過程涉及到變數值入棧,出棧,賦值等操作,最後將出棧的計算結果返回並賦值給c變數。

總結說來,本地程式呼叫的過程大致可以分為幾個步驟和階段:

// 1.開發者開發好的程式,並進行編譯,編譯成機器認可的可執行檔案。

// 2. 執行可執行檔案,呼叫對應的功能方法,期間會讀取可執行檔案中國的機器指令,進行入棧,出棧賦值等操作。

// 此時,計算機由可執行程式所在的程序控制。

// 3. 呼叫結束,所有的記憶體資料出棧,程式執行結束。計算機繼續由作業系統進行控制。

遠端過程呼叫是在兩台或者多台不同的物理機器上實現的呼叫,其間要跨越網路進行呼叫。因此,我們再想通過前文字地方法呼叫的形式完成功能呼叫,就無法實現了,因為編譯器無法通過編譯的可執行檔案來呼叫遠端機器上的程式方法。因此需要採用rpc的方式來實現遠端伺服器上的程式方法的呼叫。

rpc技術內部原理是通過兩種技術的組合來實現的:本地方法呼叫 和 網路通訊技術。

rpc簡介
在上述本地過程呼叫的例子中,我們是在一台計算機上執行了計算機上的程式,完成呼叫。隨著計算機技術的發展和需求場景的變化,有時就需要從一台計算機上執行另外一台計算機上的程式的需求,因此後來又發展出來了rpc技術。特別是目前隨著網際網路技術的快速迭代和發展,使用者和需求幾乎都是以指數式的方式在高速增長,這個時候絕大多數情況下程式都是部署在多台機器上,就需要在呼叫其他物理機器上的程式的情況。

rpc是remote procedure call protocol三個單詞首字母的縮寫,簡稱為:rpc,翻譯成中文叫遠端過程呼叫協議。所謂遠端過程呼叫,通俗的理解就是可以在本地程式中呼叫執行在另外一台伺服器上的程式的功能方法。這種呼叫的過程跨越了物理伺服器的限制,是在網路中完成的,在呼叫遠端伺服器上程式的過程中,本地程式等待返**用結果,直到遠端程式執行完畢,將結果進行返回到本地,最終完成一次完整的呼叫。

需要強調的是:遠端過程呼叫指的是呼叫遠端伺服器上的程式的方法整個過程。

rpc和rpc/jsonrpc包提供了對rpc的支援

// rpc構建tcp或http協議之上,底層資料編碼使用gob,因為gob編碼為golang定義,所以無法支援跨語言呼叫.

// rpc/jsonrpc構建與tcp協議之上,底層資料編碼使用json,可支援跨語言呼叫

rpc設計組成
rpc技術在架構設計上有四部分組成,分別是:客戶端、客戶端存根、服務端、服務端存根。這裡提到了客戶端服務端的概念,其屬於程式設計架構的一種方式,在現代的計算機軟體程式架構設計上,大方向上分為兩種方向,分別是:b/s架構c/s架構。b/s架構指的是瀏覽器到伺服器互動的架構方式,另外一種是在計算機上安裝乙個單獨的應用,稱之為客戶端,與伺服器互動的模式。

由於在服務的呼叫過程中,有一方是發起呼叫方,另一方是提供服務方。因此,我們把服務發起方稱之為客戶端,把服務提供方稱之為服務端。以下是對rpc的四種角色的解釋和說明:

rpc原理及呼叫步驟
了解完了rpc技術的組成結構我們來看一下具體是如何實現客戶端到服務端的呼叫的。實際上,如果我們想要在網路中的任意兩台計算機上實現遠端呼叫過程,要解決很多問題,比如:

讓我們來看看rpc具體是如何解決這些問題的,rpc具體的呼叫步驟圖如下:

在上述圖中,通過1-10的步驟**的形式,說明了rpc每一步的呼叫過程。具體描述為:

rpc涉及到的相關技術
通過上文一系列的文字描述和講解,我們已經了解了rpc的由來和rpc整個呼叫過程。我們可以看到rpc是一系列操作的集合,其中涉及到很多對資料的操作,以及網路通訊。因此,我們對rpc中涉及到的技術做乙個總結和分析:

我們常見的json,xml等相關框架都可以對資料做序列化和反序列化編譯碼操作。之前protobuf協議,這也是一種資料編譯碼的協議,在rpc框架中使用的更廣泛。

rcp定義和使用

定義rpc

定義rpc結構體和方法

// rpc方法必須要有兩個引數和返回值error, 

// 第乙個引數為請求結構體變數,指用於獲取客戶端提交的引數

// 第二個引數為響應結構體指標變數,用於返回,返回值error用於告知客戶端錯誤資訊

rpcserver
tree rpcserver 

rpcserver

├── data

│   └── data.go

├── go.mod

├── main.go

└── service

└── rpc_client.go

go mod init rpcserver

rpcserver/data/data.go

package data

type calculatorrequest struct

// 定義演算法服務

type calculatorresponse struct

rpcserver/service/rpc_server

package service

import (

"log"

"rpcserver/data"

)// 定義演算法服務

type calculator struct

// 定義+方法

func (c *calculator) add(request *data.calculatorrequest,response *data.calculatorresponse) error

rpcserver/main.go

package main

import (

"log"

"net"

"net/rpc"

"net/rpc/jsonrpc"

"rpcserver/service"

)func main() )

// 註冊服務,指定服務名稱

rpc.registername("calc",&service.calculator{})

lister,err := net.listen("tcp",addr)

if err != nil

defer lister.close()

log.printf("[+] listen on: %s",addr)

for

log.printf("[+] client connected: %s",conn.remoteaddr())

// 使用例程啟動jsonrpc處理客戶端請求

go jsonrpc.serveconn(conn)

}}

rpcclient
tree rpcclient 

rpcclient

├── data

│   └── data.go

├── go.mod

└── main.go

1 directory, 3 files

rpcclient/data/data.go

package data

type calculatorrequest struct

// 定義演算法服務

type calculatorresponse struct

rpcclient/main.go

package main

import (

"fmt"

"log"

"net/rpc/jsonrpc"

"rpcclient/data"

)func main()

defer conn.close()

// 定義請求物件

request := &data.calculatorrequest

// 定義響應物件

response := &data.calculatorresponse{}

// 呼叫遠端方法

//err = conn.call("calculator.add",request,response)

err = conn.call("calc.add",request,response)

// 獲取結果

fmt.println(err,response.result)

}

LRU cache原理及go實現

1.1 概述 快取資源通常比較昂貴,通常資料量較大時,會竟可能從較少的快取滿足盡可能多訪問,這裡有一種假設,通常最近被訪問的資料,那麼它就有可能會被後續繼續訪問,基於這種假設,將所有的資料按訪問時間進行排序,並按驅逐出舊資料,那麼存在快取的資料就為熱點資料,這樣既節省了記憶體資源,又極大的滿足了訪問...

推薦演算法之FFM 原理及實現簡介

推薦系統一般可以分成兩個模組,檢索和排序。比如對於電影推薦,檢索模組會針對使用者生成乙個推薦電影列表,而排序模組則負責對這個電影列表根據使用者的興趣做排序。當把ffm演算法應用到推薦系統中時,具體地是應用在排序模組。ffm演算法,全稱是field aware factorization machin...

STL vector的內部實現原理及基本用法

本文基於stl vector源 但是不考慮分配器allocator,迭代器iterator,異常處理try catch等內容,同時對 ucopy umove ufill 函式也不會過度分析。一 vector的定義 template class vector public vector val ty,...