GVKun编程网logo

使用Zookeeper实现负载均衡原理(zookeeper做负载均衡)

8

以上就是给各位分享使用Zookeeper实现负载均衡原理,其中也会对zookeeper做负载均衡进行解释,同时本文还将给你拓展ActiveMQ建立brokercluster实现负载均衡、Dubbo与Z

以上就是给各位分享使用Zookeeper实现负载均衡原理,其中也会对zookeeper做负载均衡进行解释,同时本文还将给你拓展ActiveMQ建立broker cluster实现负载均衡、Dubbo 与 Zookeeper、SpringMVC 整合和使用(负载均衡、容错)、dubbo负载均衡与服务降级以及Zookeeper认证、java使用zookeeper实现的分布式锁示例等相关知识,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

使用Zookeeper实现负载均衡原理(zookeeper做负载均衡)

使用Zookeeper实现负载均衡原理(zookeeper做负载均衡)

 

思路

使用Zookeeper实现负载均衡原理,服务器端将启动的服务注册到,zk注册中心上,采用临时节点。客户端从zk节点上获取最新服务节点信息,本地使用负载均衡算法,随机分配服务器。

创建项目工程

Maven依赖

<dependencies>
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.8</version>
        </dependency>
    </dependencies>

创建Server服务

ZkServerScoekt服务

//##ServerScoekt服务端
public class ZkServerScoekt implements Runnable {
    private int port = 18080;

    public static void main(String[] args) throws IOException {
        int port = 18080;
        ZkServerScoekt server = new ZkServerScoekt(port);
        Thread thread = new Thread(server);
        thread.start();
    }

    public ZkServerScoekt(int port) {
        this.port = port;
    }

    public void run() {
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(port);
            System.out.println("Server start port:" + port);
            Socket socket = null;
            while (true) {
                socket = serverSocket.accept();
                new Thread(new ServerHandler(socket)).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (serverSocket != null) {
                    serverSocket.close();
                }
            } catch (Exception e2) {

            }
        }
    }

}

ZkServerClient

public class ZkServerClient {
    public static List<String> listServer = new ArrayList<String>();

