思路

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

创建项目工程

Maven依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>com.101tec</groupId>
  4. <artifactId>zkclient</artifactId>
  5. <version>0.8</version>
  6. </dependency>
  7. </dependencies>

创建Server服务

ZkServerScoekt服务

  1. //##ServerScoekt服务端
  2. public class ZkServerScoekt implements Runnable {
  3. private int port = 18080;
  4.  
  5. public static void main(String[] args) throws IOException {
  6. int port = 18080;
  7. ZkServerScoekt server = new ZkServerScoekt(port);
  8. Thread thread = new Thread(server);
  9. thread.start();
  10. }
  11.  
  12. public ZkServerScoekt(int port) {
  13. this.port = port;
  14. }
  15.  
  16. public void run() {
  17. ServerSocket serverSocket = null;
  18. try {
  19. serverSocket = new ServerSocket(port);
  20. System.out.println("Server start port:" + port);
  21. Socket socket = null;
  22. while (true) {
  23. socket = serverSocket.accept();
  24. new Thread(new ServerHandler(socket)).start();
  25. }
  26. } catch (Exception e) {
  27. e.printStackTrace();
  28. } finally {
  29. try {
  30. if (serverSocket != null) {
  31. serverSocket.close();
  32. }
  33. } catch (Exception e2) {
  34.  
  35. }
  36. }
  37. }
  38.  
  39. }

ZkServerClient

  1. public class ZkServerClient {
  2. public static List<String> listServer = new ArrayList<String>();
  3.  
  4. public static void main(String[] args) {
  5. initServer();
  6. ZkServerClient client= new ZkServerClient();
  7. BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
  8. while (true) {
  9. String name;
  10. try {
  11. name = console.readLine();
  12. if ("exit".equals(name)) {
  13. System.exit(0);
  14. }
  15. client.send(name);
  16. } catch (IOException e) {
  17. e.printStackTrace();
  18. }
  19. }
  20. }
  21.  
  22. // 注册所有server
  23. public static void initServer() {
  24. listServer.clear();
  25. listServer.add("127.0.0.1:18080");
  26. }
  27.  
  28. // 获取当前server信息
  29. public static String getServer() {
  30. return listServer.get(0);
  31. }
  32.  
  33. public void send(String name) {
  34.  
  35. String server = ZkServerClient.getServer();
  36. String[] cfg = server.split(":");
  37.  
  38. Socket socket = null;
  39. BufferedReader in = null;
  40. PrintWriter out = null;
  41. try {
  42. socket = new Socket(cfg[0], Integer.parseInt(cfg[1]));
  43. in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  44. out = new PrintWriter(socket.getOutputStream(), true);
  45.  
  46. out.println(name);
  47. while (true) {
  48. String resp = in.readLine();
  49. if (resp == null)
  50. break;
  51. else if (resp.length() > 0) {
  52. System.out.println("Receive : " + resp);
  53. break;
  54. }
  55. }
  56. } catch (Exception e) {
  57. e.printStackTrace();
  58. } finally {
  59. if (out != null) {
  60. out.close();
  61. }
  62. if (in != null) {
  63. try {
  64. in.close();
  65. } catch (IOException e) {
  66. e.printStackTrace();
  67. }
  68. }
  69. if (socket != null) {
  70. try {
  71. socket.close();
  72. } catch (IOException e) {
  73. e.printStackTrace();
  74. }
  75. }
  76. }
  77. }
  78. }

ServerHandler

  1. public class ServerHandler implements Runnable {
  2. private Socket socket;
  3.  
  4. public ServerHandler(Socket socket) {
  5. this.socket = socket;
  6. }
  7.  
  8. public void run() {
  9. BufferedReader in = null;
  10. PrintWriter out = null;
  11. try {
  12. in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
  13. out = new PrintWriter(this.socket.getOutputStream(), true);
  14. String body = null;
  15. while (true) {
  16. body = in.readLine();
  17. if (body == null)
  18. break;
  19. System.out.println("Receive : " + body);
  20. out.println("Hello, " + body);
  21. }
  22.  
  23. } catch (Exception e) {
  24. if (in != null) {
  25. try {
  26. in.close();
  27. } catch (IOException e1) {
  28. e1.printStackTrace();
  29. }
  30. }
  31. if (out != null) {
  32. out.close();
  33. }
  34. if (this.socket != null) {
  35. try {
  36. this.socket.close();
  37. } catch (IOException e1) {
  38. e1.printStackTrace();
  39. }
  40. this.socket = null;
  41. }
  42. }
  43. }
  44. }

