• 单机器搭建 zk 集群


    在一台机器上配置 2 节点的 zk 集群,zk1 和 zk2 的 serverid 分别为 1 和 2,本机 ip 是 192.168.40.1

    zk1 相关配置:

    dataDir=E:/test/zk_project/data
    dataLogDir=E:/test/zk_project/log
    clientPort=2181
    server.1=192.168.40.1:2888:3888
    server.2=192.168.40.1:2889:3889

    zk2 相关配置:

    dataDir=E:/test/zk_project_r/data
    dataLogDir=E:/test/zk_project_r/log
    clientPort=2182
    server.1=192.168.40.1:2888:3888
    server.2=192.168.40.1:2889:3889

    配置集群,重要就是 ip 和 端口的配置,以 zk1 为例,2888 端口是它成为 leader 后,follower 连接这个端口传输数据,而 3888 端口是选举端口,集群中的节点连接到这个端口发送投票信息。myid 文件放在 dataDir 目录中,配置 server 的 id。

    public static class QuorumServer {
        public QuorumServer(long id, InetSocketAddress addr,
                InetSocketAddress electionAddr) {
            this.id = id;
            this.addr = addr;
            this.electionAddr = electionAddr;
        }
    
        // 成为 leader 后的地址,以 zk1 为例,即 192.168.40.1:2888
        public InetSocketAddress addr;
        // 参与选举的地址,以 zk1 为例,即 192.168.40.1:3888
        public InetSocketAddress electionAddr;
        public long id;
        public LearnerType type = LearnerType.PARTICIPANT;
    }

    分别定位到了使用这两个端口的代码。

    连接选举地址的代码:

    // void org.apache.zookeeper.server.quorum.QuorumCnxManager.connectOne(long sid)
    synchronized void connectOne(long sid){
        if (senderWorkerMap.get(sid) == null){
            InetSocketAddress electionAddr;
            if (self.quorumPeers.containsKey(sid)) {
                electionAddr = self.quorumPeers.get(sid).electionAddr;
            } else {
                LOG.warn("Invalid server id: " + sid);
                return;
            }
            try {
    
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Opening channel to server " + sid);
                }
                Socket sock = new Socket();
                setSockOpts(sock);
                sock.connect(self.getView().get(sid).electionAddr, cnxTO);
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Connected to server " + sid);
                }
                initiateConnection(sock, sid);
            } catch (UnresolvedAddressException e) {
                // Sun doesn't include the address that causes this
                // exception to be thrown, also UAE cannot be wrapped cleanly
                // so we log the exception in order to capture this critical
                // detail.
                LOG.warn("Cannot open channel to " + sid
                        + " at election address " + electionAddr, e);
                throw e;
            } catch (IOException e) {
                LOG.warn("Cannot open channel to " + sid
                        + " at election address " + electionAddr,
                        e);
            }
        } else {
            LOG.debug("There is a connection already for server " + sid);
        }
    }

    连接 leader 的代码:

    // void org.apache.zookeeper.server.quorum.Learner.connectToLeader(InetSocketAddress addr) throws IOException, ConnectException, InterruptedException
    protected void connectToLeader(InetSocketAddress addr) 
    throws IOException, ConnectException, InterruptedException {
        sock = new Socket();        
        sock.setSoTimeout(self.tickTime * self.initLimit);
        for (int tries = 0; tries < 5; tries++) {
            try {
                sock.connect(addr, self.tickTime * self.syncLimit);
                sock.setTcpNoDelay(nodelay);
                break;
            } catch (IOException e) {
                if (tries == 4) {
                    LOG.error("Unexpected exception",e);
                    throw e;
                } else {
                    LOG.warn("Unexpected exception, tries="+tries+
                            ", connecting to " + addr,e);
                    sock = new Socket();
                    sock.setSoTimeout(self.tickTime * self.initLimit);
                }
            }
            Thread.sleep(1000);
        }
        leaderIs = BinaryInputArchive.getArchive(new BufferedInputStream(
                sock.getInputStream()));
        bufferedOutput = new BufferedOutputStream(sock.getOutputStream());
        leaderOs = BinaryOutputArchive.getArchive(bufferedOutput);
    }   

    当前 zk 监听选举端口的代码:

    // void org.apache.zookeeper.server.quorum.QuorumCnxManager.Listener.run()
    public void run() {
        int numRetries = 0;
        InetSocketAddress addr;
        while((!shutdown) && (numRetries < 3)){
            try {
                ss = new ServerSocket();
                ss.setReuseAddress(true);
                if (self.getQuorumListenOnAllIPs()) {
                    int port = self.quorumPeers.get(self.getId()).electionAddr.getPort();
                    addr = new InetSocketAddress(port);
                } else {
                    addr = self.quorumPeers.get(self.getId()).electionAddr;
                }
                LOG.info("My election bind port: " + addr.toString());
                setName(self.quorumPeers.get(self.getId()).electionAddr
                        .toString());
                ss.bind(addr);
                while (!shutdown) {
                    Socket client = ss.accept();
                    setSockOpts(client);
                    LOG.info("Received connection request "
                            + client.getRemoteSocketAddress());
                    receiveConnection(client);
                    numRetries = 0;
                }
            } catch (IOException e) {
                LOG.error("Exception while listening", e);
                numRetries++;
                try {
                    ss.close();
                    Thread.sleep(1000);
                } catch (IOException ie) {
                    LOG.error("Error closing server socket", ie);
                } catch (InterruptedException ie) {
                    LOG.error("Interrupted while sleeping. " +
                              "Ignoring exception", ie);
                }
            }
        }
        LOG.info("Leaving listener");
        if (!shutdown) {
            LOG.error("As I'm leaving the listener thread, "
                    + "I won't be able to participate in leader "
                    + "election any longer: "
                    + self.quorumPeers.get(self.getId()).electionAddr);
        }
    }

    当前 zk 成为 leader 后,监听端口的代码:

    Leader(QuorumPeer self,LeaderZooKeeperServer zk) throws IOException {
        this.self = self;
        try {
            if (self.getQuorumListenOnAllIPs()) {
                ss = new ServerSocket(self.getQuorumAddress().getPort());
            } else {
                ss = new ServerSocket();
            }
            ss.setReuseAddress(true);
            if (!self.getQuorumListenOnAllIPs()) {
                ss.bind(self.getQuorumAddress());
            }
        } catch (BindException e) {
            if (self.getQuorumListenOnAllIPs()) {
                LOG.error("Couldn't bind to port " + self.getQuorumAddress().getPort(), e);
            } else {
                LOG.error("Couldn't bind to " + self.getQuorumAddress(), e);
            }
            throw e;
        }
        this.zk=zk;
    }
  • 相关阅读:
    Python Day 29 socket、scoket套接字分类、基于TCP的socket、常见错误
    Python Day 28 网络编程、OSI七层模型、三次握手和四次挥手
    Python Day 27 元类、__inti__方法、__new__方法、__call__方法、单例模式、exec与eval区别、异常处理语法
    get,post区别
    Restful API
    tcp 3次握手四次挥手
    mongodb数据库常用操作的整理
    python装饰器
    python中的*args和** kwargs区别
    Vue插件
  • 原文地址:https://www.cnblogs.com/allenwas3/p/9460347.html
Copyright © 2020-2023  润新知