    public static void main(String[] args) {
        initServer();
        ZkServerClient     client= new ZkServerClient();
        BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            String name;
            try {
                name = console.readLine();
                if ("exit".equals(name)) {
                    System.exit(0);
                }
                client.send(name);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // 注册所有server
    public static void initServer() {
        listServer.clear();
        listServer.add("127.0.0.1:18080");
    }

    // 获取当前server信息
    public static String getServer() {
        return listServer.get(0);
    }
    
    public void send(String name) {

        String server = ZkServerClient.getServer();
        String[] cfg = server.split(":");

        Socket socket = null;
        BufferedReader in = null;
        PrintWriter out = null;
        try {
            socket = new Socket(cfg[0], Integer.parseInt(cfg[1]));
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new PrintWriter(socket.getOutputStream(), true);

            out.println(name);
            while (true) {
                String resp = in.readLine();
                if (resp == null)
                    break;
                else if (resp.length() > 0) {
                    System.out.println("Receive : " + resp);
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                out.close();
            }
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

ServerHandler

public class ServerHandler implements Runnable {
    private Socket socket;

    public ServerHandler(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        BufferedReader in = null;
        PrintWriter out = null;
        try {
            in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
            out = new PrintWriter(this.socket.getOutputStream(), true);
            String body = null;
            while (true) {
                body = in.readLine();
                if (body == null)
                    break;
                System.out.println("Receive : " + body);
                out.println("Hello, " + body);
            }

        } catch (Exception e) {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (out != null) {
                out.close();
            }
            if (this.socket != null) {
                try {
                    this.socket.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                this.socket = null;
            }
        }
    }
}

改造ZkServerScoekt

public class ZkServerScoekt implements Runnable {
    private static int port = 18081;

    public static void main(String[] args) throws IOException {
        ZkServerScoekt server = new ZkServerScoekt(port);
        Thread thread = new Thread(server);
        thread.start();
    }

    public ZkServerScoekt(int port) {
        this.port = port;
    }

    public void regServer() {
        // 向ZooKeeper注册当前服务器
        ZkClient client = new ZkClient("127.0.0.1:2181", 60000, 1000);
        String path = "/test/server" + port;
        if (client.exists(path))
            client.delete(path);
        client.createEphemeral(path, "127.0.0.1:" + port);
    }

    public void run() {
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(port);
            regServer();
            System.out.println("Server start port:" + port);
            Socket socket = null;
            while (true) {
                socket = serverSocket.accept();
                new Thread(new ServerHandler(socket)).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (serverSocket != null) {
                    serverSocket.close();
                }
            } catch (Exception e2) {

            }
        }
    }

}

改造ZkServerClientScoekt

public class ZkServerClient {
    public static List<String> listServer = new ArrayList<String>();

    public static void main(String[] args) {
        initServer();
        ZkServerClient client = new ZkServerClient();
        BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            String name;
            try {
                name = console.readLine();
                if ("exit".equals(name)) {
                    System.exit(0);
                }
                client.send(name);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // 注册所有server
    public static void initServer() {
        String path = "/test";
        final ZkClient zkClient = new ZkClient("127.0.0.1:2181", 6000, 1000);
        List<String> children = zkClient.getChildren(path);
        for (String ipServer : children) {
            listServer.add((String) zkClient.readData(path + "/" + ipServer));
        }
        System.out.println("####从注册中心获取服务信息####listServer:" + listServer.toString());
        // 监听事件
        zkClient.subscribeChildChanges(path, new IZkChildListener() {

            public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
                listServer.clear();
                for (String ctPath : currentChilds) {
                    listServer.add(zkClient.readData(parentPath) + "/" + ctPath);
                }
                System.out.println("####节点事件监听发生变化### listServer:" + listServer.toString());

            }
        });
        // listServer.clear();
        // listServer.add("127.0.0.1:8080");
    }

    private static int reqestCount = 1;

    // 获取当前server信息
    public static String getServer() {
        int serverCount = listServer.size();
        String serverHost = listServer.get(reqestCount / serverCount);
        reqestCount++;
        return serverHost;
    }

    public void send(String name) {

        String server = ZkServerClient.getServer();
        String[] cfg = server.split(":");

        Socket socket = null;
        BufferedReader in = null;
        PrintWriter out = null;
        try {
            socket = new Socket(cfg[0], Integer.parseInt(cfg[1]));
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new PrintWriter(socket.getOutputStream(), true);

            out.println(name);
            while (true) {
                String resp = in.readLine();
                if (resp == null)
                    break;
                else if (resp.length() > 0) {
                    System.out.println("Receive : " + resp);
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                out.close();
            }
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
} 

使用Zookeeper实现选举策略

 

场景

  有一个向外提供的服务,服务必须7*24小时提供服务,不能有单点故障。所以采用集群的方式,采用master、slave的结构。一台主机多台备机。主机向外提供服务,备机负责监听主机的状态,一旦主机宕机,备机要迅速接代主机继续向外提供服务。从备机选择一台作为主机,就是master选举。

 

原理分析

 右边三台主机会尝试创建master节点,谁创建成功了,就是master,向外提供。其他两台就是slave

所有slave必须关注master的删除事件(临时节点,如果服务器宕机了,Zookeeper会自动把master节点删除)。如果master宕机了,会进行新一轮的master选举。本次我们主要关注master选举,服务注册、发现先不讨论。

使用Zookeeper原理

» 领导者(leader),负责进行投票的发起和决议,更新系统状态
  » 学习者(learner),包括跟随者(follower)和观察者(observer),follower用于接受客户端请求并想客户端返回结果,在选主过程中参与投票
  » Observer可以接受客户端连接,将写请求转发给leader,但observer不参加投票过程,只同步leader的状态,observer的目的是为了扩展系统,提高读取速度
  » 客户端(client),请求发起方

• Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab
     议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者
   崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和leader的状态同步以后
    ,恢复模式就结束了。状态同步保证了leaderServer具有相同的系统状态。

  为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(
   proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识
     leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader
   统治时期。低32位用于递增计数。
  每个Server在工作过程中有三种状态:
    LOOKING:当前Server不知道leader是谁,正在搜寻
    LEADING:当前Server即为选举出来的leader
    FOLLOWINGleader已经选举出来,当前Server与之同步

 

ActiveMQ建立broker cluster实现负载均衡

ActiveMQ建立broker cluster实现负载均衡

最近在测试activeMQ这个开源中间件,在建立broker-cluster实现负载均衡时出现一个问题,请教一下:

 <networkConnectors>
            <networkConnector uri="static:(tcp://host1:61616,tcp://host2:61616)" duplex="true"/>
   </networkConnectors>

配置是按照给的例子 activemq-static-network-broker2.xml进行的,我用一个发送者,开两个消费者,一个消费host1,另一个消费host2.看到两者消费的消息不一样多,大体host1这支是另一支的2倍;后来我host1开一支消费,host2开2支消费,此时两个host消费相等。

activemq实现的负载均衡就是这样子吗,不是应该每支consumer消费相等吗?

Dubbo 与 Zookeeper、SpringMVC 整合和使用(负载均衡、容错)

Dubbo 与 Zookeeper、SpringMVC 整合和使用(负载均衡、容错)

互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,Dubbo 是一个分布式服务框架,在这种情况下诞生的。现在核心业务抽取出来,作为独立的服务,使前端应用能更快速和稳定的响应。

 

第一:介绍 Dubbo 背景

 

    

大规模服务化之前,应用可能只是通过 RMI 或 Hessian 等工具,简单的暴露和引用远程服务,通过配置服务的 URL 地址进行调用,通过 F5 等硬件进行负载均衡。

(1) 当服务越来越多时,服务 URL 配置管理变得非常困难,F5 硬件负载均衡器的单点压力也越来越大。

此时需要一个服务注册中心,动态的注册和发现服务,使服务的位置透明。

并通过在消费方获取服务提供方地址列表,实现软负载均衡和 Failover,降低对 F5 硬件负载均衡器的依赖,也能减少部分成本。

(2) 当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。

这时,需要自动画出应用间的依赖关系图,以帮助架构师理清理关系。

(3) 接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?

为了解决这些问题,第一步,要将服务现在每天的调用量,响应时间,都统计出来,作为容量规划的参考指标。

其次,要可以动态调整权重,在线上,将某台机器的权重一直加大,并在加大的过程中记录响应时间的变化,直到响应时间到达阀值,记录此时的访问量,再以此访问量乘以机器数反推总容量。

 

第二:Dubbo 的简介

 

Dubbo 是一个分布式服务框架,解决了上面的所面对的问题,Dubbo 的架构如图所示:

 

节点角色说明:

Provider: 暴露服务的服务提供方。

Consumer: 调用远程服务的服务消费方。

Registry: 服务注册与发现的注册中心。

Monitor: 统计服务的调用次调和调用时间的监控中心。

Container: 服务运行容器。

 

调用关系说明:

0. 服务容器负责启动,加载,运行服务提供者。

1. 服务提供者在启动时,向注册中心注册自己提供的服务。

2. 服务消费者在启动时,向注册中心订阅自己所需的服务。

3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

 Dubbo 提供了很多协议,Dubbo 协议、RMI 协议、Hessian 协议,我们查看 Dubbo 源代码,有各种协议的实现,如图所示:

 

我们之前没用 Dubbo 之前时,大部分都使用 Hessian 来使用我们服务的暴露和调用,利用 HessianProxyFactory 调用远程接口。

 

上面是参考了 Dubbo 官方网介绍,接下来我们来介绍 SpringMVC、Dubbo、Zookeeper 整合使用。

 

第三:Dubbo 与 Zookeeper、SpringMVC 整合使用

  

  第一步:在 Linux 上安装 Zookeeper

 

       Zookeeper 作为 Dubbo 服务的注册中心,Dubbo 原先基于数据库的注册中心,没采用 Zookeeper,Zookeeper 一个分布式的服务框架,是树型的目录服务的数据存储,能做到集群管理数据 ,这里能很好的作为 Dubbo 服务的注册中心,Dubbo 能与 Zookeeper 做到集群部署,当提供者出现断电等异常停机时,Zookeeper 注册中心能自动删除提供者信息,当提供者重启时,能自动恢复注册数据,以及订阅请求。我们先在 linux 上安装 Zookeeper,我们安装最简单的单点,集群比较麻烦。

    (1)下载 Zookeeper-3.4.6.tar.gz  地址 http://www.apache.org/dist/zookeeper/

    (2) 我们放到 Linux 下的一个文件夹,然后解压: 

      #tar zxvf zookeeper-3.4.6.tar.gz

  (3)然后在对应的 zookeeper-3.4.6/conf 下有一个文件 zoo_sample.cfg 的这个文件里面配置了监听客户端连接的端口等一些信息,Zookeeper 在启动时会找 zoo.cfg 这个文件作为默认配置文件,所以我们复制一个名称为 zoo.cfg 的文件,如图所示:

     

 

   我们查看一下这个文件的里面的一些配置信息,如图所示:

    

  获取【下载地址】   最主流的 Java 后台 SSM 框架 springmvc spring mybatis 项目源码

说明:

 clientPort:监听客户端连接的端口。

 tickTime:基本事件单元,以毫秒为单位。它用来控制心跳和超时,默认情况下最小的会话超时时间为两倍的 tickTime。

 我们可以对配置文件的端口等或者进行高级配置和集群配置例如:maxClientCnxns:限制连接到 ZooKeeper 的客户端的数量等

 (4) 启动 Zookeeper 的服务,如图所示:

    

 到这边 Zookeeper 的安装和配置完成

  第二步:配置 dubbo-admin 的管理页面,方便我们管理页面

    (1) 下载 dubbo-admin-2.4.1.war 包,在 Linux 的 tomcat 部署,先把 dubbo-admin-2.4.1 放在 tomcat 的 webapps/ROOT 下,然后进行解压:

        #jar -xvf dubbo-admin-2.4.1.war

    (2) 然后到 webapps/ROOT/WEB-INF 下,有一个 dubbo.properties 文件,里面指向 Zookeeper ,使用的是 Zookeeper 的注册中心,如图所示:

        

   (3) 然后启动 tomcat 服务,用户名和密码:root, 并访问服务,显示登陆页面,说明 dubbo-admin 部署成功,如图所示:

      

  第三步:SpringMVC 与 Dubbo 的整合,这边使用的 Maven 的管理项目

    第一:我们先开发服务注册的,就是提供服务,项目结构如图所示:

         

    (1)test-maven-api 项目加入了一个服务接口,代码如下:

 

  1. public interface TestRegistryService {  
  2.    public String hello(String name);  
  3. }  

  (2)test-maven-console 在 pom.xml 加入 Dubbo 和 Zookeeper 的 jar 包、引用 test-maven-api 的 jar 包,代码如下:

 

  1.    <dependency>  
  2.     <groupId>cn.test</groupId>  
  3.     <artifactId>test-maven-api</artifactId>  
  4.     <version>0.0.1-SNAPSHOT</version>  
  5. </dependency>  
  6.   
  7.    <dependency>  
  8.          <groupId>com.alibaba</groupId>  
  9.          <artifactId>dubbo</artifactId>  
  10.          <version>2.5.3</version>  
  11.      </dependency>  
  12.        
  13.       <dependency>  
  14.          <groupId>org.apache.zookeeper</groupId>  
  15. <artifactId>zookeeper</artifactId>  
  16. <version>3.4.6</version>  
  17.      </dependency>  
  18.   
  19.    <dependency>  
  20.      <groupId>com.github.sgroschupf</groupId>  
  21. <artifactId>zkclient</artifactId>  
  22. <version>0.1</version>  
  23.    </dependency>  

(3) test-maven-console 实现具体的服务,代码如下:
 

  1.  @Service("testRegistryService")  
  2. ublic class TestRegistryServiceImpl implements TestRegistryService {  
  3. public String hello(String name) {    
  4.     return "hello"+name;  
  5. }  


(4) 我们服务以及实现好了,这时要暴露服务,代码如下:
  

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  4.     xmlns:jee="http://www.springframework.org/schema/jee"  
  5.     xmlns:tx="http://www.springframework.org/schema/tx"  
  6.     <span >xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"</span>  
  7.     xmlns:context="http://www.springframework.org/schema/context"  
  8.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd  
  9.     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd  
  10.     http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd  
  11.     <span >http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd</span>  
  12.     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"  
  13.     default-lazy-init="false" >  
  14.    <!-- 提供方应用名称信息,这个相当于起一个名字,我们 dubbo 管理页面比较清晰是哪个应用暴露出来的 -->  
  15.    <dubbo:application name="dubbo_provider"></dubbo:application>  
  16.    <!-- 使用 zookeeper 注册中心暴露服务地址 -->    
  17.    <dubbo:registry address="zookeeper://127.0.0.1:2181" check="false" subscribe="false" register=""></dubbo:registry>  
  18.   <!-- 要暴露的服务接口 -->    
  19.   <dubbo:service interface="cn.test.dubbo.registry.service.TestRegistryService" ref="testRegistryService" />        
  20. </beans>  

 

说明:

   dubbo:registry 标签一些属性的说明:

      1)register 是否向此注册中心注册服务,如果设为 false,将只订阅,不注册。

      2)check 注册中心不存在时,是否报错。

      3)subscribe 是否向此注册中心订阅服务,如果设为 false,将只注册,不订阅。

      4)timeout 注册中心请求超时时间 (毫秒)。

      5)address 可以 Zookeeper 集群配置,地址可以多个以逗号隔开等。

  dubbo:service 标签的一些属性说明:

     1)interface 服务接口的路径

     2)ref 引用对应的实现类的 Bean 的 ID

     3)registry 向指定注册中心注册,在多个注册中心时使用,值为 <dubbo:registry> 的 id 属性,多个注册中心 ID 用逗号分隔,如果不想将该服务注册到任何 registry,可将值设为 N/A

     4)register 默认 true ,该协议的服务是否注册到注册中心。

 

  (5) 启动项目,然后我们在 Dubbo 管理页面上显示,已经暴露的服务,但显示还没有消费者,因为我们还没实现消费者服务,如图所示:

  

   第二:我们在开发服务消费者,就是调用服务,我们在新建一个新的消费者项目结构如图所示:

       

   (1)test-maven-server-console 的 pom.xml 引入 Dubbo 和 Zookeeper 的 jar 包、test-maven-api 的 jar 包,因为引入 test-maven-api 的 jar 包,我们在项目中调用像在本地调用一样。代码如下:

      

[java] view plain copy

 

  1.    <dependency>  
  2.     <groupId>cn.test</groupId>  
  3.     <artifactId>test-maven-api</artifactId>  
  4.     <version>0.0.1-SNAPSHOT</version>  
  5. </dependency>  
  6.   
  7.    <dependency>  
  8.          <groupId>com.alibaba</groupId>  
  9.          <artifactId>dubbo</artifactId>  
  10.          <version>2.5.3</version>  
  11.      </dependency>  
  12.        
  13.       <dependency>  
  14.          <groupId>org.apache.zookeeper</groupId>  
  15. <artifactId>zookeeper</artifactId>  
  16. <version>3.4.6</version>  
  17.      </dependency>  
  18.   
  19.    <dependency>  
  20.      <groupId>com.github.sgroschupf</groupId>  
  21. <artifactId>zkclient</artifactId>  
  22. <version>0.1</version>  
  23.    </dependency>  

  (2)test-maven-server-console 项目的具体实现,代码如下:

     

[java] view plain copy

 

  1. @Controller  
  2. public class IndexController {  
  3.       
  4.     @Autowired  
  5.     private TestRegistryService testRegistryService;  
  6.       
  7.     @RequestMapping("/hello")  
  8.     public String index(Model model){  
  9.          String name=testRegistryService.hello("zz");  
  10.          System.out.println("xx=="+name);  
  11.         return "";  
  12.     }  
  13.   
  14. }  


  (3) 我们要引用的地址,代码如下:
   

[java] view plain copy

 

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  4.     xmlns:jee="http://www.springframework.org/schema/jee"  
  5.     xmlns:tx="http://www.springframework.org/schema/tx"  
  6.     <span ><span >xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"</span></span>  
  7.     xmlns:context="http://www.springframework.org/schema/context"  
  8.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd  
  9.     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd  
  10.     http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd  
  11.     <span >http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd</span>  
  12.     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"  
  13.     default-lazy-init="false" >  
  14.   
  15.    <dubbo:application name="dubbo_consumer"></dubbo:application>  
  16.    <!-- 使用 zookeeper 注册中心暴露服务地址 -->    
  17.    <dubbo:registry address="zookeeper://192.168.74.129:2181" check="false"></dubbo:registry>   
  18.      <!-- 要引用的服务 -->    
  19.    <dubbo:reference interface="cn.test.dubbo.registry.service.TestRegistryService" id="testRegistryService"></dubbo:reference>  
  20. </beans>  

 

说明:

   dubbo:reference 的一些属性的说明:

      1)interface 调用的服务接口

      2)check 启动时检查提供者是否存在,true 报错,false 忽略