改造ZkServerScoekt

  1. public class ZkServerScoekt implements Runnable {
  2. private static int port = 18081;
  3.  
  4. public static void main(String[] args) throws IOException {
  5. ZkServerScoekt server = new ZkServerScoekt(port);
  6. Thread thread = new Thread(server);
  7. thread.start();
  8. }
  9.  
  10. public ZkServerScoekt(int port) {
  11. this.port = port;
  12. }
  13.  
  14. public void regServer() {
  15. // 向ZooKeeper注册当前服务器
  16. ZkClient client = new ZkClient("127.0.0.1:2181", 60000, 1000);
  17. String path = "/test/server" + port;
  18. if (client.exists(path))
  19. client.delete(path);
  20. client.createEphemeral(path, "127.0.0.1:" + port);
  21. }
  22.  
  23. public void run() {
  24. ServerSocket serverSocket = null;
  25. try {
  26. serverSocket = new ServerSocket(port);
  27. regServer();
  28. System.out.println("Server start port:" + port);
  29. Socket socket = null;
  30. while (true) {
  31. socket = serverSocket.accept();
  32. new Thread(new ServerHandler(socket)).start();
  33. }
  34. } catch (Exception e) {
  35. e.printStackTrace();
  36. } finally {
  37. try {
  38. if (serverSocket != null) {
  39. serverSocket.close();
  40. }
  41. } catch (Exception e2) {
  42.  
  43. }
  44. }
  45. }
  46.  
  47. }

改造ZkServerClientScoekt

  1. public class ZkServerClient {
  2. public static List<String> listServer = new ArrayList<String>();
  3.  
  4. public static void main(String[] args) {
  5. initServer();
  6. ZkServerClient client = new ZkServerClient();
  7. BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
  8. while (true) {
  9. String name;
  10. try {
  11. name = console.readLine();
  12. if ("exit".equals(name)) {
  13. System.exit(0);
  14. }
  15. client.send(name);
  16. } catch (IOException e) {
  17. e.printStackTrace();
  18. }
  19. }
  20. }
  21.  
  22. // 注册所有server
  23. public static void initServer() {
  24. String path = "/test";
  25. final ZkClient zkClient = new ZkClient("127.0.0.1:2181", 6000, 1000);
  26. List<String> children = zkClient.getChildren(path);
  27. for (String ipServer : children) {
  28. listServer.add((String) zkClient.readData(path + "/" + ipServer));
  29. }
  30. System.out.println("####从注册中心获取服务信息####listServer:" + listServer.toString());
  31. // 监听事件
  32. zkClient.subscribeChildChanges(path, new IZkChildListener() {
  33.  
  34. public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
  35. listServer.clear();
  36. for (String ctPath : currentChilds) {
  37. listServer.add(zkClient.readData(parentPath) + "/" + ctPath);
  38. }
  39. System.out.println("####节点事件监听发生变化### listServer:" + listServer.toString());
  40.  
  41. }
  42. });
  43. // listServer.clear();
  44. // listServer.add("127.0.0.1:8080");
  45. }
  46.  
  47. private static int reqestCount = 1;
  48.  
  49. // 获取当前server信息
  50. public static String getServer() {
  51. int serverCount = listServer.size();
  52. String serverHost = listServer.get(reqestCount / serverCount);
  53. reqestCount++;
  54. return serverHost;
  55. }
  56.  
  57. public void send(String name) {
  58.  
  59. String server = ZkServerClient.getServer();
  60. String[] cfg = server.split(":");
  61.  
  62. Socket socket = null;
  63. BufferedReader in = null;
  64. PrintWriter out = null;
  65. try {
  66. socket = new Socket(cfg[0], Integer.parseInt(cfg[1]));
  67. in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  68. out = new PrintWriter(socket.getOutputStream(), true);
  69.  
  70. out.println(name);
  71. while (true) {
  72. String resp = in.readLine();
  73. if (resp == null)
  74. break;
  75. else if (resp.length() > 0) {
  76. System.out.println("Receive : " + resp);
  77. break;
  78. }
  79. }
  80. } catch (Exception e) {
  81. e.printStackTrace();
  82. } finally {
  83. if (out != null) {
  84. out.close();
  85. }
  86. if (in != null) {
  87. try {
  88. in.close();
  89. } catch (IOException e) {
  90. e.printStackTrace();
  91. }
  92. }
  93. if (socket != null) {
  94. try {
  95. socket.close();
  96. } catch (IOException e) {
  97. e.printStackTrace();
  98. }
  99. }
  100. }
  101. }
  102. }

使用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的状态同步以后
    ,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。

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

