public NodePo(Node node) { this.id = node.getId(); this.ip = node.getIp(); this.port = node.getPort(); this.lastTime = node.getLastTime(); this.lastFailTime = node.getLastFailTime(); this.failCount = node.getFailCount(); this.connectStatus = NodeConnectStatusEnum.UNCONNECT; this.status = node.getStatus(); }
public static Node toNode(NodePo po) { Node node = new Node(); node.setId(po.getId()); node.setIp(po.getIp()); node.setPort(po.getPort()); node.setFailCount(po.getFailCount()); node.setLastTime(po.getLastTime()); node.setLastFailTime(po.getLastFailTime()); node.setStatus(po.getStatus()); node.setConnectStatus(po.getConnectStatus()); return node; } }
private boolean checkIsSurvive(Node node) { if (node.getChannel() == null || node.getStatus() != NodeStatusEnum.CONNECTABLE || node.getConnectStatus() != NodeConnectStatusEnum.AVAILABLE) { if(node.getChannel() != null) { node.getChannel().close(); } return false; } return true; } }
/** * 节点连接失败 * * @param node */ public void nodeConnectFail(Node node) { node.setStatus(NodeStatusEnum.UNAVAILABLE); node.setConnectStatus(NodeConnectStatusEnum.FAIL); node.setFailCount(node.getFailCount() + 1); node.setLastProbeTime(TimeService.currentTimeMillis()); }
public void nodeConnectDisconnect(Node node) { if (node.getChannel() != null) { node.setChannel(null); } //连接断开后,判断是否是为连接成功,还是连接成功后断开 if (node.getConnectStatus() == NodeConnectStatusEnum.CONNECTED || node.getConnectStatus() == NodeConnectStatusEnum.AVAILABLE) { node.setFailCount(0); node.setConnectStatus(NodeConnectStatusEnum.DISCONNECT); nodesContainer.getDisconnectNodes().put(node.getId(), node); nodesContainer.getConnectedNodes().remove(node.getId()); // Log.info("node {} disconnect !", node.getId()); } else { // 如果是未连接成功,标记为连接失败,失败次数+1,记录当前失败时间,供下次尝试连接使用 nodeConnectFail(node); nodesContainer.getCanConnectNodes().remove(node.getId()); nodesContainer.getFailNodes().put(node.getId(), node); } }
private void probeNodes(Map<String, Node> verifyNodes, Map<String, Node> canConnectNodes) { for (Map.Entry<String, Node> nodeEntry : verifyNodes.entrySet()) { Node node = nodeEntry.getValue(); boolean needProbeNow = checkNeedProbeNow(node, verifyNodes); if (!needProbeNow) { continue; } int status = doProbe(node); if (status == PROBE_STATUS_IGNORE/* && !node.isSeedNode()*/) { continue; } verifyNodes.remove(node.getId()); if (status == PROBE_STATUS_SUCCESS) { node.setConnectStatus(NodeConnectStatusEnum.UNCONNECT); node.setStatus(NodeStatusEnum.CONNECTABLE); node.setFailCount(0); canConnectNodes.put(node.getId(), node); if (node.getLastProbeTime() == 0L) { // 当lastProbeTime为0时,代表第一次探测且成功,只有在第一次探测成功时情况,才转发节点信息 doShare(node); } } else if (status == PROBE_STATUS_FAIL) { nodeManager.nodeConnectFail(node); nodeManager.getNodesContainer().getFailNodes().put(node.getId(), node); } node.setLastProbeTime(TimeService.currentTimeMillis()); } }
public boolean nodeConnectIn(String ip, int port, SocketChannel channel) { if (!canConnectIn(ip, port)) { return false; } Node node = new Node(ip, port, Node.IN); node.setConnectStatus(NodeConnectStatusEnum.CONNECTED); node.setChannel(channel); cacheNode(node, channel); nodesContainer.getConnectedNodes().put(node.getId(), node); nodesContainer.markCanuseNodeByIp(ip, NodeStatusEnum.AVAILABLE); //监听被动连接的断开 node.setDisconnectListener(() -> { Log.info("------------in node disconnect:" + node.getId()); nodesContainer.getConnectedNodes().remove(node.getId()); nodesContainer.markCanuseNodeByIp(ip, NodeStatusEnum.CONNECTABLE); }); sendHandshakeMessage(node, NetworkConstant.HANDSHAKE_SEVER_TYPE); return true; }
private boolean connectionNode(Node node) { node.setConnectStatus(NodeConnectStatusEnum.CONNECTING); node.setRegisterListener(() -> Log.debug("new node {} try connecting!", node.getId())); node.setConnectedListener(() -> nodeManager.nodeConnectSuccess(node)); node.setDisconnectListener(() -> { Log.info("-----------out node disconnect:" + node.getId()); nodeManager.nodeConnectDisconnect(node); }); return connectionManager.connection(node); }
@Override public NetworkEventResult process(BaseMessage message, Node node) { VersionMessage versionMessage = (VersionMessage) message; NetworkMessageBody body = versionMessage.getMsgBody(); // Log.info("receive a version message : {}", body); if (body.getBestBlockHeight() < 0) { // node.setStatus(Node.BAD); nodeManager.removeNode(node.getId()); return null; } node.setBestBlockHeight(body.getBestBlockHeight()); node.setBestBlockHash(body.getBestBlockHash()); node.setTimeOffset((TimeService.currentTimeMillis() - node.getLastTime()) / 2); return null; } }
private boolean checkNeedProbeNow(Node node, Map<String, Node> verifyNodes) { // 探测间隔时间,根据失败的次数来决定,探测失败次数为failCount,探测间隔为probeInterval,定义分别如下: // failCount : 0-10 ,probeInterval = 60s // failCount : 11-20 ,probeInterval = 300s // failCount : 21-30 ,probeInterval = 600s // failCount : 31-50 ,probeInterval = 1800s // failCount : 51-100 ,probeInterval = 3600s // 当一个节点失败次数大于100时,将从节点列表中移除,除非再次收到该节点的分享,否则永远丢弃该节点 long probeInterval; int failCount = node.getFailCount(); if (failCount <= 10) { probeInterval = 60 * 1000L; } else if (failCount <= 20) { probeInterval = 300 * 1000L; } else if (failCount <= 30) { probeInterval = 600 * 1000L; } else if (failCount <= 50) { probeInterval = 1800 * 1000L; } else if (failCount <= 100) { probeInterval = 3600 * 1000L; } else { verifyNodes.remove(node.getId()); return false; } return TimeService.currentTimeMillis() - node.getLastProbeTime() > probeInterval; }
public void nodeConnectSuccess(Node node) { nodesContainer.getConnectedNodes().put(node.getId(), node); nodesContainer.getCanConnectNodes().remove(node.getId()); node.setConnectStatus(NodeConnectStatusEnum.CONNECTED); // Log.info("node {} connect success !", node.getId()); sendHandshakeMessage(node, NetworkConstant.HANDSHAKE_CLIENT_TYPE); }
public boolean addNeedCheckNode(Node newNode) { String nodeId = newNode.getId(); newNode.setLastProbeTime(0L); uncheckNodes.put(nodeId, newNode); newNode.setStatus(NodeStatusEnum.UNCHECK);
private int doProbe(Node node) { if(node == null) { return PROBE_STATUS_FAIL; } CompletableFuture<Integer> future = new CompletableFuture<>(); node.setConnectedListener(() -> { node.setConnectStatus(NodeConnectStatusEnum.CONNECTED); node.getChannel().close(); }); node.setDisconnectListener(() -> { node.setChannel(null); if (node.getConnectStatus() == NodeConnectStatusEnum.CONNECTED) { future.complete(PROBE_STATUS_SUCCESS); } else if (nodeManager.getAvailableNodesCount() == 0) { future.complete(PROBE_STATUS_IGNORE); } else { future.complete(PROBE_STATUS_FAIL); } }); boolean result = connectionManager.connection(node); if (!result) { return PROBE_STATUS_FAIL; } try { return future.get(); } catch (Exception e) { Log.error(e); return PROBE_STATUS_IGNORE; } }
public boolean start() { try { ChannelFuture future = boot.connect(node.getIp(), node.getPort()); future.await(); return future.isSuccess(); } catch (Exception e) { Log.error("{}", e); if (node.getChannel() != null) { node.getChannel().close(); } return false; } }
private void shareMyServer() { String externalIp = getMyExtranetIp(); if (externalIp == null) { return; } Log.info("my external ip is {}" , externalIp); networkParam.getLocalIps().add(externalIp); Node myNode = new Node(externalIp, networkParam.getPort(), Node.OUT); myNode.setConnectedListener(() -> { myNode.getChannel().close(); doShare(externalIp); }); myNode.setDisconnectListener(() -> myNode.setChannel(null)); connectionManager.connection(myNode); }
@Override public NetworkEventResult process(BaseMessage message, Node node) { GetVersionMessage getVersionMessage = (GetVersionMessage) message; NetworkMessageBody body = getVersionMessage.getMsgBody(); if (body.getBestBlockHeight() < 0) { // node.setStatus(Node.BAD); nodeManager.removeNode(node.getId()); return null; } node.setBestBlockHeight(body.getBestBlockHeight()); node.setBestBlockHash(body.getBestBlockHash()); NetworkMessageBody myVersionBody = new NetworkMessageBody(NetworkConstant.HANDSHAKE_CLIENT_TYPE, networkParam.getPort(), NulsContext.getInstance().getBestHeight(), NulsContext.getInstance().getBestBlock().getHeader().getHash()); return new NetworkEventResult(true, new VersionMessage(myVersionBody)); }
@Override public NetworkEventResult process(BaseMessage message, Node node) { HandshakeMessage handshakeMessage = (HandshakeMessage) message; NetworkMessageBody body = handshakeMessage.getMsgBody(); // Log.info("receive message from node {}, message : {}", node.getId(), body); node.setBestBlockHash(body.getBestBlockHash()); node.setBestBlockHeight(body.getBestBlockHeight()); node.setExternalIp(body.getNodeIp()); node.setRemoteVersion(body.getVersion()); node.setConnectStatus(NodeConnectStatusEnum.AVAILABLE); return null; } }