      3)registry 从指定注册中心注册获取服务列表,在多个注册中心时使用,值为 <dubbo:registry> 的 id 属性,多个注册中心 ID 用逗号分隔

      4)loadbalance 负载均衡策略,可选值:random,roundrobin,leastactive,分别表示:随机,轮循,最少活跃调用

   

(4) 项目启动,Dubbo 管理页面,能看到消费者,如图所示:

 

(5) 然后访问消费者项目,Controller 层能像调用本地一样调用服务的具体实现,如图所示:

  

 

 

 

Dubbo 提供了多种容错方案,包括负载均衡这些,如图所示:

 

 

dubbo负载均衡与服务降级以及Zookeeper认证

dubbo负载均衡与服务降级以及Zookeeper认证

1.Dubbo集群与负载均衡

2.服务降级:指的是当服务器资源紧张的时候,暂停掉一些不重要的微服务,从而将所有的服务器的资源统一交由另外一个核心的微服务处理

  • 【dubbo-api】如果要想实现服务降级的处理,在Dubbo之中需要为业务接口设计一个降级时的处理业务类即可

package com.yootk.dubbo.service;
import com.yootk.dubbo.service.IMessageService;
import com.yootk.dubbo.vo.Message;
public class IMessageServiceMock implements IMessageService {
    @Override
    public Message echo(Message msg) {
        Message echoMessage = new Message() ;
        echoMessage.setSender("【ECHO】Nothing...");
        echoMessage.setTitle("【ECHO】Nothing...");
        echoMessage.setContent("【ECHO】Nothing...");
        return echoMessage;
    }
}

  • 【dubbo-echo-consumer】所有的服务降级的处理操作全部都是在客户端上处理完成的,修改客户端的接口注入配置

