ダボのソースコードを手に取って読んでください(1)サービスの公開

 

この記事は主にダボの公式文書を読むことについてです:http//dubbo.apache.org/zh-cn/docs/user/quick-start.htmlサービスの公開と見積もりに関して、私は多くの詳細があまり明確ではないと感じています。手元のプロジェクトから始めて、実装を段階的に検討し、このプロセスで学んだ他の知識を記録することにしました。dubboは非常に成熟したフレームワークであるため、多くのテクノロジーが使用され、多くの定義が含まれています。クラスとインターフェースは非常に複雑なので、段階的に分析するのに時間がかかる可能性があり、周辺の知識もたくさんあります。関連する拡張知識へのリンクを記事に記載しました。クローンを作成することをお勧めします。ソースコードを読んでください。ダボのバージョン番号は2.6.2です。

1.ダボの設定から始めます:

ここでは主に春のカスタムラベル機能が使用されます。春のカスタム構成については、https//www.cnblogs.com/mahuan2/p/7213866.htmlの記事を確認しください

ここでは、主にdubbo名前空間を定義してから、対応するxsdドキュメントを書き込みます。dubboxsdドキュメントは、jarパッケージのMETA-INF /dubbo.xsdにあります。

次に、dubbo.xsdでは、主にサービスタグと参照タグに焦点を当てています。

次に、タグ処理クラスdubboの定義がMETA-INF /spring.handlersに記述されます。

dubboタグの分析では、主にDubboNamespaceHandlerクラスが使用されていることがわかります。次に、DubboNamespaceHandlerクラスのソースコードを開きます。

dubboが上記のタグを解析するためにDubboBeanDefinitionParserクラスをカスタマイズし、ServiceBeanとReferenceBeanをカスタマイズしたことがわかります。次に、DubboBeanDefinitionParserクラスを開きます。

ここでは主に解析メソッドに焦点を当てます。このメソッドには多くのロジックがあり、あまり明確に読んでいませんでしたが、一般的な意味は、xml内のすべての構成の基本情報を取得し、それを次のように定義することです。春のBeanDefinition。BeanDefinitionについて、読者はこの記事を読むことができます:https//blog.csdn.net/windrui/article/details/52973915これは大まかにSpringBeanを抽象化したものであり、主にクラス名、スコープ、属性、コンストラクターパラメーターリスト、依存Bean、シングルトンクラスかどうか、レイジーロードかどうかなどを保存します。実際には、このBeanDefinition内のBeanの定義情報対応する属性では、Beanに対する後続の操作はBeanDefinitionで直接実行されます。たとえば、BeanDefinitionを取得した後、リフレクションを使用して、クラス名、コンストラクター、およびに基づいてオブジェクトを作成できます。内部のコンストラクターパラメーター。

ここで私はそれらの1つにもっと興味があります。それはサービスのrefパラメーターです。

ここでは、インターフェースがインスタンス化可能なクラスにマップされており、実行時のBeanの名前であるため、ref解決の実装を確認しました。解決には主に2つのタイプがあります。

(1)refではなくclass属性を記述します:

この段落の意味は、クラスタグが使用されている場合、springは対応するクラスのBeanDefinitionを生成し、実行時にBeanを表すBeanDefinitionHolderを作成し、Beanの名前はid + Implであるということです。

(2)クラスではなくrefを記述します。

参照がある場合は、作成時にBeanとしてRuntimeBeanReferenceを使用します。

このように、元のインターフェースは、インスタンス化されたときに別のBeanになることができ、このBeanはiocのBean作成チェーンにも存在します。

refとclassの両方が記述されている場合、refのコードが後ろにあるため、refが優先されます。haha^ _ ^

上記は、dubboがxmlからspringとして定義されたBeanDefinitionを読み取る方法です。次に、Beanがインスタンス化されたときにサービスがどのように公開されるかを見てみましょう。

 

2.serviceBeanはいつサービスを公開しますか

 

ServiceBeanがApplicationListener <ContextRefreshedEvent>、ApplicationContextAware、およびInitializingBeanインターフェースを実装していることがわかります。これらの3つのインターフェースは、春が始まるさまざまな時間に順番に呼び出されます。これらは2-> 1-> 3の順序で呼び出されます。

次に、ServiceBeanの3つのインターフェースを見てみましょう。

言うまでもなく、いくつかの変数を初期化します

基本的に、いくつかの変数は初期化されます。これが1つの方法です:

BeanFactoryUtils.beansOfTypeInclusiveAncestorsの場合、一般的な関数は、上記のproviderConfigMapなど、このコンテキストで指定されたクラスのすべてのBeanを取得することであり、着信パラメーターはProviderConfig.classです。

次に、最終的なメソッドのエクスポートに焦点を当てます。

その後、このserviceBeanによって実装された3番目のインターフェースが最終的に実行され、それほど多くはありません。実際には、exportを呼び出すことでもあります。前のメソッドが実行されないようにするためと推定されます!

次に、このエクスポートに注意します。このエクスポート方法は、ローカルサービスを外部呼び出しプロセスに公開し、Springコンテナが初期化されたときにすべてのserivceBeanがサービスに公開されるようにすることです。次に、エクスポートが行ったことを見てみましょう。

 

3. serviceBeanはサービスを何に公開しますか?

エクスポートのソースコードを見てみましょう。

これは主に、サービスが開かれたかどうか、後で開く必要があるかどうかを判断します。実際のロジックはdoExportにあります。doExportのコードを見てみましょう。

言うまでもなく、モニターはモニタリングセンターの構成、レジストリはレジストリの構成、プロトコルはパブリッシャーの構成です。当面はどうすればよいかわかりません。当分の間、これらはcheckDefaultで初期化されます。このクラスを開いて確認してください

主にホスト、ポート、環境パスなどの情報であり、これらの情報はシステム変数から取得されます。checkDefaultで確認できます。

次に、システム変数に接頭辞dubbo。が付いているすべての変数が取得されます。dubboの各サービスが実行されると、これらのパラメーターが自動的に設定されます(おそらく)。さらに、このクラスを初期化するためのテストユニットがあり、理解しやすいです。

次に、doExportに戻ります。

 

これがClass.forNameのレビューです。特定のコンテンツはhttps://www.cnblogs.com/xingzc/p/5760166.htmlを参照できます。主なものは、インターフェイスクラスをロードすることです。

checkInterfaceAndMethodsは、interfaceClassを空にすることはできず、インターフェイスタイプである必要があり、検証メソッドが存在する必要があることを確認します。

checkRef check refを空にすることはできず、インターフェイスインターフェイスを実装する必要があります。特定のコードを自分で読み取る必要があります。

次に、checkApplicationは後でアプリケーション変数を初期化します

checkRegistryはレジストリ変数を初期化します

checkProtocolはプロトコル変数を初期化します

appendPropertiesメソッドについては前述しました

checkStubAndMockメソッドが何をするのかわかりません。無視してください

主にdoExportUrlsメソッドを見てください

次にloadRegistries

この方法では、applicationおよびregistryconfigのパラメーターを使用して、レジストリ変数の各アドレスを、www.xxx.com?key1 = value1&key2 = value2などの標準形式のパラメーターを使用してregistryUrl(最後に生成されたURLではない)にスペルします。次に、これらのURLのリストを返します。これは、サービスによって生成されたURLの例です。

 

RegistryUrl:

Registry://172.23.2.101:2181 / com.alibaba.dubbo.registry.RegistryService?application = oic-dubbo-provider&dubbo = 2.6.1&logger = slf4j&pid = 15258&register = true&registry = zookeeper&timestamp = 1528958780785

 

 

次に、protocols変数をトラバースし、URLに従ってプロトコルリスト内の各プロトコル(主にdoExportUrlsFor1Protocolメソッド)を公開します。

次に、このメソッドの初期段階で、一連のパラメーターがマップに詰め込まれ、最終的には、いくつかのモジュール、プロバイダー、およびいくつかの独自のパラメーターがに追加されたことを除いて、上記で生成されたregistryUrlと同様でした。より長いURLを形成します。以下は、上記のサービスによって生成された完全なURLです。

dubbo://10.8.0.28:12000 / com.tyyd.oic.service.PushMessageService?accepts = 1000&anyhost = true&application = oic-dubbo-provider&bind.ip = 10.8.0.28&bind.port = 12000&buffer = 8192&charset = UTF-8&default.service .filter = dubboCallDetailFilter&dubbo = 2.6.1&generic = false&interface = com.tyyd.oic.service.PushMessageService&iothreads = 9&logger = slf4j&methods = deletePushMessage、getPushMessage、batchPushMessage、addPushMessage、updatePushMessage、qryPushMessage&payload = 8388608&pid = 8388608& = provider&threadpool = fixed&threads = 100&timeout = 6000&timestamp = 15289594541&version = 1.0.0

上記のように、URLアドレスには、バージョン番号、インターフェース名、メソッドリスト、シリアル化メソッド、有効期限など、このインターフェースBeanが使用する必要のあるすべてのコンテキスト情報が含まれ、アドレスヘッダーもレジストリから変更されます。ダボに。このURLにはすべてのコンテキスト情報が含まれているため、後でコードを見るとわかるように、このURLは非常に便利です。

このパートの後、いくつかの拡張機能がURLに追加され、URLやその他の情報が監視されます。詳細については詳しく説明しませんが、主に呼び出し元に変換してエクスポーターを作成する段階について説明します。

この場合、proxyFactory変数がどのように生成されるかについてもっと興味があります。公式ドキュメントによると、これはjavassistProxyFactoryまたはJdkProxyFactoryのいずれかです。もちろん、ここに重要なポイントがあります。これは動的プロキシです。動的プロキシの知識については、こちらをご覧ください:https://www.cnblogs.com/gonjan-blog/p/6685611.html

その場合、javassistProxyFactoryとJdkProxyFactoryはどちらも動的プロキシ生成テクノロジですが、一方はバイトコードで生成され、もう一方はjdkで生成されます。

次に、このproxyFactory変数の生成が表示されます。

 

次に、オンラインで確認しました。SPIと呼ばれる非常に強力なテクノロジーがあることがわかりました。関連する手順については、以下を参照してください。

https://blog.csdn.net/qiangcai/article/details/77750541

ほぼ同じインターフェイスで、異なる実装クラスが存在する可能性があります。これらのクラスは、構成によってのみ動的に変更でき、取得された実装は引き続きシングルトンモードです。

特定のダボ記事の説明も説明されています、あなたは見ることができます

proxyFactoryインターフェースはSPIタグを書き込んでいるため、ここではデフォルトでjavassistProxyFactoryが使用されます。

 

次に、javassistProxyFactoryの実装で記述されている内容を確認します。

ここでラッパーが生成されます。このラッパーはバイトコードを介して生成されます。これは、渡されたプロキシ実装クラスをさらに抽象化したものである可能性があります。対応する実装クラスのメソッドは、メソッド名、パラメーターなどに従って呼び出すことができます。詳細については、この記事を読むことができます:

https://blog.csdn.net/synpore/article/details/79148260

次に、ラッパーはInvokerにカプセル化され、URLは主にInvokerに配置されます。

次に、前に戻り、生成されたインボーカーを使用して、DelegateProviderMetaDataInvokerにカプセル化します。このクラスはインボーカーと大差ありませんが、このserviceBeanの情報は後で使用するために追加されます。

 

次に、portocolを使用してexportメソッドを呼び出し、portocolがどこから来ているかを見てみましょう。

これはもう1つのおなじみのSPIテクノロジーです。PortocolインターフェースのSPIラベルを見てみましょう。

ラベルはdubboです。DubboPortocolクラスを開くために私を使用してください

次に、上記のURLを取得するためのいくつかのパラメーター、または上記の例があります。ブレークポイントに表示される値は次のとおりです。

どうやって取るのかわかりません。openServerメソッドを見てみましょう。

ここで直接フォローアップし、特定の値を確認してから、createServerに移動します

それほど多くはありませんが、私は主にExchangers.bind(url、requestHandler)に焦点を当てています。

それから私たちはずっと続いて見つけました

