Zookeeper實現Master選舉(哨兵機制)


master選舉使用場景及結構

 現在很多時候我們的服務需要7*24小時工作,假如一台機器掛了,我們希望能有其它機器頂替它繼續工作。此類問題現在多采用master-salve模式,也就是常說的主從模式,正常情況下主機提供服務,備機負責監聽主機狀態,當主機異常時,可以自動切換到備機繼續提供服務(這里有點兒類似於數據庫主庫跟備庫,備機正常情況下只監聽,不工作),這個切換過程中選出下一個主機的過程就是master選舉。

對於以上提到的場景,傳統的解決方式是采用一個備用節點,這個備用節點定期給當前主節點發送ping包,主節點收到ping包后會向備用節點發送應答ack,當備用節點收到應答,就認為主節點還活着,讓它繼續提供服務,否則就認為主節點掛掉了,自己將開始行使主節點職責。如圖1所示:

 

使用Zookeeper實現服務master選舉

        在哨兵機制中 只能一個主 多個從!

使用zk可以實現之!

 

  原理: 多個服務器在啟動時候,會在Zookeeper上創建相同的臨時節點,誰如果能夠創建成功,誰就為主!(節點保證唯一)

           如果主服務器宕機,會話連接斷開。臨時節點刪除。其他節點服務選舉開始

 

  

 創建項目:

pom文件: 注意springboot 整合 zk的包

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.0.RELEASE</version>
	</parent>
	<dependencies>
		<dependency>
			<groupId>com.101tec</groupId>
			<artifactId>zkclient</artifactId>
			<version>0.10</version>
			<exclusions>
				<exclusion>
					<artifactId>slf4j-api</artifactId>
					<groupId>org.slf4j</groupId>
				</exclusion>
				<exclusion>
					<artifactId>log4j</artifactId>
					<groupId>log4j</groupId>
				</exclusion>
				<exclusion>
					<artifactId>slf4j-log4j12</artifactId>
					<groupId>org.slf4j</groupId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
	</dependencies>  

 后台controller

package com.toov5.zkMaster;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class IndexController {
   @Value("${server.port}")
   private String serverPort;
   
   @RequestMapping("getServerInfo")
   public String getServerInfo(){
       return "serverPort"+serverPort+(ElectionMaster.isSurvival? "選舉為主" :"選舉為從");
   }

    public static void main(String[] args) {
        //1,項目啟動的時候  在zk創建臨時節點
        //2,誰能夠創建成功誰就是主服務器
        //3,使用服務監聽節點是否被刪除,如果被刪。 重新開始創建節點
        
    }
    
}

啟動加載運行類

package com.toov5.zkMaster;

import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationRunner implements ApplicationRunner{
      private ZkClient zkClient  =    new ZkClient("192.168.91.5:2181");
      private String path = "/election";
      @Value("${server.port}")
      private String serverPort;
    //啟動后執行的方法
     public void run(ApplicationArguments args) throws Exception {  //重寫這個方法
        System.out.println("項目啟動成功!"); 
             //1,項目啟動的時候  在zk創建臨時節點
           createEphemeral();
            //2,誰能夠創建成功誰就是主服務器
            //3,使用服務監聽節點是否被刪除,如果被刪。 重新開始創建節點
        zkClient.subscribeDataChanges(path, new IZkDataListener() {
            //返回節點如果被刪除后 返回通知
            public void handleDataDeleted(String arg0) throws Exception {
               //重新創建(選舉)
                System.out.println("開始重新選舉策略");
                 createEphemeral();
            }
            
            public void handleDataChange(String arg0, Object arg1) throws Exception {
                // TODO Auto-generated method stub
                
            }
        });
    }
    
    private void createEphemeral(){
       try {
       zkClient.createEphemeral(path); 
        System.out.println("serverport"+serverPort+",選舉成功!");
        ElectionMaster.isSurvival=true; //標志位true  單個jvm共享
    } catch (Exception e) {
        System.out.println("該節點已經存在");
        ElectionMaster.isSurvival=false;
    }
    }
     
     
}

全局變量

package com.toov5.zkMaster;

public class ElectionMaster {
     //服務器info信息 是否存活
    public static boolean isSurvival;  //靜態的 標志下 服務器是否還存活
}

運行類

package com.toov5.zkMaster;

public class ElectionMaster {
     //服務器info信息 是否存活
    public static boolean isSurvival;  //靜態的 標志下 服務器是否還存活
}

yml:

server:
  port: 8088

 

運行,啟動兩個端口

一個主 一個從 

然后關掉主,重新選舉從(需要等待一段時間,強制關閉有延遲的)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM