アイデアのクラスター
登録サービス
そして、サービス
ディスカバリーサービス
ロードバランシング戦略
登録サービス
登録サービスを実現するために、最初にすべての私たちは(私たちは飼育係の主流・レジストリーとして選択します)登録センターを持っている必要があり、私たちはそれぞれネッティーサービスを開始するときに、IPアドレスやポート番号など、いくつかのローカル・サービス情報をバー。飼育係にサインアップしてください。
コードは次のように実装されています。
CF2 CuratorFramework;公共ボイドレジスタ(nodeNameの文字列、文字列IP)は例外{スロー ;文字列のパス= ZK_CLUSTER_PATH + "/" +たnodeName 。スタットSTAT = cf.checkExists()forPath(パス); IF(STAT == NULL){/を/親ノードが親ノードを作成するために存在しない場合 cf.create()creatingParentsIfNeeded()withMode(CreateMode.PERSISTENT).forPath(パス); ... } のSystem.out.println( "マシンのIPへのアクセス:" + IP) ; //対応する一時ノード作成 cf.createを()withMode(CreateMode.EPHEMERAL).forPath(パス+ "/" + IP、ip.getBytes());. }
ここでは、表示されるはずです、私たちの場所は、キーである我々は、我々は短命ノードであり、ノードは一時的なノードで作成することを確認することができ、対応するノードのIPを作成することです。
一時的なノードとは何ですか?
サービス開始後の一時的なノードを作成し、サービスを一時的に遮断ノードが存在しません。
なぜ一時的なノードを使うのか?
思考の通常の方法は、登録の時間がかかるかもしれない、私たちは通常のノードを登録し、その後、組立ラインオフサービス内のノードを削除したが、その後の欠点があるでしょうZK好きです。
例えば、一時的なノードを削除することができない私たちのサービスのポンプは、そのノードは、間違ったクライアントたちに利用できるようになります。
また、我々はまた、あなたが永続的なノードクラスを作成した後に削除された問題を検討し、問題がより複雑になりますので、我々は一時的なノードを使用しています。
そして、サービス
[OK]を私たちは私たちの登録サービス上記のプロセスを知っているし、我々はクライアントに提供すること登録されたサービスを必要としています。
実際には、ここでの重要な問題は、サービスが利用可能かを知る方法です。
2つの方法があります。
ZKすべての問い合わせに行きます
ローカルキャッシュのリスト
ここでは、最初のネットワークを呼び出すたびに、効率を行くための最初の方法について話とは考えられない、低すぎます。だから我々は最初の方法で、一瞬考えたことがあり、私の組立ラインオフサービス、またはライン上の新しいサービスは、どのように私がなければ、ここに私たちの次のステップを導入する:サービス検出我々が使用し、サービス発見メカニズムをローカルキャッシュを更新するには、このような場合は、私たちは地元でのサービスのリストに拾うたびに、ネットワークのオーバーヘッドを大幅に節約します。
ディスカバリーサービス
私たちは、上記の言った服务的列表变更去更新本地的缓存
鍵は、我々はそれを達成しようとしている方法です。
友人はすべてを知っている必要がありZK学び、ZKの通知になり変化したノードは、時計機構ZKはノードのために待機しているがあります。
私たちは、それが私たちのサービスの発見で、オンラインとオフラインの通知を提供するZK見るためにこれを使用しています。
コードは次のように実装されています。
CuratorFramework CF;公共ボイドは(文字列購読ノード名)例外{//スロー特定のサービスに加入 最終列パス= ZK_CLUSTER_PATH + "/" +ノード名; 。スタットSTAT = cf.checkExists()forPath(パス); IF(STAT == NULL){//親ノードが親ノードを作成するために存在しない場合 )cf.createを(creatingParentsIfNeeded()withMode(CreateMode.PERSISTENT).forPath(パス); ... } PathChildrenCache =キャッシュ新しい新しいPathChildrenCache(CF2、パス、真の) ; //初期化時にキャッシュモニタに cache.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT); cache.getListenable() .addListener((CuratorFrameworkクライアント、PathChildrenCacheEventイベント) - > {//子ノードを取得 リストの<string> = client.getChildren子供()forPath(パス);. //ソート突然ノードの Collections.sort(子供); //子ノードの再キャッシュされ data.put(nodeNameの、子供); }); }
ロードバランシング戦略
私たちは、登録と発見サービスの問題を解決した後、我々は実際にそれを設定し、クライアントサービスに提供し、[OK]、、、私たちは選択を確認する必要があり、この時間は、クライアントを可能にするためにも、例えば(当社のサーバーに接続することができ、 100台のクライアント、サーバー2台、それぞれ50を割り当てます)があり、我々は必要负载均衡
な戦略を。
ここでは、要求ごとにIPクライアントを割り当てるには、ポーリング方法を使用します。以下を達成するために特定のコード:
パブリッククラスRoundRobinLoadBalance {パブリック静的最終的な文字列名=「ラウンドロビン」。プライベート静的最終のAtomicInteger系列=新しいのAtomicInteger(); 公共の静的な文字列のdoSelect(一覧<文字列> callList){//取模轮循 ()callList.isEmptyを返しますか?ヌル: callList.get(sequences.getAndIncrement()%callList.size())。 } }
テスト結果の下で
私たちは、クラスタ全体の構築を完了した、と我々は何我々の結果を測定するためのテストプログラムを書きます。
完全なテストコードは次のとおりです。
パブリック静的リスト<文字列>のDataList =新しいArrayListを<>(); 静的{ dataList.add( "19.21.2.1")。 dataList.add( "12.34.33.12"); dataList.add( "21.1.235.22")。 dataList.add( "6.12.36.233"); dataList.add( "71.12.36.233")。 } / ** *飼育係情報 * / パブリック静的な無効メイン(文字列[]引数)が例外をスロー{ 文字列ZK_ADDRESS = "127.0.0.1:2181"。 文字列のノード=「IM」。 文字列のパス= "/ zk_cluster / IM"。//接続はZKする CuratorFrameworkクライアント= CuratorFrameworkFactory.newClient(ZK_ADDRESSを、新しいRetryNTimes(10、5000)); client.start(); 一覧<文字列> = client.getChildren子供()forPath(パス);. Children.isEmptyアサート(); //テスト ZkList zkList =新新ZkList(クライアント); //最初のサブスクリプション zkList.subscribe(ノード); //追加ノード dataList.stream()のforEach(IP - > {{試し。 zkList.register(ノード、IP); }キャッチ(例外E){ e.printStackTrace(); } }); //統計マップを初期化します各ノードの検出の数が割り当てられる のConcurrentHashMapの地図<のAtomicIntegerの文字列>地図を新しい新しい= <>(); dataList.stream()のforEach(IP - > {{試み。 のAtomicIntegerのmap.putIfAbsent(IP、新しい新しい(0))。 }キャッチ(例外e){ e.printStackTrace(); } })。//マップ のために(; iは20000 <; I = 0 int型私は++){ 文字列のノード= zkList.selectNode(ノード)。 map.get(ノード).incrementAndGet(); }の(のMap.Entry <文字列のAtomicInteger> M:map.entrySet()){ System.out.printlnは(String.Formatの( "[%のS]一共被执行了:%sの次"、m.getKey() 。、m.getValue()を取得())); } }
私たちは、の効果を見て
[12.34.33.12]は完全に行われる:4000 [21.1.235.22】完全に行われる:4000 [6.12.36.233]完全に行われる:4000 [19.21.2.1]が完全に行われる:4000 [71.12を.36.233]完全に実施される:4000回
我々は、ノードオンラインとオフラインの外観をシミュレートするために、我々のテストプログラムについて変更し、次のように私たちは、特定のコードを、それを変更するには、クエリノード部分に行ってみましょう:
以下のために(INT i = 0; iは<20001; I ++){IF(Iの== 10000){ zkList.unRegister(ノード、dataList.get(0))。 }であれば(私の== 15000){ zkList.register(ノード、dataList.get(0))。 } 文字列ノード= zkList.selectNode(ノード)。 map.get(ノード).incrementAndGet(); System.out.println(ノード)。 }
次のように実際の結果は以下のとおりです。
[12.34.33.12]完全に行われる:4285回 【21.1.235.22】完全に行われる:4284回 【6.12.36.233]完全に行われる:4284回 2863回:[19.21.2.1]は、合計実行される [71.12を.36.233]完全に実施される:4285回
[OK]を、我々は関係なく、サービスラインまたはオフラインのあまり配信サービスには影響しません、私たちの基本的な要求が均等に各ノードに分散されて見ることができます。
注意
私たちは、一時的なノードにサインアップして行く、私たちの現在の論理に従って、それを行うサービス登録時の上に見ることができる
私がハングアップしたときに、このサービスは、私は即座に、一時的に切断され、対応するノードのZK一般的なセッションを再起動する場合は、デフォルトそして、その後、私はこの時点では、現在の一時的なノードを登録するには行きました、それが原因でノードが存在する作成されません、そして、私は再試行するには、この裁判官の前に3回は、それを上に再起動するように私のサービスを終了し、3回のリトライ判断があるでしょうしばらくして、元のノードZKのテストが完了し、サービスは、それがノード、私はもう一度再起動する、または適切な成功を登録していないことができない限り、と言うことですその後、ノードを削除し、ハングアップすることを発見されました。
道
Iノードが存在するかどうかを決定するために登録されたときに存在しない場合、通常の登録は、元のノードを削除して再登録が存在します。
しかし、そうする気持ちは、ある意味、同時の場合には、それが他の新たな問題を生じることが
第二の方法
我々は戦略を提供することができます。この時間は、ときに、2つのサービスの登録に失敗しました:
最初のサービスは、ユーザがサービスが正常に登録されていないことを知らせ、例外がスローされ登録できませんでしたです。
第二の方法は、もう一度試して、それはあまりにも少しの時間であれば、登録が失敗した後に再登録しようとし続け、一定回数後の障害やその他の政策の選択のための時間です。
概要
のは、プロセスのステップを見てみましょう:
我々はすべてのネッティーサービスを開始すると、そのような飼育係に登録されたIPアドレスとポート番号として、いくつかのローカル・サービス情報をバー
外部サービスのネッティーリストのクラスタは(従来のHTTPサービスでもよい)があり、ローカルキャッシュにサービスのリスト、彼らのキャッシングサービスのリストを変更するための変更がある場合、ZKの変化に対応し、当社のリスニング・ノードへのサービス。
サービス要求へのすべてのクライアントは、外部に設けられたサーバは、クライアント(ここでは、ポーリング・モードを使用)、それぞれの戦略によると、クライアントは、サーバによって提供されたアドレスに応じてビジネス通信ノードの接続を確立するためにノードを選択します。
交換グループに参加するには、Java、Javaテクノロジのエンジニアの友人の1年から5年を仕事にようこそ:659 270 626は
、高可用性、高同時実行、高い性能と分散、JVMのパフォーマンスチューニングを持つJavaアーキテクチャグループ(春ソース内の無料学習教材を提供MyBatisの、ネッティー、Redisの、カフカ、 Mysqlの、飼育係、Tomcatの、ドッカー、ダボ、nginxのと情報アーキテクチャの他の知識)自分の学習を強化するために自分の時間の毎分の使用の合理化は、「何の時間を使用しません。 「彼のイデオロギーの怠惰を非表示にします!若い、ハード戦い、自分の将来のアカウントを与えます!