序文
最近、cimプロジェクトに注目する人が増えるにつれ、質問やバグの件数も増えており、問題を解決する過程でコードのクリーンさが再び現れることは避けられません。
1、2年前に書いたものを見ると、本当に自分の手から来たのではないかといつも思っています。いくつかの場所で、私はそれを助けることができず、再建への長い道のりを始めました。
比較の前後に、
開始する前にcimプロジェクトを簡単に紹介します。以下はそのアーキテクチャ図です。
簡単に言えば、これはIMインスタントメッセージングシステムであり、主に次の部分で構成されています。
-
IMサーバーは当然サーバーであり、クライアントとの長い接続を維持するために使用されます。
-
IMクライアントクライアントは、QQと同様のクライアントツールと見なすことができます。もちろん、機能はそれほど豊富ではなく、いくつかの単純なメッセージ送受信機能しか提供しません。
- 主にクライアント認証、メッセージ転送などに使用されるルートルーティングサービス。システムステータス、オンライン人数、およびその他の機能を表示するために使用できるいくつかのhttpインターフェイスを提供します。
もちろん、サーバーとルーティングの両方を水平方向に拡張できます。
これはメッセージ送信のフローチャートです。2つのサーバーAとB、およびルーティングサービスが展開されていると仮定します。その中で、ClientAとClientBは、それぞれサーバーAとBとの長い接続を維持します。
ClientAがHelloWorldをClientBに送信すると、メッセージフロー全体が次の図に示されます。
-
まず、http経由でルートサービスにメッセージを送信します。
-
ルーティングサービスは、ClientBがServerBに接続されていることを認識し、http経由でServerBにメッセージを送信します。
- 最後に、ServerBはClientBとの長い接続チャネルを介してメッセージをプッシュし、メッセージは正常に送信されます。
ここで、ClientAがRouteへのリクエストを開始するためのコードをインターセプトしました。
これは、okhttpを使用してhttpリクエストを開始することであることがわかります。この関数は実装できますが、エレガントではありません。
例:Alipayのインターフェースに接続する必要がある場合、ここでhttpリクエストを送信することは当然問題ありませんが、Alipayの内部部門が相互のインターフェースを直接呼び出す場合は、元のhttpリクエストを使用しないでください。
サービスプロバイダーはapiパッケージを提供する必要があり、サービスコンシューマーは、インターフェイス呼び出しを実装するためにこのパッケージに依存するだけで済みます。
もちろん、最終的にはhttpまたはカスタムプライベートプロトコルを使用できます。
また、DubboまたはSpringCloudを使用する場合と同様に、通常はapiパッケージに直接依存するため、ローカルメソッドの呼び出しなどのリモートサービスを呼び出し、httpまたは他のプライベートプロトコルを使用しているかどうかに関係なく、基になる詳細を完全に保護できます。それは問題ではありません、それは発信者にはまったく関係ありません。
それは内面的な趣味がありますか?これはRPCの公式の説明ではありませんか?
これに対応するのも同じ理由です。クライアント、ルート、サーバーは基本的にシステムであり、相互のインターフェイス呼び出しにRPCを使用するのが妥当です。
したがって、私のリファクタリングは次のようになりました。
ローカルメソッドを呼び出すのと同じように、コードははるかに簡潔であり、これにはいくつかの利点もあります。
-
基礎となる詳細は完全に保護されており、ビジネスをより適切に実現し、コードを維持できます。
- サービスプロバイダーがパラメーターを変更した場合でも、コンパイル中にすぐに検出される可能性があり、呼び出しは以前と同様に完全に認識されないため、リスクも増大します。
今
、それがどのように実装されるかについての話をしましょう。
実際、上記の「動的エージェントの実用化」で述べたように、原理は似ています。
呼び出し元を認識したくない場合は、インターフェイスプロキシオブジェクトを作成する必要があります。このプロキシオブジェクトには、エンコード、呼び出し、およびデコードのプロセスが実装されています。
ここに対応するのは、実際にはrouteApiプロキシオブジェクトを作成することです。重要なのは次のコードです。
RouteApi
routeApi
=
new
ProxyManager
<>(
RouteApi
.
class
,
routeUrl
,
okHttpClient
).
getInstance
();
完全なソースコードは次のとおりです。
getInstance()関数は、プロキシする必要のあるインターフェイスオブジェクトを返します。ProxyInvocationは、InvocationHandlerインターフェイスを実装するクラスです。この一連のコードは、JDKを使用して動的プロキシを実装するための3つのアプローチです。
ProxyInvocationのソースコードを表示すると、プロキシインターフェイスの任意のメソッドを呼び出すと、ここでのinvoke()メソッドが実行されることがわかります。
invoke()メソッドは、上図で説明したエンコード、リモート呼び出し、デコードのプロセスを自然に実装します。この説明の焦点ではないため、あまり紹介しませんので、誰もが理解しやすいと思います。
まとめ
実際、これらを理解することで、DubboなどのRPCフレームワークのコアソースコードを理解しやすくなります。プライベートプロトコルが使用されることを除いて、全体的な考え方は似ているため、エンコードとデコードが異なります。
したがって、RPCフレームワークを自分で実装する場合は、このアイデアを参照して試してみることをお勧めします。独自のコードでRPC helloworldを実行すると、DubboやSpringCloudなどのサードパーティフレームワークを自分で統合したように感じられます。全く違います。
この記事のすべてのソースコード: