中心的な役割をサイン
オープニングは、最初の問題について考えてみたい、ダボは永遠に再生することができます何のレジストリはありませんか?
もちろん、後にだけ、サービスプロバイダのアドレス情報は、消費者が設定を呼び出すことができることを知っています。唯一のいくつかのサービスであれば、何ら問題は遊んでいないもちろんそう。各サービスの構成情報を書面で要求されている場合でも、すべての生産サービスは数十万人を回し、どのように多くの問題を想像してみてください。
上記の問題は言葉の問題ではない場合ダウン実行中のサービスプロバイダは、消費者がどのようにやっている場合まあ、想像?消費者は知らなかったので、それは、サービスプロバイダに送信された要求に進み、その後、失敗していきます。唯一の方法は、この時間は、サービスアドレス情報を変更し、サービスを再起動することです。
非常に面倒になります発見を見つけるために何のレジストリ、分散環境のサービスが存在しない場合は、私たちが見ることができ、手動で自動化を完了することができ、すべてを、設定する必要があります。そこでここでは、サービス・プロバイダーと消費者との間の関係を調整するために第三者を必要とする、これはレジストリです。
レジストリの主な役割は以下の通り:
- 動的消費者へのあなたの露出のダイナミックな中心地を登録することで、サービスプロバイダへの参加、消費者が個別に設定ファイルを更新する必要はありません。
- 動的な発見サービスは、消費者が動的に有効にするために再起動することなく、新しいサービスを発見することができます。
- 各サービスにローカル設定の結果を回避するための統一された構成は、矛盾しています。
- 動的調整、動的な調整支援レジストリパラメータ、新しいパラメータが自動的に関連付けられているすべてのサービスノードを更新します。
- 統一された管理は、一元管理構成サービスノードすることができ、レジストリデータに依存しています。
レジストリのワークフロー
レジストリ全体的なワークフローは、比較的簡単なフローチャートである次のとおりです。
メインの作業プロセスは、以下のステップに分けることができます。
- サービスプロバイダを開始した後、サービスがレジストリに登録されます。
- 消費者の後にコールバック関数を残したまま、現在利用可能な全てのサービスを取得するように、レジストリのサブスクリプションサービスプロバイダを開始するためのイニシアチブをとります。
- サービスプロバイダが追加またはオフラインにする場合は、レジストリは、コールバック第2工程を登録することで、お客様に通知します。
- ダボ管理者(サービス管理センター)は、コンソールでの提供と消費者はすべてのサービスを管理できるように、サービスプロバイダや消費者にサブスクライブします。
ダボ以前のバージョンは、主に、登録センターとしてのZooKeeper、Redisのに使用すること、およびダボの更新されたバージョンと、現在登録中心としてナコス、領事、etcdなどをサポートします。
ダボ登録センターコアソース
PS:次のソースベースのダボ2.7.3バージョン
注册中心实现使用模板模式,源码位于 dubbo-registry 模块,类关系如下图:
最上层的 RegistryService
接口定义了核心方法,分别为注册,取消注册,订阅,取消订阅以及查询。
中间层抽象类主要实现通用逻辑,如:AbstractRegistry
实现缓存机制,FailbackRegistry
实现失败重试功能。
底层 ZookeeperRegistry
等为具体实现类,实现与 ZooKeeper 等注册中心交互的逻辑。
接下去我们具体分析 AbstractRegistry
与 FailbackRegistry
逻辑。
AbstractRegistry
缓存实现的原理
如果每次服务调用都需要调用注册中心实时查询可用服务列表,不但会让注册中心承受巨大的流量压力,还会产生额外的网络请求,导致系统性能下降。
其次注册中心需要非强依赖,其宕机不能影响正常的服务调用。
基于以上几点,注册中心模块在 AbstractRegistry
类中实现通用的缓存机制。这里的缓存可以分为两类,内存服务缓存以及磁盘文件缓存。
内存服务缓存
内存服务缓存很好理解也最容易实现,AbstractRegistry
使用一个 ConcurrentMap
保存相关信息。
private final ConcurrentMap<URL, Map<String, List<URL>>> notified = new ConcurrentHashMap<>();
这个集合中 key 为消费者的 URL,而 value 为一个 Map 集合。这个内层 Map 集合使用服务目录作为 key,分别为 providers,routers,configurators,consumers 四类,value 则是对应服务列表集合。
磁盘文件缓存
由于服务重启就会导致内存缓存消失,所以额外增加磁盘文件缓存。
文件缓存默认位置位于 ${user.home}/.dubbo/
文件夹,文件名为dubbo-registry-${application.name}-${register_address}.cache
。可以设置 dubbo.registry.file
配置信息从而修改默认配置,实现源码如下:
String filename = url.getParameter(Constants.FILE_KEY, System.getProperty("user.home") + "/.dubbo/dubbo-registry-" + url.getParameter(Constants.APPLICATION_KEY) + "-" + url.getAddress() + ".cache");
ps: ${application.name} 取自
dubbo.application.name
信息,${register_address} 取值注册中心地址信息。缓存文件完整名称为:C:\Users\xxx/.dubbo/dubbo-registry-dubbo-auto-configure-consumer-sample-127.0.0.1:2181.cache
缓存文件内容使用 properties
配置文件格式,即 key=value
格式。key为服务接口名称,value 为服务列表,由于服务可能存在多个,将会使用空格分隔。
缓存文件的加载
dubbo 程序初始化的时候,AbstractRegistry
构造函数将会从本地磁盘文件中将数据读取到 Properties
对象实例中,后续都将会先写入 Properties
,最后再将里面信息再写入文件。
缓存初始化的源码为下图。
缓存文件的保存与更新
缓存文件将会通过 AbstractRegistry#notify
方法保存或更新。客户端第一次订阅服务获取的全量数据,或者后续回调中获取到新数据,都将会调用 AbstractRegistry#notify
方法,用来更新内存缓存以及文件缓存。
notify
方法源码如下图:
在保存文件缓存方法中,首先把根据 URL 取出的数据,拼接成字符串,然后写入上面提到过的 properties
对象中,最后输出到文件中。
这里可以选择两种保存方式,同步或异步。由于 notify
可能被多次调用,为了提高系统能,系统默认使用异步方式保存。
saveProperties
方法源码如下:
doSaveProperties
方法最终将会将信息写入缓存。考虑到保存方法可能会被多个线程同时调用,这里使用 CAS 方法,首先比较版本大小,若小于,代表有新线程正在写入信息,本次更新直接丢弃。
其次考虑到多个 dubbo 应用可能共用一份缓存文件,所以这里使用文件排他锁当做分布式锁,防止多个应用并发操作同一份文件。
一旦文件写入异常或者获取锁失败,保存操作将会不断重试,直到超过最大次数。
ps: dubbo 2.7.2 之前重试没有设置最大次数,如果文件没有权限保存,保存将会一直失败,异步线程将会陷入死循环。
doSaveProperties
方法源码如下:
FailbackRegistry
重试机制
FailbackRegistry
継承AbstractRegistry
達成するためにregister
、subscribe
そのような慣習法、および増加としてdoRegister
、doSubscribe
そのためのテンプレートメソッドは、実装するサブクラスを参照しました。
場合はdoRegister
、テンプレートメソッドの例外が発生するようなことは、それがコレクションにタスクを失敗した後、定期的に再びテンプレートメソッドを呼び出します。
FailbackRegistry
エラー発生時の再試行設定されています。
ではsubscribe
方法、例えば、ここでは、これら呼ぶdoSubscribe
テンプレートメソッドを。例外がある場合、キャッシュファイルの内容を読み、[サービスをロードします。最後に、新しいタスクは、これらのタスクに非同期セット、再試行タイマーのタイミングを再試行するように追加されます。
FailbackRegistry#subscribe
メソッド出典:
ではaddFailedSubscribed
新しくスケジュールされたタスクになり、その後、タイマーの実行に引き渡さ。再試行のタイミングタスクデフォルトの最大数は3で、デフォルトの5秒の間隔を呼びます。
addFailedSubscribed
ソースは以下のとおりです。
その他の再試行失敗したタスクは、すべてから継承された、比較的類似しておりAbstractRetryTask
、次の図に、親クラスクラス関係を。
概要
本論文では、登録、ワークフロー、一般的なキャッシュメカニズムと失敗時の再試行メカニズムの中心的な役割を説明します。あなたはモードを学ぶことができ、そこからテンプレート、およびマルチスレッドスキル。
次は、ZooKeeperのレジストリ原則についてお話しますので、ご期待に起因レジストリとして、現在の主な使用のZooKeeperに、特定の実装に関連した登録センターでは、ありません。
ヘルプブック
「Apacheのダボ深い理解と実用的。」