15. 相互認知 org.apache.cassandra.service.StorageService initServer 304 initialized = true; 305 isClientMode = false; 306 storageMetadata_ = SystemTable.initMetadata(); 307 308 // be certain that the recorded clustername matches what the user specified 309 if (!(Arrays.equals(storageMetadata_.getClusterName(),DatabaseDescriptor.getClusterName().getBytes()))) 310 { 311 logger_.error("ClusterName mismatch: " + new String(storageMetadata_.getClusterName()) + " != " + 312 DatabaseDescriptor.getClusterName()); 313 System.exit(3); 314 } 315 316 DatabaseDescriptor.createAllDirectories(); 最初に自分自身の初期化を行う。 クラスターネーム、キースペース、トークンなどメタ情報取得など
16. ゴシップ開始 org.apache.cassandra.service.StorageService 327 logger_.info("Starting up server gossip"); 328 329 // have to start the gossip service before we can see any info on other nodes. this is necessary 330 // for bootstrap to get the load info it needs. 331 // (we won't be part of the storage ring though until we add a nodeId to our state, below.) 332 Gossiper.instance.register(this); 333Gossiper.instance.start(FBUtilities.getLocalAddress(), storageMetadata_.getGeneration()); // needed for node-ring gathering. 「start」の最初にローカルのアドレスを取得。(FBUtilities.getLocalAddress) 私たちが、他のノードの情報を見ることができる前にゴシップサービスは始めなければなりません。 これは、「bootstrap」が必要とする負荷の情報を得る為に必要です。 もっとも、私たちは「nodeid」を私たちのstateに追加するまでストレージ・リングの一部でなくなるでしょう。
17. ゴシップ開始2 org.apache.cassandra.gms.Gossiper 838 public void start(InetAddresslocalEndPoint, intgenerationNbr) 839 { 840 localEndPoint_ = localEndPoint; 841 /* Get the seeds from the config and initialize them. */ 842 Set<InetAddress> seedHosts = DatabaseDescriptor.getSeeds(); 843 for (InetAddress seed : seedHosts) 844 { 845 if (seed.equals(localEndPoint)) 846 continue; 847 seeds_.add(seed); 848 } Seedsより自分以外のIPを取得
18. ゴシップ開始3 org.apache.cassandra.gms.Gossiper 351 /* initialize the heartbeat state for this localEndPoint */ 352 EndPointStatelocalState = endPointStateMap_.get(localEndPoint_); 353 if ( localState == null ) 354 { 355 HeartBeatStatehbState = new HeartBeatState(generationNbr); 356 localState = new EndPointState(hbState); 357 localState.isAlive(true); 358 localState.isAGossiper(true); 359 endPointStateMap_.put(localEndPoint_, localState); 360 } 自分のハートビートステータスを取得
19. ゴシップ開始4 org.apache.cassandra.gms.Gossiper 361 /* starts a timer thread */ 362 gossipTimer_.schedule( new GossipTimerTask(), Gossiper.intervalInMillis_, Gossiper.intervalInMillis_); GossipTimerTask起動! public final static intintervalInMillis_ = 1000; というところで1000ミリ秒間隔でタイマー起動
20. GossipTimerTask org.apache.cassandra.gms.Gossiper private class GossipTimerTask extends TimerTask { public void run() { try { MessagingService.instance.waitUntilListening(); synchronized( Gossiper.instance ) { endPointStateMap_.get(localEndPoint_).getHeartBeatState().updateHeartBeat(); List<GossipDigest> gDigests = new ArrayList<GossipDigest>(); Gossiper.instance.makeRandomGossipDigest(gDigests); if ( gDigests.size() > 0 ) { Message message = makeGossipDigestSynMessage(gDigests); booleangossipedToSeed = doGossipToLiveMember(message); doGossipToUnreachableMember(message); if (!gossipedToSeed || liveEndpoints_.size() < seeds_.size()) doGossipToSeed(message); if (logger_.isTraceEnabled()) logger_.trace("Performing status check ..."); doStatusCheck(); } } } catch (Exception e) { throw new RuntimeException(e); } } } GossipTimerTask 親abstractクラスにてRunnableのインターフェースを実装。 Runにてスレッド開始 1000ミリ秒ごとにハートビートを交換。