zookeeper curator學習(配合spring boot模擬leader選舉)
基礎知識:http://www.cnblogs.com/LiZhiW/p/4930486.html
項目路徑:https://gitee.com/zhangjunqing/spring-boot 查找下面四個項目就可以了
zookeeper版本為zookeeper-3.4.9(需要查找合適的curator版本)
三個spring bootweb項目:
官方案例leader:
思路:新建三個spring boot web項目,在這三個web項目中定義一個過濾器來在初始化時搶奪leader權限,如果發現強奪到leader權限,則可以提供服務,如果沒有搶奪到請求則提示無法提供服務,當leader死掉時,curator會重新選舉新的leader(這裏只是提供選舉的一個使用思路,本身這個選舉也是舉個列子
1 pom文件依賴如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.springboot</groupId> <artifactId>springboot-zookeeper-leaderTest01</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>springoot</name> <url>http://maven.apache.org</url> <!-- 使用spring boot必須有這依賴 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.7.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- spring boot依賴jar包 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 以下是 curator依賴jar包 --> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>2.7.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-test</artifactId> <version>2.7.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-x-discovery</artifactId> <version>2.7.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.2</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2:spring boot啟動類如下:
package com.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; @ServletComponentScan(basePackages= {"com.springboot.filter"})//此處用於掃描過濾器 @SpringBootApplication //註意此類的包地址應該是最大的包,這樣他就可以自動掃描其下包的所有類.否則也可以(scanBasePackages={"com.springboot.controller"})指定要掃描的包 public class App { public static void main(String[] args) throws Exception { SpringApplication.run(App.class, args); } }
3:controller層如下:
package com.springboot.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/hello") public class HelloController { //如果能提供服務,請求返回值就在此處 @GetMapping("/say") public @ResponseBody String sayHello() { return "is servicing now"; } }
3:進行leader選舉根據其是否是leader身份來判斷是否提供服務
package com.springboot.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.framework.recipes.leader.LeaderSelector; import org.apache.curator.retry.ExponentialBackoffRetry; @WebFilter(filterName = "myFilter", urlPatterns = "/*") public class MyFilter implements Filter { //zookeeper集群地址 public static final String ZOOKEEPERSTRING = "192.168.99.129:2181,192.168.99.153:2181,192.168.99.171:2181"; //zookeeper鏈接client CuratorFramework client = null; //選舉類 LeaderSelector leaderSelector; String dataPath = "/tomcat/leader"; public void init(FilterConfig filterConfig) throws ServletException { //初始化連接 client = CuratorFrameworkFactory.newClient(ZOOKEEPERSTRING, new ExponentialBackoffRetry(1000, 3)); //啟動一個客戶端 client.start(); //實例化一個選舉器//特別註意LeaderListener,如果takeLeadership方法執行完畢,則會自動釋放leaders身份,故我們使用countDownLatch來阻塞此方法使其不主動放棄leaders身份 //同時這也給我們一個思路,我們可以通過在外部修改countDownLatch的值來控制leader是否主動放棄其身份 leaderSelector = new LeaderSelector(client, dataPath, new LeaderListener());//放棄leader權限後還可以參加選舉 leaderSelector.autoRequeue(); //開始服務 leaderSelector.start(); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest)request; //判斷是否現在是leader if(leaderSelector.hasLeadership()) { chain.doFilter(request, response); }else { response.getWriter().write("is not servicing"); } //chain.doFilter(request, response); } public void destroy() { // TODO Auto-generated method stub } }
4:leader身份監聽器:
package com.springboot.filter; import java.util.concurrent.CountDownLatch; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.recipes.leader.LeaderSelectorListenerAdapter; public class LeaderListener extends LeaderSelectorListenerAdapter{ private CountDownLatch countDownLatch = new CountDownLatch(1); //當這個方法執行完畢以後,leader會自動放棄身份,我們在這個項目當中使用countDownLatch阻塞不主動放棄身份 //這裏給我們提供思路,我們可以在外部動態修改countDownLatch值來使其主動放棄leader身份 public void takeLeadership(CuratorFramework client) throws Exception { System.out.println("一直阻塞當中,一直提供服務"); /** * 使用countdownLath,使leader永遠不放棄自己的地位 */ countDownLatch.await();; } }
5:進行測試
一: 在不同端口啟動項目3個此項目,發現8080現為leader提供服務
二:強制關閉8080的web服務,一會後觀察 leader成功跳到8081,提供服務
三:啟動8080,關閉8081,8082 一段時間後8080又重新拿回leader身份
特別註意:
在zookeeper重新選擇leader的過程中需要等待一段時間,這段時間沒法對外提供服務,
zookeeper curator學習(配合spring boot模擬leader選舉)