誤って実装されたRPC

誤って実装されたRPC
序文
誤って実装されたRPC

最近、cimプロジェクトに注目する人が増えるにつれ、質問やバグの件数も増えており、問題を解決する過程でコードのクリーンさが再び現れることは避けられません。

1、2年前に書いたものを見ると、本当に自分の手から来たのではないかといつも思っています。いくつかの場所で、私はそれを助けることができず、再建への長い道のりを始めました。

比較の前後に、
開始する前にcimプロジェクトを簡単に紹介します。以下はそのアーキテクチャ図です。

誤って実装されたRPC

簡単に言えば、これはIMインスタントメッセージングシステムであり、主に次の部分で構成されています。

  • IMサーバーは当然サーバーであり、クライアントとの長い接続を維持するために使用されます。

  • IMクライアントクライアントは、QQと同様のクライアントツールと見なすことができます。もちろん、機能はそれほど豊富ではなく、いくつかの単純なメッセージ送受信機能しか提供しません。

  • 主にクライアント認証、メッセージ転送などに使用されるルートルーティングサービス。システムステータス、オンライン人数、およびその他の機能を表示するために使用できるいくつかのhttpインターフェイスを提供します。

もちろん、サーバーとルーティングの両方を水平方向に拡張できます。

誤って実装されたRPC

これはメッセージ送信のフローチャートです。2つのサーバーAとB、およびルーティングサービスが展開されていると仮定します。その中で、ClientAとClientBは、それぞれサーバーAとBとの長い接続を維持します。

ClientAがHelloWorldをClientBに送信すると、メッセージフロー全体が次の図に示されます。

  1. まず、http経由でルートサービスにメッセージを送信します。

  2. ルーティングサービスは、ClientBがServerBに接続されていることを認識し、http経由でServerBにメッセージを送信します。

  3. 最後に、ServerBはClientBとの長い接続チャネルを介してメッセージをプッシュし、メッセージは正常に送信されます。

ここで、ClientAがRouteへのリクエストを開始するためのコードをインターセプトしました。

誤って実装されたRPC

これは、okhttpを使用してhttpリクエストを開始することであることがわかります。この関数は実装できますが、エレガントではありません。

例:Alipayのインターフェースに接続する必要がある場合、ここでhttpリクエストを送信することは当然問題ありませんが、Alipayの内部部門が相互のインターフェースを直接呼び出す場合は、元のhttpリクエストを使用しないでください。

サービスプロバイダーはapiパッケージを提供する必要があり、サービスコンシューマーは、インターフェイス呼び出しを実装するためにこのパッケージに依存するだけで済みます。

もちろん、最終的にはhttpまたはカスタムプライベートプロトコルを使用できます。

また、DubboまたはSpringCloudを使用する場合と同様に、通常はapiパッケージに直接依存するため、ローカルメソッドの呼び出しなどのリモートサービスを呼び出し、httpまたは他のプライベートプロトコルを使用しているかどうかに関係なく、基になる詳細を完全に保護できます。それは問題ではありません、それは発信者にはまったく関係ありません。

それは内面的な趣味がありますか?これはRPCの公式の説明ではありませんか?

これに対応するのも同じ理由です。クライアント、ルート、サーバーは基本的にシステムであり、相互のインターフェイス呼び出しにRPCを使用するのが妥当です。

したがって、私のリファクタリングは次のようになりました。

誤って実装されたRPC

ローカルメソッドを呼び出すのと同じように、コードははるかに簡潔であり、これにはいくつかの利点もあります。

  • 基礎となる詳細は完全に保護されており、ビジネスをより適切に実現し、コードを維持できます。

  • サービスプロバイダーがパラメーターを変更した場合でも、コンパイル中にすぐに検出される可能性があり、呼び出しは以前と同様に完全に認識されないため、リスクも増大します。


、それがどのように実装されるかについての話をしましょう。

実際、上記の「動的エージェントの実用化」で述べたように、原理は似ています。

呼び出し元を認識したくない場合は、インターフェイスプロキシオブジェクトを作成する必要があります。このプロキシオブジェクトには、エンコード、呼び出し、およびデコードのプロセスが実装されています。

誤って実装されたRPC

ここに対応するのは、実際にはrouteApiプロキシオブジェクトを作成することです。重要なのは次のコードです。


RouteApi
 routeApi 
=

new

ProxyManager
<>(
RouteApi
.
class
,
 routeUrl
,
 okHttpClient
).
getInstance
();

完全なソースコードは次のとおりです。
誤って実装されたRPC

getInstance()関数は、プロキシする必要のあるインターフェイスオブジェクトを返します。ProxyInvocationは、InvocationHandlerインターフェイスを実装するクラスです。この一連のコードは、JDKを使用して動的プロキシを実装するための3つのアプローチです。

誤って実装されたRPC

ProxyInvocationのソースコードを表示すると、プロキシインターフェイスの任意のメソッドを呼び出すと、ここでのinvoke()メソッドが実行されることがわかります。

invoke()メソッドは、上図で説明したエンコード、リモート呼び出し、デコードのプロセスを自然に実装します。この説明の焦点では​​ないため、あまり紹介しませんので、誰もが理解しやすいと思います。

まとめ
実際、これらを理解することで、DubboなどのRPCフレームワークのコアソースコードを理解しやすくなります。プライベートプロトコルが使用されることを除いて、全体的な考え方は似ているため、エンコードとデコードが異なります。

したがって、RPCフレームワークを自分で実装する場合は、このアイデアを参照して試してみることをお勧めします。独自のコードでRPC helloworldを実行すると、DubboやSpringCloudなどのサードパーティフレームワークを自分で統合したように感じられます。全く違います。

この記事のすべてのソースコード:

https://github.com/crossoverJie/cim

おすすめ

転載: blog.51cto.com/15049794/2562746