@Reference(mock="true",check=false)
private IMessageService messageInstance;

  

  那么现在就有一个问题了,如果所有的业务接口都使用这样的一种Mock实现类型,这个时候一定会造成代码的维护困难,所以还有一种简单的做法,让数据直接返回null,一旦服务不可用,返回一个null对象,而这种配置只需要在消费端的注解上定义即可。

@Reference(mock="return null",check=false)
private IMessageService messageInstance;

3.ZooKeeper认证:在以后实际的开发之中,一定要为ZooKeeper设置ACL认证,才可以更好的进行注册内容的保护,同时防止其他用户盗取你的网络资源。

 • 【zookeeper-cluster-*】为根目录设置Zookeeper的认证信息,同时建议删除已经存在的所有dubbo路径信息

    • 删除当前已经存在的所有dubbo的路径:deleteall /dubbo

    • 追加一个新的数字认证信息:addauth digest zkuser:hellolee

    • 为zkuser的账户设置权限:setAcl / auth:zkuser:hellolee:crwda

 • 【zookeeper-echo-*】修改服务提供者与服务消费者的dubbo.properties配置文件,追加账户信息:

  dubbo.registry.username=zkuser
  dubbo.registry.password=hellolee

 • 【zookeeper-echo-*】修改服务提供者与服务消费者的spring配置文件

   • 【zookeeper-echo-provider】spring-dubbo-provider.xml:

    <!-- 在进行Dubbo服务注册的时候一定要将服务注册到ZooKeeper之中 -->
    <dubbo:registry protocol="zookeeper" address="${dubbo.registry.address}"
                    timeout="${dubbo.provider.timeout}" file="${dubbo.registry.file}"
                    username="${dubbo.registry.username}"
                    password="${dubbo.registry.password}" client="curator"/>

   • 【zookeeper-echo-provider】spring-dubo-consumer.xml:

    <!-- 在进行Dubbo服务注册的时候一定要将服务注册到ZooKeeper之中 -->
    <dubbo:registry protocol="zookeeper" address="${dubbo.registry.address}"
        timeout="${dubbo.provider.timeout}"
        username="${dubbo.registry.username}"
        password="${dubbo.registry.password}" client="curator"/>