生成されるデフォルトのExchangerはheaderExchangerです。もう一度HeaderExchangerを見てみましょう。

HeaderExchangerのパラメーターはTransporters.bindパラメーターです。引き続きフォローアップします。

次に、getTransporterメソッドは次のように続行します。

古いルーチン、Transporterインターフェースを見てみましょう

それがnettyTransporterであることを確認して、次の手順を続行します。

この時点で、ようやくおなじみのNettyServerが表示されます。NettyServerクラスを見てみましょう。

このメソッドは、親クラスAbstractServerのコンストラクターとChannelHandlers.wrapメソッドを使用します。最初にこのメソッドを見てみましょう。

ChannelHandlersがシングルトンモードであることがわかります。ここでも、SPIを使用してDispatcherクラスを作成しています。

 

AllDispatcher.NAMEはallの値であり、AllDispatcherクラスを開きます

AllChannelHandlerをもう一度見てください

スーパーペアレント

スレッドプールを定義し、SPIがfixThreadPoolを作成したので、私はそれを見ませんでした(最終的に基本的なjdkクラスを見つけました)

次に、fixThreadPoolに関するこの記事を読むことができます:https://blog.csdn.net/czd3355/article/details/52608567

 

データストアもあります:

これはおおよそConcurrentMapとConcurrentMapのクラスです。こちらをご覧ください

 

nettyServerの親クラスAbstractServerの構築メソッドに戻る

それでも以前のサービスであり、URLのパラメーターが使用されていることがわかります。したがって、すべてのダボサービスのコンテキストは、基本的に生成されたURLにあります。ここでは主にdoOpenメソッドを見ていきます

次に、基本的にjdk自体に関連するものがあり、最後にnetty関連のパッケージを見ました。

ここで、dubboはNamedThreadFactoryをカプセル化し(dubboも多くのファクトリパターンを使用していることがわかりました)、このクラスを開きます

このクラスがクラス名のプレフィックスとスレッドグループをカスタマイズしているのを見ると、将来自分で使用できる優れたファクトリクラスのように感じます。

その後、nettyの使用は後で行われます。さらに、dubboはデフォルトで比較的古いnetty3を使用します。使用法の概要:

https://www.cnblogs.com/java-zhao/p/7625557.html 次に、nettyの詳細な説明については、https://blog.csdn.net/haoyuyang/article/details/53231585を参照してください。

Nettyは同期および非ブロッキング、ブロッキング非ブロッキングはアプリケーション用、同期および非同期はオペレーティングシステム用です。

次に、ここにnettyコーデックを実装しました。Dubboは独自のクラスを多数カプセル化しています。実際、ワイヤーを剥がすのは非常に簡単です。この記事を参照してください:https//www.cnblogs.com/ll409546297 / p /8036954.html

次に、ダボエンコーディングのシリアル化の効率の分析についてこの記事を見ることができます:https//blog.csdn.net/moonpure/article/details/53175519

特定のソースコードについては詳しく説明しません。デフォルトのシリアル化プロトコルはhessian2です。

 

それでは、前に戻って、これまで歩いた後に何をしたかを考えてみてください。

サービスタグ付きのサービスBeanに対して生成されたプロキシグッドインボーカーです。このインボーカーはexporterというオブジェクトの下に配置され、次にエクスポーターはserviceBeanのエクスポーター変数の下に配置されて呼び出される準備が整います。作成されたnettyServerは次のようになります。 serviceBeanの変数プロトコルの下で変数serverMapに配置され、そのようなserverBean nettyサービスのメソッドプロキシクラスが生成されますか?ここで、プロトコルはシングルトンによって生成されるため、BeanがnettyServerを開いた場合、他のBeanは再度開かれないことに注意してください。

次に、直前のServiceConfigのdoExportに戻ります。

彼は生成されたserviceBeanをApplicationModelに入れ、後で消費者もそれを入れたことがわかりました。なぜそれが使用されたのか正確にはわかりません。

これは、サービスの公開のプロセスです。簡単ではない...

おすすめ

転載: blog.csdn.net/qq_33762302/article/details/114983188