RPCテクノロジーの内部原理は、ローカルメソッド呼び出しとネットワーク通信テクノロジーという 2つのテクノロジーの組み合わせによって実現されます。
RPCの概要
RPCは、リモートプロシージャコールプロトコルの頭字語で、略してRPCと呼ばれ、中国語のリモートプロシージャコールプロトコルと呼ばれます。いわゆるリモートプロシージャコールと呼ばれる一般的な理解では、ローカルプログラム内の別のサーバーで実行されているプログラムの関数メソッドを呼び出すことができます。この呼び出しプロセスは、物理サーバーの制限を超え、ネットワークで行われます。リモートサーバーでプログラムを呼び出している間、ローカルプログラムは、リモートプログラムが実行されて結果をローカルに返すまで、呼び出し結果を返すのを待ちます。 、そして最後に完全な呼び出しを完了します。
リモートプロシージャコールは、リモートサーバー上のプログラムを呼び出すプロセス全体を指す ことを強調しておく必要があります。
RPCデザイン構成
RPCテクノロジは、アーキテクチャ設計の4つの部分、つまりクライアント、クライアントスタブ、サーバー、サーバースタブで構成されています。
クライアント:サービスコールの開始者。サービスコンシューマとも呼ばれます。
クライアントスタブ(Client Stub):このプログラムは、クライアントが配置されているコンピューターマシンで実行され、主に呼び出されるサーバーのアドレスを格納するために使用されます。さらに、プログラムは、リモートサーバープログラムを要求するクライアントのデータ情報をパッケージ化する役割も果たします。データパケットは、ネットワークを介してサーバースタブプログラムに送信されます。次に、サーバースタブプログラムによって送信された呼び出し結果データパケットを受信し、解析してクライアントに戻す必要もあります。
サーバー:リモートコンピューターマシン上で実行されるプログラム。クライアントによって呼び出されるメソッドがあります。
サーバースタブ(Server Stub):クライアントスタブプログラムによって送信された要求メッセージデータパケットをネットワーク経由で受信し、サーバーの実際のプログラム関数メソッドを呼び出して関数呼び出しを完了します。次に、サーバーがデータ処理パッケージを実行して送信します。クライアントへのスタブプログラム。
RPCの原則と呼び出し手順
上の図では、RPCの各ステップの呼び出しプロセスが、ステップ1〜10に示されているステップの形式で示されています。具体的な説明は次のとおりです。
1.クライアントは、ローカルクライアントスタブプログラムを呼び出すことによって使用される関数メソッド名を最初に呼び出すことによって、リモートプロシージャコールを開始したい。
2.クライアントスタブプログラムは、クライアントの関数呼び出し要求を受け取り、メソッド名、パラメーター、およびクライアント要求によって運ばれるその他の情報をシリアル化し、データパッケージにパッケージ化します。
3.クライアントスタブは、リモートサーバープログラムのIPアドレスを見つけ、ソケット通信プロトコルを呼び出し、それをネットワーク経由でサーバーに送信します。
4.サーバーのスタブプログラムは、クライアントから送信されたデータパケット情報を受信し、合意されたプロトコルを介してデータを逆シリアル化して、要求されたメソッド名と要求パラメーターを取得します。
5.サーバースタブプログラムは、関連データを準備し、ローカルサーバーの対応する関数メソッドを呼び出し、ビジネス処理のために対応するパラメーターを渡します。
6.サーバープログラムが既存のビジネスロジックに従って呼び出しプロセスを実行し、ビジネスの実行が完了すると、実行結果がサーバースタブプログラムに返されます。
7.サーバースタブプログラムは、合意されたプロトコルに従ってプログラム呼び出しの結果をシリアル化し、ネットワークを介してクライアントスタブプログラムに送り返します。
8.クライアントスタブプログラムは、サーバースタブから送信された戻りデータを受信し、データを逆シリアル化して、呼び出しによって返されたデータをクライアント要求イニシエーターに渡します。
9.クライアントはイニシエーターに呼び出し結果の取得を要求し、RPC呼び出しプロセス全体が終了します。
RPCに関連する関連技術
1. ダイナミックプロキシテクノロジー:上記のクライアントスタブプログラムとサーバースタブプログラムはすべて、特定のコーディングおよび開発作業中にダイナミックプロキシテクノロジーを使用して自動的に生成されるプログラムです。
2. シリアライゼーションとデシリアライゼーション:RPC呼び出し中に、データをあるマシンから別のマシンに転送する必要があることがわかります。インターネットでは、すべてのデータはバイトの形式で送信されます。プログラミングのプロセスでは、データオブジェクトを使用することが多いため、ネットワーク上でデータオブジェクトと関連する変数を転送する場合は、データオブジェクトをシリアル化および逆シリアル化する必要があります。
シリアライゼーションの:処理対象と称されるオブジェクトの配列を変換、すなわち符号化処理のバイトのシーケンスです。
逆シリアル化:バイトシーケンスをオブジェクトに復元するプロセスは、オブジェクトの逆シリアル化と呼ばれます。これは、デコードのプロセスです。
RPC公式ライブラリ
Go言語の公式Webサイトのpkgの説明では、公式にサポートされているrpcパッケージが提供されており、具体的なリンクは次のとおりです:https : //golang.org/pkg/net/rpc/。公式のrpcパッケージの完全なパッケージ名は、net / rpcです。公式説明によると、rpcパッケージは主にネットワークを介してオブジェクトにアクセスする機能を提供します。
net / rpcライブラリはRPC呼び出しプログラミングを実装しています
1.サービスの定義と公開
プログラミングのプロセスでは、サーバーは構造オブジェクトを登録し、そのオブジェクトが属するメソッドを介して呼び出し側に公開する必要があります。これにより、サービスが提供されます。このメソッドは出力メソッドと呼ばれ、この出力メソッドはリモートで呼び出すことができます。もちろん、出力メソッドを定義するとき、リモートで呼び出すことができるメソッドは、特定の規則に従う必要があります。コードで説明します。
func(t * T)MethodName(request T1、response * T2)エラー
上記のコードは、go言語の担当者によって提供される公開されたサービスメソッドの定義標準であり、いくつかの主要なルールが含まれています。
1.外部露出のメソッドは2つのパラメーターのみを持つことができ、これらの2つのパラメーターは、出力タイプまたは組み込みタイプのいずれかになります。
2.メソッドの2番目のパラメーターはポインター型でなければなりません。
3.メソッドの戻りタイプはエラーです。
4.メソッドのタイプはエクスポート可能です。
5.メソッド自体もエクスポート可能です。
タイプMathUtil struct { } func(this * MathUtil)CalculateCircleArea(req float32、resp * float32)error { * resp = math.Pi * req * req return nil }
2.登録サービスと監視リクエスト
1 //初期化ポインタデータタイプ
mathUtil:=新新(MathUtil)
// 2、コールネットは/ RPCパケットサービス関数オブジェクトが登録
ERR:= rpc.Register(mathUtil)
!ERR = nilの{IFを
パニック(ERR。エラー())
}
// 3.この関数を使用して、mathUtilで提供されるサービスをHTTPプロトコルに登録し、呼び出し元がhttpを使用してデータを転送できるようにします
rpc.HandleHTTP()
// 4.特定のポートでリッスンします
listen、err:= net.Listen( "tcp"、 ":8081")
if err!= nil {
panic(err.Error())
}
go http.Serve(listen、nil)
第三に、クライアントが呼び出します
サーバーはHttpポートモニタリング方式による接続を待機しているため、クライアントはhttp経由で接続し、最初にサーバーに接続する必要があります。
client、err:= rpc.DialHTTP(" tcp "、" localhost:8081 " ) if err!= nil { panic(err.Error()) } var req float32 req = 3 var resp * float32 err = client.Call(" MathUtil.CalculateCircleArea "、req、* resp) if err!= nil { panic(err.Error()) } fmt.Println( * resp)
上記の呼び出しメソッドの中核は、client.Callメソッドの呼び出しにあります。このメソッドには3つのパラメーターがあります。最初のパラメーターは、呼び出されるリモートサービスのメソッド名を示します。2番目のパラメーターは、呼び出し時に渡されるパラメーターです。3番目のパラメーターはパラメータは、呼び出しによって受信される戻り値です。
上記の呼び出し方法は同期呼び出しで実装されていますが、非同期に呼び出す方法もあります。コードを非同期的に呼び出す
var respSync * float32 // 非同期呼び出し syncCall: = client.Go(" MathUtil.CalculateCircleArea "、req、&respSync、nil) replayDone: = < -syncCall.Done fmt.Println(replayDone) fmt.Println( * respSync )
マルチパラメーター要求呼び出しパラメーターの受け渡し
新しい構造でパラメーターを定義し、それらをparamパッケージに格納します。
タイプAddParma struct { Args1 float32 // 最初のパラメーター Args2 float32 // 2番目のパラメーター }
server.goファイルに、2つの数値を追加する関数を実装し、サービス登録のロジックを実装します。
func(mu * MathUtil)Add(param param.AddParma、resp * float32)error { * resp = param.Args1 + param.Args2 // 2つの数値を加算する関数を実現 nilを返す } mathUtil: = new(MathUtil) err: = rpc.RegisterName(" MathUtil " 、mathUtil) if err!= nil { panic(err.Error()) } rpc.HandleHTTP() listen、err: = net.Listen(" tcp "、" :8082 " ) http .Serve(listen、nil)
RPCをProtobufと組み合わせて使用する
要件:システムに注文モジュール(Order)があり、他のモジュールがRPCのリモートエンジニアリング呼び出しを実装したいとします。注文情報は、注文IDとタイムスタンプに従って取得できます。取得が成功した場合、対応する注文情報が返され、クエリが失敗情報を返せなかった場合。次に、要件をプログラムしてみましょう。
送信データフォーマット定義
データ定義
要件に従って、次のように定義されているmessage.protoファイルを定義します。
syntax = " proto3 " ; パッケージメッセージ; // 注文リクエストパラメータ メッセージOrderRequest { string orderId = 1 ; int64 timeStamp = 2 ; } // 注文情報 メッセージOrderInfo { string OrderId = 1 ; string OrderName = 2 ; string OrderStatus = 3 ; }
protoファイルをコンパイルする
protoコンパイルコマンドを使用して.protoファイルをコンパイルし、対応する構造のGo言語ファイルを自動的に生成します。コンパイルコマンドは次のとおりです。
protoc ./message.proto --go_out =。/
RPCと組み合わせたProtobufg形式のデータ
サービスの定義:
RPCリモートプロシージャコールを行い、リモートサーバーを呼び出すメソッドを実装するには、最初にサービスが必要です。この場合、OrderServiceという注文クエリ関数を提供するサービスを定義し、リモート呼び出し用の注文情報クエリメソッドを提供します。詳細なサービスとメソッドは次のように定義されています。
タイプOrderService struct { } func(this * OrderService)GetOrderInfo(request message.OrderRequest、response * message.OrderInfo)error { orderMap: = map [string] message.OrderInfo { " 201907300001 ":message.OrderInfo {OrderId:" 201907300001 "、OrderName:" 衣服"、OrderStatus:" 既に付款" }、 " 201907310001 ":message.OrderInfo {OrderId:" 201907310001 "、OrderName:" 零食"、注文状況:" 有料" }、 " 201 907 310 002 ":{message.OrderInfo OrderIdで:" 201 907 310 002 "、ORDERNAME:" 食品"、オーダーステータス:" 未払い" }、 } 電流: = 。Time.now()UNIX() IF(要求.TimeStamp> current){ * response = message.OrderInfo {OrderId:" 0 "、OrderName:""、OrderStatus:" 注文情報が異常です"} } else { 結果:= orderMap [request.OrderId] if result.OrderId!= "" { * response = orderMap [request.OrderId] } else { return errors.New(" server error " ) } } return nil }
サービスのメソッド定義では、orderMapを使用して初期注文データベースをシミュレートし、ケースのクエリと表示を容易にします。GetOrderInfoメソッドには2つのパラメーターがあり、1つ目は呼び出し元から渡されたパラメーターとしてのmessage.OrderRequest、2つ目は呼び出しによって返されたパラメーターとしてのmessage.OrderInfoです。ここで2つのパラメーターを介して上記を渡します。定義され、自動生成されたGo言語構造データが結合されます。
サービスの登録と処理
サービスを定義したら、RPCフレームワークにサービスを登録し、HTTPリクエストの監視プロセスを有効にする必要があります。コードのこの部分は、以前のRPCサーバー実装ロジックと一致しており、具体的な実装は次のとおりです。
func main(){ orderService: = new(OrderService) rpc.Register(orderService) rpc.HandleHTTP() listen、err: = net.Listen(" tcp "、" :8081 " ) if err!= nil { panic(err .Error()) } http.Serve(listen、nil) }
RPCクライアント呼び出しの実装
クライアントでは、クライアントが通常リモートサーバーにアクセスするロジックに加えて、クライアントが渡す必要のある要求データmessage.OrderInfoも準備する必要があります。具体的な実装は次のとおりです。
func main(){ client、err: = rpc.DialHTTP(" tcp "、" localhost:8081 " ) if err!= nil { panic(err.Error()) } timeStamp: = time.Now()。Unix( ) request: = message.OrderRequest {OrderId:" 201907300001 " 、TimeStamp:timeStamp} var response * message.OrderInfo err = client.Call(" OrderService.GetOrderInfo "、request、&response) if err!=nil { panic(err.Error()) } fmt.Println( * response) }
運用実績