4.Dubbo直连与Token认证

  • 修改服务提供端的配置文件,引入token的配置项:

<dubbo:provider timeout="${dubbo.provider.timeout}"
                    dispatcher="message" threadpool="fixed" threads="8" token="true"/>

  • 修改消费端的@Reference注解,将其设置为默认形式的引用配置:在日后所有的项目开发之中,dubbo服务端一定要开启token认证,这才是标准的项目开发。

@Reference(mock="return null",check=false)
private IMessageService messageInstance;

   

 

java使用zookeeper实现的分布式锁示例

java使用zookeeper实现的分布式锁示例

这篇文章主要介绍了java使用zookeeper实现的分布式锁示例,需要的朋友可以参考下

使用zookeeper实现的分布式锁

分布式锁,实现了Lock接口

复制代码 代码如下:

package com.concurrent;import java.io.IOException;

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.TimeUnit;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import org.apache.zookeeper.CreateMode;

import org.apache.zookeeper.KeeperException;

import org.apache.zookeeper.WatchedEvent;

import org.apache.zookeeper.Watcher;

import org.apache.zookeeper.ZooDefs;

import org.apache.zookeeper.ZooKeeper;

import org.apache.zookeeper.data.Stat;

/**

   distributedLock lock = null;

 try {

  lock = new distributedLock("127.0.0.1:2182","test");

  lock.lock();

  //do something...

 } catch (Exception e) {

  e.printstacktrace();

 }

 finally {

  if(lock != null)

   lock.unlock();

 }

 * @author xueliang

 *

 */

