zoukankan      html  css  js  c++  java
  • 【Zookeeper】实现负载均衡原理

    一、思路

    • 使用Zookeeper实现负载均衡原理,服务器端将启动的服务注册到,zk注册中心上,采用临时节点。客户端从zk节点上获取最新服务节点信息,本地使用负载均衡算法,随机分配服务器。
    • 服务端启动的时候 会想注册中心Zookeeper中添加节点,(注意这个节点是临时的,目的是如果服务端关闭连接的时候,该结点会自动删除)
    • 客户端会查询注册中心里面的节点信息,拿到对应的地址和端口号,使用本地负载均衡算法随机 来进行负载均衡
        

      
     

    二、项目搭建

    2.1 Maven依赖

    • 需要引入zk的客户端依赖
    <dependencies>
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.8</version>
        </dependency>
    </dependencies>
    

    2.1 创建Server服务端

    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) {
    
                }
            }
        }
    
        }
    
    

    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;
            }
        }
    }
    }
    
    

    2.3 客户端ZkServerClient

    public class ZkServerClient {
        public static List<String> listServer = new ArrayList<String>();
        public static String parent = "/test";
    
        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.add("127.0.0.1:18080");
    
            final ZkClient zkClient = new ZkClient("127.0.0.1:2181", 6000, 1000);
            List<String> children = zkClient.getChildren(parent);
            getChilds(zkClient, children);
            // 监听事件
            zkClient.subscribeChildChanges(parent, new IZkChildListener() {
    
                public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
                    getChilds(zkClient, currentChilds);
                }
            });
        }
    
        private static void getChilds(ZkClient zkClient, List<String> currentChilds) {
            listServer.clear();
            for (String p : currentChilds) {
                String pathValue = (String) zkClient.readData(parent + "/" + p);
                listServer.add(pathValue);
            }
            serverCount = listServer.size();
            System.out.println("从zk读取到信息:" + listServer.toString());
    
        }
    
        // 请求次数
        private static int reqestCount = 1;
        // 服务数量
        private static int serverCount = 0;
    
        // 获取当前server信息
        public static String getServer() {
            // 实现负载均衡
            String serverName = listServer.get(reqestCount % serverCount);
            ++reqestCount;
            return serverName;
        }
    
        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();
                    }
                }
            }
        }
        }
    
  • 相关阅读:
    数独小算法,测试通过(Java)
    OC运行时和方法机制笔记
    AlertView点击确定后再执行后面的代码
    对第三方库集成方式的分析
    当程序进入后台时执行长时间代码
    iOS开发之GCD使用总结
    缓存网络请求的结果
    防止 NSTimer retain 作为 target 的 self
    获取设备唯一码
    原生网络请求以及AFN网络请求/异步下载
  • 原文地址:https://www.cnblogs.com/haoworld/p/zookeeper-shi-xian-fu-zai-jun-heng-yuan-li.html
Copyright © 2011-2022 走看看