Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Gossip事始め

2,846 views

Published on

第八回cassandra勉強会slideです。

  • Be the first to comment

Gossip事始め

  1. 1. Gossip事始め<br />株式会社ムロドー<br />とみたかずたか<br />
  2. 2. アジェンダ<br />Gossip事始め<br />コードリーディングの準備<br />デーモン起動<br />起動準備<br />デーモン初期化<br />Gossip開始<br />
  3. 3. コードリーディング下準備<br /><ul><li>Eclpseでstepbystep 実行を行う。</li></ul>用意するもの<br /><ul><li>面倒くさいのでpleiadesonGlileo を用意
  4. 4. ApacheCassandra0.6.3
  5. 5. Cassandra クラスター</li></li></ul><li>Eclpseのセッティング<br /><ul><li>stepbystep 実行の設定で結構手間取った。</li></ul>Ecplseを適当なディレクトリに展開し起動を行う。<br />
  6. 6. Eclpseのセッティング<br />EcplseでCassandraのソースを読み込みプロジェクトを作成。<br />Cassandraのソースディレクトリを直接指定。<br />直接buildを行う為、要注意。Binディレクトリを吹っ飛ばしたり別途ソースを使いまわすことが不可能になります。<br />
  7. 7. Eclpseのセッティング<br />CassandraのBuild。<br />Build.xmlを右クリックし実行タブから外部ツールの構成を選択。<br />Targetからbuildとjarを選択<br />
  8. 8. Eclpseのセッティング<br />Eclipse上部から実行->実行の構成を選択し構成の作成、管理画面を表示<br />Cassandraの実行構成の設定<br />メインクラスに「org.apache.cassandra.thrift.CassandraDaemon」を指定<br />
  9. 9. Eclpseのセッティング<br />Cassandraの実行構成の設定<br />引き続き引数タブを選択<br />引数に<br />-Dcom.sun.management.jmxremote.port=8080<br />-Dcom.sun.management.jmxremote.ssl=false<br />-Dcom.sun.management.jmxremote.authenticate=false<br />-Dcassandra<br />-Dstorage-config="C:UserskazutakaDownloadsapache-cassandra-0.6.3-srcconf"<br />-Dcassandra-foreground=yes<br />を設定(少なくとも「Dstorage-config」は必要なようです。<br />
  10. 10. Eclpseのセッティング<br />CassandraのStepByStep実行<br />Debugのパースペクティブを開きデバック実行<br />
  11. 11. デーモン起動<br />Main関数直後にsetupメソッドがあります。<br /> public static void main(String[] args)<br /> {<br />CassandraDaemon daemon = new CassandraDaemon();<br /> String pidFile = System.getProperty("cassandra-pidfile");<br /> try<br /> { <br />daemon.setup();<br />203<br />204<br />205<br />206<br />207<br />208<br />209<br />210<br />211<br />212<br />
  12. 12. デーモン起動<br />Main直後にsetupメソッドがあります。<br /> public static void main(String[] args)<br /> {<br />CassandraDaemon daemon = new CassandraDaemon();<br /> String pidFile = System.getProperty("cassandra-pidfile");<br /> try<br /> { <br />daemon.setup();<br />203<br />204<br />205<br />206<br />207<br />208<br />209<br />210<br />211<br />212<br />
  13. 13. デーモン起動<br />Setup内サーバー初期化まで。<br />63 private void setup() throws IOException, TTransportException<br />64 {<br />~~<br />~~<br />69 intlistenPort = DatabaseDescriptor.getThriftPort();<br />70 InetAddresslistenAddr = DatabaseDescriptor.getThriftAddress();<br />~~<br />~~<br />92 try<br />93 {<br />94 SystemTable.checkHealth();<br />95 }<br />~~<br />~~<br />111 CommitLog.recover();<br />112 CompactionManager.instance.checkAllColumnFamilies();<br />~~<br />~~<br />114 // start server internals<br />115 StorageService.instance.initServer();<br />ローカルのIPと<br />ポートを取得<br />システムテーブルのチェック<br />Commitログの読み込みと内容のチェック、リカバリーなど<br />初期化開始<br />ここまでorg.apache.cassandra.thrift.CassandraDaemon<br />
  14. 14. デーモン起動<br />Setup内サーバー初期化まで。<br />63 private void setup() throws IOException, TTransportException<br />64 {<br />~~<br />~~<br />69 intlistenPort = DatabaseDescriptor.getThriftPort();<br />70 InetAddresslistenAddr = DatabaseDescriptor.getThriftAddress();<br />~~<br />~~<br />92 try<br />93 {<br />94 SystemTable.checkHealth();<br />95 }<br />~~<br />~~<br />111 CommitLog.recover();<br />112 CompactionManager.instance.checkAllColumnFamilies();<br />~~<br />~~<br />114 // start server internals<br />115 StorageService.instance.initServer();<br />ローカルのIPと<br />ポートを取得<br />システムテーブルのチェック<br />Commitログの読み込みと内容のチェック、リカバリーなど<br />初期化開始<br />ここまでorg.apache.cassandra.thrift.CassandraDaemon<br />
  15. 15. 相互認知<br />org.apache.cassandra.service.StorageService<br />initServer<br />304 initialized = true;<br />305 isClientMode = false;<br />306 storageMetadata_ = SystemTable.initMetadata();<br />307<br />308 // be certain that the recorded clustername matches what the user specified<br />309 if (!(Arrays.equals(storageMetadata_.getClusterName(),DatabaseDescriptor.getClusterName().getBytes())))<br />310 {<br />311 logger_.error("ClusterName mismatch: " + new String(storageMetadata_.getClusterName()) + " != " +<br />312 DatabaseDescriptor.getClusterName());<br />313 System.exit(3);<br />314 }<br />315<br />316 DatabaseDescriptor.createAllDirectories();<br />最初に自分自身の初期化を行う。<br />クラスターネーム、キースペース、トークンなどメタ情報取得など<br />
  16. 16. ゴシップ開始<br />org.apache.cassandra.service.StorageService<br />327 logger_.info("Starting up server gossip");<br />328<br />329 // have to start the gossip service before we can see any info on other nodes. this is necessary<br />330 // for bootstrap to get the load info it needs.<br />331 // (we won't be part of the storage ring though until we add a nodeId to our state, below.)<br />332 Gossiper.instance.register(this);<br />333Gossiper.instance.start(FBUtilities.getLocalAddress(), storageMetadata_.getGeneration()); // needed for node-ring gathering.<br />「start」の最初にローカルのアドレスを取得。(FBUtilities.getLocalAddress)<br />私たちが、他のノードの情報を見ることができる前にゴシップサービスは始めなければなりません。<br />これは、「bootstrap」が必要とする負荷の情報を得る為に必要です。<br />もっとも、私たちは「nodeid」を私たちのstateに追加するまでストレージ・リングの一部でなくなるでしょう。<br />
  17. 17. ゴシップ開始2<br />org.apache.cassandra.gms.Gossiper<br />838 public void start(InetAddresslocalEndPoint, intgenerationNbr)<br />839 {<br />840 localEndPoint_ = localEndPoint;<br />841 /* Get the seeds from the config and initialize them. */<br />842 Set<InetAddress> seedHosts = DatabaseDescriptor.getSeeds();<br />843 for (InetAddress seed : seedHosts)<br />844 {<br />845 if (seed.equals(localEndPoint))<br />846 continue;<br />847 seeds_.add(seed);<br />848 }<br />Seedsより自分以外のIPを取得<br />
  18. 18. ゴシップ開始3<br />org.apache.cassandra.gms.Gossiper<br />351 /* initialize the heartbeat state for this localEndPoint */<br />352 EndPointStatelocalState = endPointStateMap_.get(localEndPoint_);<br />353 if ( localState == null )<br />354 {<br />355 HeartBeatStatehbState = new HeartBeatState(generationNbr);<br />356 localState = new EndPointState(hbState);<br />357 localState.isAlive(true);<br />358 localState.isAGossiper(true);<br />359 endPointStateMap_.put(localEndPoint_, localState);<br />360 }<br />自分のハートビートステータスを取得<br />
  19. 19. ゴシップ開始4<br />org.apache.cassandra.gms.Gossiper<br />361 /* starts a timer thread */<br />362 gossipTimer_.schedule( new GossipTimerTask(), Gossiper.intervalInMillis_, Gossiper.intervalInMillis_);<br />GossipTimerTask起動!<br />  public final static intintervalInMillis_ = 1000;<br />というところで1000ミリ秒間隔でタイマー起動<br />
  20. 20. GossipTimerTask<br />org.apache.cassandra.gms.Gossiper<br />private class GossipTimerTask extends TimerTask<br />{<br /> public void run()<br /> {<br /> try<br /> {<br />MessagingService.instance.waitUntilListening();<br /> synchronized( Gossiper.instance )<br /> {<br />endPointStateMap_.get(localEndPoint_).getHeartBeatState().updateHeartBeat();<br /> List<GossipDigest> gDigests = new ArrayList<GossipDigest>();<br />Gossiper.instance.makeRandomGossipDigest(gDigests);<br /> if ( gDigests.size() > 0 )<br /> {<br /> Message message = makeGossipDigestSynMessage(gDigests);<br />booleangossipedToSeed = doGossipToLiveMember(message);<br />doGossipToUnreachableMember(message);<br /> if (!gossipedToSeed || liveEndpoints_.size() < seeds_.size())<br />doGossipToSeed(message);<br /> if (logger_.isTraceEnabled())<br />logger_.trace("Performing status check ...");<br />doStatusCheck();<br /> }<br /> }<br /> }<br /> catch (Exception e)<br /> {<br /> throw new RuntimeException(e);<br /> }<br /> }<br />}<br />GossipTimerTask<br />親abstractクラスにてRunnableのインターフェースを実装。<br />Runにてスレッド開始<br />1000ミリ秒ごとにハートビートを交換。<br />
  21. 21. 宣伝<br /><ul><li>日経Linux8月号に記事書きました。</li></ul>検証が大変でした。よかったら見てください。<br />ApacheがWorkerだったり、簡易PythonスクリプトをJmeterでたたけるように作っていたり細かい所にネタ満載です。<br />質問等有れば連絡ください。<br /> twitter:railute<br />blog:http://www.intheforest.jp/blog/<br /> e-mail:tomitakazutaka@gmail.com<br />

×