はじめに
Rabbit.Rpc http://www.cnblogs.com/ants/p/5605754.html
も、最初にサービス インターフェイスを定義し、次にサーバーがそれを 2 つのコピーを作成します。インターフェイスを継承することによるクライアントの具体的なロジックは、インターフェイス内のすべてのメソッド、メソッドのパラメーター、およびリフレクションによる戻り値の情報を抽出し、コードを動的に生成してプロキシ クラスを生成し、それを動的にコンパイルすることです。そして容器に入れます。 生成されたプロキシ クラスに関しては、すべてのメソッドが統一された実装を持ちます。つまり、Invoke メソッドを呼び出してメソッドとパラメーターを最下層に送信し、最下層のアセンブリがサーバーに送信されます。ここでコードを生成する方法はもっと楽しく、学ぶことができます。さらに、このフレームワークはサービス ガバナンスも統合しており、サービスは Zookeeper に登録され、クライアントは Zookeeper を通じて特定のサービス アドレスを取得して呼び出すことができます。 実際、現時点では、これは単なるサービス フレームワークではなく、サービス ガバナンス機能も含まれています。
私はコードをざっと読んだだけなので、詳細を完全には理解していません。詳しく知りたい場合は、ソースコードを読んでください。
Dyd.BaseService.ServiceCenter http://git.oschina.net/chejiangyi/Dyd.BaseService.ServiceCenter
基本的な機能はすべて揃っていますが、このプロジェクトについての著者の紹介がこのプロジェクトについてです研究目的のため、サービスを呼び出すクライアントもコードを通じて生成されます。詳細については、コードを参照してください。
さらに、このブロガーをさらに紹介しましょう。彼はブログパーク http://www.cnblogs.com/chejiangyi/ にもブログを持っており、その下にいくつかのオープンソース プロジェクトをオープンしています http://git.oschina .net /chejiangyi は、スケジュール サービス、構成サービス、監視サービスなどの非常に優れたプロジェクトであり、ある程度の規模のインターネット企業にとって、これらのサービスは .Net に基づいているため、より価値があります。これは、.Net 開発を使用する一部のインターネット企業にとって、優れた参考資料となるためです。
Redola.Rpc http://www.cnblogs.com/gaochundong/p/redola_yet_another_csharp_rpc_framework.html
これは私が最近発見したもので、フレームワークはActorモデルを使用し、シリアル化はprotobuf-netを使用し、送信方法はベースです。 tcp では、tcp フレームワークは独自の Cowboy.WebSockets を使用します。ただし、Actor モデルが理解できないため、ここでは詳しく説明しません。興味のある方は読んでください。著者のブログ。
私が自分で書いたサービスフレームワーク
たくさんのサービスフレームワークを読んだ後、私も自分で一つ書きました。これは単なるサービス呼び出しであり、本質的には参考として使用できます。
フレームワークの原理は Hession と似ています。最初にインターフェイスを定義し、その後サーバーがインターフェイスを実装します。ここでは、Web API のコントローラーにインターフェイスを直接継承させることにしました。リクエストをインターセプトするハンドルを明確に定義する必要がありますが、Web API アクセスには影響しないため、このフレームワークを使用しても、http を使用して直接アクセスできなくなります。クライアントの呼び出し方法も Hession と同様で、プロキシを定義してからパラメータを収集する必要があります
インターフェースの次のステップは Web API を使用します。コントローラーを定義します。このコントローラーでは、APIController を継承するだけでなく、インターフェースの固有のロジックも実装されます。
同時に、このインターフェイスが配置されている dll をクライアントにコピーします。 ここでは、.Net に付属するプロキシ クラスであり、Hession で使用されるメカニズムでもある RealProxy という関数を紹介します。
using System; using System.Linq; using System.Reflection; using System.Runtime.Remoting.Messaging; using System.Runtime.Remoting.Proxies; using Newtonsoft.Json; using RestSharp; namespace SimleRPC { public class SimpleProxy : RealProxy { private readonly Uri _uri; public SimpleProxy(Type type, Uri uri) : base(type) { this._uri = uri; } public override IMessage Invoke(IMessage msg) { //msg参数包含调用方法的信息,这里通过封装,使信息更丰富一些 IMethodCallMessage methodMessage = new MethodCallMessageWrapper((IMethodCallMessage)msg); MethodInfo methodInfo = (MethodInfo)methodMessage.MethodBase; ParameterInfo[] paramsInfo = methodInfo.GetParameters(); //获取方法调用参数 //拼装path 类名即controller名, 方法名即action名 这样就表示出具体的url string path = "/api/" + methodInfo.DeclaringType.Name + "/" + methodInfo.Name; //请求类型,post or get bool isHttpGet = methodInfo.CustomAttributes.Any(customAttributeData => customAttributeData.AttributeType.Name == "HttpGetAttribute"); var client = new RestClient(_uri); var request = new RestRequest(path, isHttpGet ? Method.GET : Method.POST); //构建参数 //web api对于传参的一切规则 参考 http://www.cnblogs.com/babycool/p/3922738.html http://www.cnblogs.com/landeanfen/p/5337072.html 两篇博客 if (isHttpGet) { //这里默认get请求的参数都是基本类型 for (int i = 0; i < paramsInfo.Length; i++) { request.AddParameter(paramsInfo[i].Name, methodMessage.Args[i]); } } else { //对于post请求,要么没有参数(当然基本没有这种情况),要么只有一个参数(这些是受web api的限制) if (paramsInfo.Length > 0) { request.AddJsonBody(methodMessage.Args[0]); } } // 发送请求 拿到结果 IRestResponse response = client.Execute(request); var content = response.Content; Type returnType = methodInfo.ReturnType; //获取调用方法返回类型,根据类型反序列化结果 object returnValue; if (IsBaseType(returnType)) { returnValue = Convert.ChangeType(content, returnType); } else { returnValue = JsonConvert.DeserializeObject(content, returnType); //如果是一个对象,则用json进行反序列化 } return new ReturnMessage(returnValue, methodMessage.Args, methodMessage.ArgCount, methodMessage.LogicalCallContext, methodMessage); } /// <summary> /// 判断是否是基础类型(int long double), string 是引用类型,但是也归到基础类型里面 /// </summary> /// <param name="type"></param> /// <returns></returns> private static bool IsBaseType(Type type) { if (type == typeof(string) || type.IsPrimitive) return true; return false; } } }
すべてのメソッド呼び出しは Invoke メソッドを呼び出します。Invoke メソッドでは、パラメーター、戻り値の型など、呼び出しメソッドの特定の情報を取得できます。 次に、リフレクションとアセンブリを通じて、HTTP リクエストが形成されます。ここで、デフォルトのインターフェイス クラス名はコントローラーの名前であり、インターフェイス メソッド名はアクションの名前です。
最後に、RestSharp を通じてリクエストを送信します。 最後に、http の結果がメソッドの戻り値に必要な値に逆シリアル化されます。実際、サーバーにとって、Web API がインターフェースを継承するかどうかは問題ではありません。継承しない場合、インターフェースの署名は Web API のメソッドの署名と一致する必要があります。
この方法は、私が書いたデモを通じて調整できます。これに興味がある人は、さらにいくつかの状況をテストできます。ついに
現在、多くのインターネット企業が独自の RPC フレームワークを持っていますが、その中にはオープンソースのものもあれば、歴史的な問題により独自に作成されたものもあります。通信方法には、HTTP ベースのもの、TCP ベースのもの、および 2 つあります。両方のプロトコルと互換性があります。 シリアル化の方法もいろいろありますが、ここでは 5 つだけ挙げました。実際、github で検索すると、優れた RPC がたくさんあります。
RPC は、プロジェクト開発プロセスの一段階にすぎません。 RPC を使用すると、これに基づいて次のような多くのことを実行できます。
サービス ガバナンス すべてのサービスは、開始時にサービス センターに登録されます。登録センターでは、Nginx などのプロキシを経由せずに直接呼び出して、実際のアドレスを取得する際に、どのクライアントを使用できるか、どのクライアントを使用できるかなどのいくつかの許可制限を設定できます。ここでダボを参照できます。
HTTP リクエスト パス マイクロサービスは現在、非常に人気があります。フロントエンド リクエストは、http ヘッダーに RequestId と RequestIndex を追加して、これらのサービスを結び付けることができます。 B ->C の場合、サービス A がサービス B を呼び出すときに、http ヘッドに RequestId がないことが判明すると、GuId を通じて RequestId を生成でき、RequestIndex が 1 増加します。サービス B がサービス C を呼び出すとき、次の理由により、 RequestId はすでに存在します。直接渡されます。次に、RequestIndex を 1 ずつ増やして、この情報をログに記録します。分析を通じて、呼び出し全体が結合され、サービス全体の呼び出しリンク図が作成されます。完全データで描画可能です。
リンク図に加えて、各サービス呼び出しをインターセプトできるため、リンク図を使用すると、サービス全体の情報がより完全になります。
上記は .NET でのいくつかのサービス フレームワークの紹介です。さらに関連する内容については、PHP 中国語 Web サイト (m.sbmmt.com) に注目してください。