コース概要:
- RPCプロトコルの基本構成
- RPC プロトコル メッセージのエンコードと実装の詳細
- Dubbo でサポートされる RPC プロトコルと使用法
RPCプロトコルの基本構成
RPCプロトコル用語の説明
一般的な RPC 使用シナリオには、サービス検出、負荷、フォールト トレランス、ネットワーク送信、シリアル化などのコンポーネントが含まれており、RPC プロトコルは、プログラムがネットワーク送信とシリアル化を実行する方法を指定します。言い換えれば、RPC プロトコルの実装は、非透過的なリモート呼び出しの実装と同等です。
契約の基本構成:
- 住所: サービスプロバイダーのアドレス
- ポート: プロトコルは開いているポートを指定します
- メッセージ エンコーディング: プロトコル メッセージ エンコーディング。リクエスト ヘッダーとリクエスト本文の 2 つの部分に分かれています。
- シリアル化メソッド: リクエストボディをオブジェクトにシリアル化します。
- Hessian2連載、
- ダボ連載、
- Javaシリアル化
- Jsonシリアル化
- 実行中のサービス: ネットワーク伝送の実装
- ネットティ
- ミナ
- RMIサービス
- servlet 容器(jetty、Tomcat、Jboss)
Dubbo でサポートされている RPC プロトコルの使用
dubbo がサポートする RPC プロトコルのリスト
名前 | 実装の説明 | 接続の説明 | 該当シーン |
---|---|---|---|
ダボ | 送信サービス: mina、netty (デフォルト)、grizzy シリアル化: hessian2 (デフォルト)、java、fastjson カスタム メッセージ | 単一の長い接続 NIO 非同期送信 | 1. 通常の RPC 呼び出し 2. 転送されるデータの量が少ない 3. プロバイダーはコンシューマーより小さい |
rmi | トランスポート: Java RMI サービスのシリアル化: Java ネイティブ バイナリのシリアル化 | 複数のショートコネクションBIOの同期送信 | 1. 通常の RPC 呼び出し 2. 元の RMI クライアントとの統合 3. 少量のファイルを転送可能 4. ファイアウォールを通過しない |
ヘシアン語 | トランスポート サービス: サーブレット コンテナー シリアル化: ヘシアン バイナリ シリアル化 | Http プロトコル送信に基づいて、遅延サーブレット コンテナ構成に従って | 1. 消費者よりもプロバイダーの方が多い 2. 大きなフィールドやファイルを送信できる |
http | トランスポート サービス: サーブレット コンテナのシリアル化: Java ネイティブ バイナリのシリアル化 | 遅延サーブレットコンテナの設定に応じて | 1. 混合パケットサイズ |
倹約 | thrift RPC と統合し、それに基づいてパケット ヘッダーを変更します | 長時間接続、NIO 非同期送信 |
RMI がファイアウォールの侵入をサポートしていないことについての補足:
原因在于RMI 底层实现中会有两个端口,一个是固定的用于服务发现的注册端口,另外会生成一个***随机***端口用于网络传输。因为这个随机端口就不能在防火墙中提前设置开放开。所以存在*防火墙穿透问题*
プロトコルの使用法と構成:
Dubbo フレームワーク構成プロトコルは非常に便利で、ユーザーはプロバイダー アプリケーションで*<* dubbo:protocol>要素を構成するだけで済みます。
<!--
name: 协议名称 dubbo|rmi|hessian|http|
host:本机IP可不填,则系统自动获取
port:端口、填-1表示系统自动选择
server:运行服务 mina|netty|grizzy|servlet|jetty
serialization:序列化方式 hessian2|java|compactedjava|fastjson
详细配置参见dubbo 官网 dubbo.io
-->
<dubbo:protocol name="dubbo" host="192.168.0.11" port="20880" server="netty"
serialization=“hessian2” charset=“UTF-8” />
#TODO は、他のプロトコルを使用して Dubbo を構成する方法を示します。
- dubbo プロトコルはシリアル化に json を使用します (ソース コードを参照: com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol*)*
- RMI プロトコルを採用 (ソースコードを参照: com.alibaba.dubbo.rpc.protocol.rmi.RmiProtocol)
- Http プロトコルを採用 (ソースコードを参照: com.alibaba.dubbo.rpc.protocol.http.HttpProtocol.InternalHandler)
- Heason プロトコルを採用します (ソース コードを参照: com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol.HessianHandler)。
新しいPrintWriter(System.out)
netstat -aon|findstr "17732"
シリアル化:
特徴 | |
---|---|
ファストジェソン | テキストタイプ: サイズが大きい、パフォーマンスが遅い、言語をまたがる、可読性が高い |
ファースト | バイナリ型: サイズが小さく、JDK ネイティブ シリアル化と互換性があります。JDK 1.7 のサポートが必要です。 |
ヘシアン2 | バイナリ型: クロスランゲージ、高いフォールトトレランス、小さいサイズ |
ジャワ | バイナリ型:ネイティブJAVAベースでNull書き込み可能 |
圧縮されたJava | バイナリ型: Java と同様、コンテンツは圧縮されます。 |
ネイティブJava | バイナリ型: ネイティブ Java シリアル化 |
クライオ | バイナリ型: ボリュームは hessian2 より小さいですが、耐障害性は hessian2 ほど良くありません。 |
ヘッセ行列化:
- パラメータと戻り値は Serializable インターフェイスを実装する必要があります
- パラメータと戻り値は、List、Map、Number、Date、Calendar などのインターフェイスを実装するようにカスタマイズできません。hessian が特別な処理を行うため、JDK によってのみ実装できます。また、属性値もカスタム実装クラスの内容は失われます。
- ヘッセ行列化、メソッドや静的変数ではなく、メンバーの属性値と値の型のみを渡します。互換性[1] [2] :
データ通信 | 状態 | 結果 |
---|---|---|
A->B | クラス A には属性が 1 つ多い (またはクラス B には属性が 1 つ少ない) | 例外はスローされません。属性の値は A に多くありますが、B にはありません。その他は正常です。 |
A->B | 列挙 A には 1 つ多い列挙があり (または B には 1 つ少ない列挙があり)、A は送信に追加の列挙を使用します。 | 例外をスローする |
A->B | 列挙型 A には 1 つ多い列挙型 (または B には 1 つ少ない列挙型) があり、A は送信に追加の列挙型を使用しません。 | 例外はスローされず、B は正常にデータを受け取ります |
A->B | A と B は同じプロパティ名を持ちますが、タイプが異なります | 例外をスローする |
A->B | シリアルIDが同じではありません | 通常の送信 |
インターフェイスに追加されたメソッドはクライアントに影響を与えません。メソッドがクライアントに必要ない場合、クライアントは再デプロイする必要はありません。入力パラメータおよび結果セットに属性を追加しても、クライアントには影響しません。クライアントが新しい属性を必要としない場合は、再デプロイする必要はありません。
入力パラメータや結果セットの属性名の変更はクライアントのシリアル化には影響しませんが、クライアントが再デプロイされていない場合、入力、出力に関わらず、属性名が変更された属性値は取得できません。
概要: サーバー側とクライアント側はドメイン オブジェクトと完全に一致している必要はありませんが、最大一致の原則に従います。
3. RPCプロトコルメッセージのエンコードと実装の詳細説明
RPC トランスポートの実装:
RPC プロトコルの送信は TCP/IP に基づいており、Socket または Netty、mina、およびその他のネットワーク プログラミング コンポーネントを使用します。しかし、TCP はバイトストリーム指向のボーダレスプロトコルであるため、データ伝送のみを担当し、各リクエストに対応するメッセージを区別しないため、TCP プロトコル伝送においてパケットのアンパックやスティッキングが発生するという問題があります。
開梱して貼り付ける理由:
tcp はデータを流れるように送信し、送信の最小単位はセグメントであることがわかります。TCP ヘッダーにはオプション フラグがあり、共通フラグは mss (最大セグメント サイズ) であり、接続層によって毎回送信されるデータには MTU (最大送信単位) の最大制限があり、通常は 1500 ビットであることを意味します。複数のメッセージ セグメントに分割された mss は、最大制限から TCP ヘッダーを差し引いたもので、送信されるデータのサイズ (通常は 1460 ビット) です。バイトに換算すると180バイト以上になります。
TCP のパフォーマンスを向上させるために、送信側は送信するデータをバッファに送信し、バッファがいっぱいになるのを待ってから、バッファ内のデータを受信側に送信します。受信機も同様に、データを受信するためのバッファなどの機構を備えています。すると、次のようなことが起こります。
- アプリケーションによって書き込まれたデータが MSS サイズより大きいため、解凍が発生します。
- アプリケーションによって書き込まれるデータが MSS サイズより小さい場合、スティッキー パケットが発生します。
- 受信メソッドがソケット バッファ データを時間内に読み取らないため、スティッキー パケットが発生します。
開梱および貼り付けの解決策:
- 固定長のメッセージを設定すると、サーバーは毎回所定の長さの内容を完全なメッセージとして読み取ります。
- {“タイプ”:“メッセージ”,“コンテンツ”:“こんにちは”}\n
- メッセージ ヘッダーのあるプロトコルを使用すると、メッセージ ヘッダーにはメッセージ開始識別子とメッセージ長の情報が格納されます。サーバーはメッセージ ヘッダーを取得すると、メッセージ長を解析して、長さの内容を逆方向に読み取ります。
**例: **HTTP プロトコル ヘッダーの Content-Length は、メッセージ本文のサイズを示します。
(注①:httpメッセージのエンコーディング)
Dubbo プロトコルのメッセージ エンコーディング:
注② Dubbo プロトコルのメッセージエンコーディング:
- magic : Java バイトコード ファイルのマジック ナンバーと同様に、ダボ プロトコルのデータ パケットであるかどうかを判断するために使用されます。マジックナンバーは定数 0xdabb で、メッセージの始まりを判断するために使用されます。
- flag : フラグ ビット、合計 8 つのアドレス ビット。下位 4 ビットは、メッセージ本文のデータに使用されるシリアル化ツールの種類 (デフォルトのヘシアン) を示すために使用され、上位 4 ビットのうち、最初のビットは要求リクエストを意味する 1、2 番目のビットは 1 になります。これは双方向送信 (つまり、応答が返される) を意味し、3 番目のビットは 1 で、ハートビート ping イベントであることを示します。
- status : ステータスビット、リクエスト応答ステータスの設定、ダボはいくつかの応答タイプを定義します。特定のタイプについては、com.alibaba.dubbo.remoting.exchange.Response を参照してください。
- 呼び出し ID:メッセージ ID、ロングタイプ。各リクエストの一意の識別ID(非同期通信を使用しているため、リクエストリクエストと返されたレスポンスの対応付けに使用されます)
- body length:メッセージ本文の長さ (int 型)。つまり、Body Content に何バイトが記録されるか。
*(注:相关源码参见 **c**om.alibaba.dubbo.rpc.protocol.dubbo.DubboCodec**)*
Dubbo プロトコルのエンコードとデコードのプロセス:
Dubbo プロトコルのエンコードとデコードの実装プロセス (ソース コードは **dubbo2.5.8 から取得)
1、DubboCodec.encodeRequestData() 116L // 编码request
2、DecodeableRpcInvocation.decode() 89L // 解码request
3、DubboCodec.encodeResponseData() 184L // 编码response
4、DecodeableRpcResult.decode() 73L // 解码response