使用Zookeeper实现负载均衡原理的更多相关文章

  1. Zookeeper实现负载均衡原理

    先玩个正常的,好玩的socket编程: 服务端: 首先公共的这个Handler: package com.toov5.zkDubbo; import java.io.BufferedReader; i ...

  2. 【Zookeeper】实现负载均衡原理

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

  3. 六大Web负载均衡原理与实现

    还有个姊妹篇也可以参考这个文章:LVS(Linus Virtual Server):三种负载均衡方式比较+另三种负载均衡方式, LVS 实现了负载均衡,NAT,DR,TUN zookeeper使用ZA ...

  4. Nginx 负载均衡原理简介与负载均衡配置详解

    Nginx负载均衡原理简介与负载均衡配置详解   by:授客  QQ:1033553122   测试环境 nginx-1.10.0 负载均衡原理 客户端向反向代理发送请求,接着反向代理根据某种负载机制 ...

  5. 搞懂分布式技术9:Nginx负载均衡原理与实践

    搞懂分布式技术9:Nginx负载均衡原理与实践 本篇摘自<亿级流量网站架构核心技术>第二章 Nginx负载均衡与反向代理 部分内容. 当我们的应用单实例不能支撑用户请求时,此时就需要扩容, ...

  6. (转)使用LVS实现负载均衡原理及安装配置详解

    使用LVS实现负载均衡原理及安装配置详解 原文:https://www.cnblogs.com/liwei0526vip/p/6370103.html

  7. LVS实现负载均衡原理及安装配置

    LVS实现负载均衡原理及安装配置 负载均衡集群是 load balance 集群的简写,翻译成中文就是负载均衡集群.常用的负载均衡开源软件有nginx.lvs.haproxy,商业的硬件负载均衡设备F ...

  8. LVS实现负载均衡原理及安装配置 负载均衡

    LVS实现负载均衡原理及安装配置 负载均衡集群是 load balance 集群的简写,翻译成中文就是负载均衡集群.常用的负载均衡开源软件有nginx.lvs.haproxy,商业的硬件负载均衡设备F ...

  9. 使用ZooKeeper实现软负载均衡(原理)

    ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,提供的功能包括配置维护.名字服务.分布式同步.组服务等. ZooKeeper会维护一个树形的数据结构,类似于Windows资源管理器 ...

随机推荐

  1. 【C/C++开发】C++11的模板类型判断——std::is_same和std::decay

    C++11的模板类型判断--std::is_same和std::decay 问题提出:有一个模板函数,函数在处理int型和double型时需要进行特殊的处理,那么怎么在编译期知道传入的参数的数据类型是 ...

  2. Windows Server 2008 R2 IIS7.5配置FTP图文教程

    本文为大家分享了IIS 配置FTP 网站的具体过程,供大家参考,具体内容如下 说明:服务器环境是Windows Server 2008 R2,IIS7.5. 1. 在 服务器管理器的Web服务器(II ...

  3. POJ 2386 DFS深搜入门

    题目链接 Time Limit: 1000MS Memory Limit: 65536K Description Due to recent rains, water has pooled in va ...

  4. 使用IDEA的maven工程导入ojdbc14 jar包失败

    原因:ojdbc是要收费的所以maven无法通过中央仓库下载. 一开始以为是我网络不好,导致下载一直失败,可是我怎么想都不对劲,因为我自己使用了阿里云的镜像,网络不可能有问题吧,于是又使用外网,重新导 ...

  5. 【数据结构】11.java源码关于TreeMap

    目录 1.TreehMap的内部结构 2.TreehMap构造函数 3.元素新增策略 4.元素删除 5.元素修改和查找 6.特殊操作 7.扩容 8.总结 1.TreeMap的内部结构 首先确认一点,t ...

  6. 怎么删除json 键值对

    var obj = { 'id': 1, 'name': 2 } delete obj.id delete obj['id'] console.log(obj) //{ 'name': 2 }

  7. Java 函数式编程和Lambda表达式

    1.Java 8最重要的新特性 Lambda表达式.接口改进(默认方法)和批数据处理. 2.函数式编程 本质上来说,编程关注两个维度:数据和数据上的操作. 面向对象的编程泛型强调让操作围绕数据,这样可 ...

  8. JavaScript 的 深拷贝和浅拷贝

    深拷贝和浅拷贝都是针对的引用类型, JS中的变量类型分为值类型(基本类型)和引用类型: 对值类型进行复制操作会对值进行一份拷贝,而对引用类型赋值,则会对地址进行拷贝,最终两个变量指向同一份数据 一.先 ...

  9. mPass多租户系统微服务开发平台

    目录 项目总体架构图 基于SpringBoot2.x.SpringCloud并采用前后端分离的企业级微服务,多租户系统架构微服务开发平台 mPaaS(Microservice PaaS)为租户业务开发 ...

  10. Java字节码扩展

    异常表 代码一: public class Test03 { public void test() { try { InputStream is = new FileInputStream(" ...