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的过程中需要等待一段时间,这段时间没法对外提供服务,

时间: 2024-08-26 15:51:48

zookeeper curator学习(配合spring boot模拟leader选举)的相关文章

基于Spring Cloud的微服务构建学习-2 Spring Boot

基于Spring Cloud的微服务构建学习-2 Spring Boot 为什么使用Spring Boot而不是Spring Spring Boot具有自动化配置,快速开发,轻松部署优点,非常适合用作微服务架构中各项具体微服务的开发框架.它不仅可以帮助我们快速的构建微服务,还可以轻松简单的整合Spring Cloud实现系统服务化,而如果使用了传统的Spring构建方式的话,在整合过程中我们还需要做更多的依赖管理工作才能让它们完好的运行起来. Spring Boot的宗旨并非是重写Spring或

Spring Boot学习笔记——Spring Boot与Redis的集成

一.添加Redis缓存 1.添加Redis起步依赖 在pom.xml中添加Spring Boot支持Redis的依赖配置,具体如下: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> <version>1.4.7.RELEASE</version> </

学习创建spring boot

一.什么是spring boot? Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者.(网上自行搜索,一大堆) 二.如何创建一个spring boot工程 打开IDEA——File——New——Project

Spring Cloud 学习 (八) Spring Boot Admin

Spring Boot Admin 用于管理和监控一个或者多个 Spring Boot 程序 新建 spring-boot-admin-server pom <parent> <artifactId>spring-cloud-parent</artifactId> <groupId>com.karonda</groupId> <version>1.0.0</version> </parent> <mode

Activiti学习之spring boot 与activiti整合

声明:本文是springboot2.0的多项目构建,springboot2.0和spingboot1.5的配置是有出入的,构建项目之前请规范您的springboot版本,选择2.0以上. 一.在IDEA中使用工具创建SpringBoot + Gradle的父工程 new -> project ->gradle 二.在父工程下新建叁个模块 dao service web 右键单击父工程 new -> module -> Spring Initializr -> type选项选中

zookeeper curator学习(增删改查)(1)

主要参考的是curator,github地址:https://github.com/apache/curator/tree/master/curator-examples. zookeeper版本为zookeeper-3.4.9(需要查找合适的curator版本) 源码地址:https://gitee.com/zhangjunqing/spring-boot/tree/master/zookeeper (1)pom文件如下 <project xmlns="http://maven.apac

《spring boot》8.2章学习时无法正常启动,报“ORA-00942: 表或视图不存在 ”

在学习<spring boot>一书的过程中,由于原书作者难免有一些遗漏的的地方,或者系统.软件版本不一致.框架更新等各种因素,完全安装书中源码页不能实现项目的正常启动 在8.2章节,演示JPA对oracle的支持时,配置文件中设置了如下代码,正常情况下应该支持数据库自动创建序列和表,但实际启动时却报错"ORA-00942: 表或视图不存在 " spring.datasource.driverClassName=oracle.jdbc.OracleDriver spring

Spring Boot学习——Spring Boot简介

最近工作中需要使用到Spring Boot,但是以前工作中没有用到过Spring Boot,所以需要学习下Spring Boot.本系列笔记是笔者学习Spring Boot的笔记,有错误和不足之处,请不吝指教. 话不多说,直接进入主题. Spring Boot是为了简化Spring应用的创建.运行.调试.部署等而出现,使用它可以做到专注于Spring应用的开发,而无需过多关注xml的配置.简单的说,Spring Boot提供了一堆依赖打包,并已经按照使用习惯解决了依赖问题--习惯大于约定. Sp

spring boot框架学习6-spring boot的web开发(2)

本章节主要内容: 通过前面的学习,我们了解并快速完成了spring boot第一个应用.spring boot企业级框架,那么spring boot怎么读取静态资源?如js文件夹,css文件以及png/jpg图片呢?怎么自定义消息转换器呢?怎么自定义spring mvc的配置呢?这些我们在公司都需要用的.这些怎么解决呢?在接下来的小节详细讲解这些.好了,现在开启spring boot的web开发第一节 本节主要: 1:InternalResourceViewResolver讲解 2:自动配置静态