public class distributedLock implements Lock, Watcher{

 private ZooKeeper zk;

 private String root = "/locks";//根

 private String lockName;//竞争资源的标志

 private String waitNode;//等待前一个锁

 private String myZnode;//当前锁

 private CountDownLatch latch;//计数器

 private int sessionTimeout = 30000;

 private List exception = new ArrayList();

 /**

  * 创建分布式锁,使用前请确认config配置的zookeeper服务可用

  * @param config 127.0.0.1:2181

  * @param lockName 竞争资源标志,lockName中不能包含单词lock

  */

 public distributedLock(String config, String lockName){

  this.lockName = lockName;

  // 创建一个与服务器的连接

   try {

   zk = new ZooKeeper(config, sessionTimeout, this);

   Stat stat = zk.exists(root, false);

   if(stat == null){

    // 创建根节点

    zk.create(root, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);

   }

  } catch (IOException e) {

   exception.add(e);

  } catch (KeeperException e) {

   exception.add(e);

  } catch (InterruptedException e) {

   exception.add(e);

  }

 }

 /**

  * zookeeper节点的监视器

  */

 public void process(WatchedEvent event) {

  if(this.latch != null) { 

            this.latch.countDown(); 

        }

 }

 public void lock() {

  if(exception.size() > 0){

   throw new LockException(exception.get(0));

  }

  try {

   if(this.tryLock()){

    System.out.println("Thread " + Thread.currentThread().getId() + " " +myZnode + " get lock true");

    return;

   }

   else{

    waitForLock(waitNode, sessionTimeout);//等待锁

   }

  } catch (KeeperException e) {

   throw new LockException(e);

  } catch (InterruptedException e) {

   throw new LockException(e);

  }

 }

 public boolean tryLock() {

  try {

   String splitStr = "_lock_";

   if(lockName.contains(splitStr))

    throw new LockException("lockName can not contains \u000B");

   //创建临时子节点

   myZnode = zk.create(root + "/" + lockName + splitStr, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);

   System.out.println(myZnode + " is created ");

   //取出所有子节点

   List subNodes = zk.getChildren(root, false);

   //取出所有lockName的锁

   List lockObjNodes = new ArrayList();

   for (String node : subNodes) {

    String _node = node.split(splitStr)[0];

    if(_node.equals(lockName)){

     lockObjNodes.add(node);

    }

   }

   Collections.sort(lockObjNodes);

   System.out.println(myZnode + "==" + lockObjNodes.get(0));

   if(myZnode.equals(root+"/"+lockObjNodes.get(0))){

    //如果是最小的节点,则表示取得锁

             return true;

         }

   //如果不是最小的节点,找到比自己小1的节点

   String subMyZnode = myZnode.substring(myZnode.lastIndexOf("/") + 1);

   waitNode = lockObjNodes.get(Collections.binarySearch(lockObjNodes, subMyZnode) - 1);

  } catch (KeeperException e) {

   throw new LockException(e);

  } catch (InterruptedException e) {

   throw new LockException(e);

  }

  return false;

 }

 public boolean tryLock(long time, TimeUnit unit) {

  try {

   if(this.tryLock()){

    return true;

   }

         return waitForLock(waitNode,time);

  } catch (Exception e) {

   e.printstacktrace();

  }

  return false;

 }

 private boolean waitForLock(String lower, long waitTime) throws InterruptedException, KeeperException {

        Stat stat = zk.exists(root + "/" + lower,true);

        //判断比自己小一个数的节点是否存在,如果不存在则无需等待锁,同时注册监听

        if(stat != null){

         System.out.println("Thread " + Thread.currentThread().getId() + " waiting for " + root + "/" + lower);

         this.latch = new CountDownLatch(1);

         this.latch.await(waitTime, TimeUnit.MILLISECONDS);

         this.latch = null;

        }

        return true;

    }

 public void unlock() {

  try {

   System.out.println("unlock " + myZnode);

   zk.delete(myZnode,-1);

   myZnode = null;

   zk.close();

  } catch (InterruptedException e) {

   e.printstacktrace();

  } catch (KeeperException e) {

   e.printstacktrace();

  }

 }

 public void lockInterruptibly() throws InterruptedException {

  this.lock();

 }

 public Condition newCondition() {

  return null;

 }

 public class LockException extends RuntimeException {

  private static final long serialVersionUID = 1L;

  public LockException(String e){

   super(e);

  }

  public LockException(Exception e){

   super(e);

  }

 }

}

上一篇:java 中 zookeeper简单使用下一篇:详解 Java静态代理 热门搜索:

redis分布式锁实现原理 

java实例 

使用实例 

分布式锁 

使用示例 

相关文章

java使用zookeeper实现的分布式锁示例

2021-10-10阅读(9392)评论(0)推荐()

这篇文章主要介绍了java使用zookeeper实现的分布式锁示例,需要的朋友可以参考下

分析ZooKeeper分布式锁的实现

2021-10-19阅读(9576)评论(0)推荐()

在分布式的情况下,sychornized 和 Lock 已经不能满足我们的要求了,那么就需要使用第三方的锁了,这里我们就使用 ZooKeeper 来实现一个分布...

ZooKeeper 实现分布式锁的方法示例

2021-11-18阅读(4303)评论(0)推荐()

这篇文章主要介绍了ZooKeeper 实现分布式锁的方法示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

zookeeper实现分布式锁

2021-09-20阅读(5325)评论(0)推荐()

这篇文章主要为大家详细介绍了基于zookeeper实现分布式锁,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

浅谈Java(SpringBoot)基于zookeeper的分布式锁实现

2021-10-10阅读(6450)评论(0)推荐()

这篇文章主要介绍了Java(SpringBoot)基于zookeeper的分布式锁实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价...

C# 实现Zookeeper分布式锁的参考示例

2021-10-06阅读(3932)评论(0)推荐()

Zookeeper分布式锁的原理是巧妙的是使用了znode临时节点的特点和监听(watcher)机制,监听机制很简单,就是我们可以给znode添加一个监听器,当...

如何操作Redis和zookeeper实现分布式锁

2021-11-19阅读(2654)评论(0)推荐()

这篇文章主要介绍了如何操作Redis和zookeeper实现分布式锁的相关资料,需要的朋友可以参考下

取消

有人回复时邮件通知我

提交评论

我们今天的关于使用Zookeeper实现负载均衡原理zookeeper做负载均衡的分享就到这里,谢谢您的阅读,如果想了解更多关于ActiveMQ建立broker cluster实现负载均衡、Dubbo 与 Zookeeper、SpringMVC 整合和使用(负载均衡、容错)、dubbo负载均衡与服务降级以及Zookeeper认证、java使用zookeeper实现的分布式锁示例的相关信息,可以在本站进行搜索。

本文标签: