Search in sources :

Example 1 with NodeDescriptor

use of services.moleculer.transporter.tcp.NodeDescriptor in project moleculer-java by moleculer-java.

the class Transporter method isOnline.

// --- IS NODE ONLINE? ---
public boolean isOnline(String nodeID) {
    if (this.nodeID.equals(nodeID)) {
        return true;
    }
    NodeDescriptor node = nodes.get(nodeID);
    if (node == null) {
        return false;
    }
    node.readLock.lock();
    try {
        return node.offlineSince == 0 && node.seq > 0;
    } finally {
        node.readLock.unlock();
    }
}
Also used : NodeDescriptor(services.moleculer.transporter.tcp.NodeDescriptor)

Example 2 with NodeDescriptor

use of services.moleculer.transporter.tcp.NodeDescriptor in project moleculer-java by moleculer-java.

the class Transporter method getAddress.

// --- GET SOCKET ADDRESS OF A NODE ---
public RemoteAddress getAddress(String nodeID) {
    NodeDescriptor node = nodes.get(nodeID);
    if (node == null) {
        return null;
    }
    RemoteAddress address;
    node.readLock.lock();
    try {
        address = new RemoteAddress(node.host, node.port);
    } finally {
        node.readLock.unlock();
    }
    return address;
}
Also used : RemoteAddress(services.moleculer.transporter.tcp.RemoteAddress) NodeDescriptor(services.moleculer.transporter.tcp.NodeDescriptor)

Example 3 with NodeDescriptor

use of services.moleculer.transporter.tcp.NodeDescriptor in project moleculer-java by moleculer-java.

the class Transporter method getDescriptor.

// --- GET DESCRIPTOR OF A NODE ---
public Tree getDescriptor(String nodeID) {
    if (this.nodeID.equals(nodeID)) {
        return registry.getDescriptor();
    }
    NodeDescriptor node = nodes.get(nodeID);
    if (node == null) {
        return null;
    }
    Tree info = null;
    node.readLock.lock();
    try {
        if (node.info != null) {
            info = node.info.clone();
        }
    } finally {
        node.readLock.unlock();
    }
    return info;
}
Also used : NodeDescriptor(services.moleculer.transporter.tcp.NodeDescriptor) FastBuildTree(services.moleculer.util.FastBuildTree) Tree(io.datatree.Tree)

Example 4 with NodeDescriptor

use of services.moleculer.transporter.tcp.NodeDescriptor in project moleculer-java by moleculer-java.

the class Transporter method received.

// --- PROCESS INCOMING MESSAGE ---
protected void received(String channel, byte[] message) {
    executor.execute(() -> {
        // Parse message
        Tree data;
        try {
            data = serializer.read(message);
        } catch (Exception cause) {
            logger.warn("Unable to parse incoming message!", cause);
            return;
        }
        // Debug
        if (debug) {
            logger.info("Message received from channel \"" + channel + "\":\r\n" + data);
        }
        // Send message to proper component
        try {
            // Get "sender" property
            String sender = data.get("sender", "");
            if (sender == null || sender.isEmpty()) {
                logger.warn("Missing \"sender\" property:\r\n" + data);
                return;
            }
            if (sender.equals(nodeID)) {
                // It's our message
                return;
            }
            // Incoming response
            if (channel.equals(responseChannel)) {
                registry.receiveResponse(data);
                return;
            }
            // Incoming event
            if (channel.equals(eventChannel)) {
                eventbus.receiveEvent(data);
                return;
            }
            // Incoming request
            if (channel.equals(requestChannel)) {
                registry.receiveRequest(data);
                return;
            }
            // HeartBeat packet
            if (channel.endsWith(heartbeatChannel)) {
                // Get node container
                NodeDescriptor node = nodes.get(sender);
                if (node == null) {
                    // Unknown node -> send discover packet
                    sendDiscoverPacket(channel(PACKET_DISCOVER, sender));
                    return;
                }
                int cpu = data.get("cpu", 0);
                // Update CPU info
                node.writeLock.lock();
                try {
                    node.updateCpu(cpu);
                } finally {
                    node.writeLock.unlock();
                }
                return;
            }
            // Info packet
            if (channel.equals(infoChannel) || channel.equals(infoBroadcastChannel)) {
                // Register services and listeners
                data.put("seq", System.currentTimeMillis());
                data.put("port", 1);
                updateNodeInfo(sender, data);
                return;
            }
            // Discover packet
            if (channel.equals(discoverChannel) || channel.equals(discoverBroadcastChannel)) {
                // Send node desriptor to the sender
                sendInfoPacket(channel(PACKET_INFO, sender));
                return;
            }
            // Ping packet
            if (channel.equals(pingChannel)) {
                sendPongPacket(sender, data);
                return;
            }
            // Disconnect packet
            if (channel.equals(disconnectChannel)) {
                // Switch to offline
                NodeDescriptor node = nodes.get(sender);
                if (node == null) {
                    return;
                }
                boolean disconnected = false;
                node.writeLock.lock();
                try {
                    if (node.markAsOffline()) {
                        // Remove remote actions and listeners
                        registry.removeActions(sender);
                        eventbus.removeListeners(sender);
                        disconnected = true;
                    }
                } finally {
                    node.writeLock.unlock();
                }
                if (node != null && disconnected) {
                    // Notify listeners (not unexpected disconnection)
                    logger.info("Node \"" + sender + "\" disconnected.");
                    broadcastNodeDisconnected(node.info, false);
                }
                return;
            }
        } catch (Exception cause) {
            logger.warn("Unable to process incoming message!", cause);
        }
    });
}
Also used : NodeDescriptor(services.moleculer.transporter.tcp.NodeDescriptor) FastBuildTree(services.moleculer.util.FastBuildTree) Tree(io.datatree.Tree)

Example 5 with NodeDescriptor

use of services.moleculer.transporter.tcp.NodeDescriptor in project moleculer-java by moleculer-java.

the class TcpTransporter method processGossipRequest.

// --- GOSSIP REQUEST MESSAGE RECEIVED ---
protected Tree processGossipRequest(Tree data) throws Exception {
    // Debug
    String sender = data.get("sender", (String) null);
    if (debug) {
        logger.info("Gossip request received from \"" + sender + "\" node:\r\n" + data);
    }
    // Add "online" and "offline" response blocks
    LinkedList<NodeDescriptor> allNodes = new LinkedList<>(nodes.values());
    NodeDescriptor descriptor = getDescriptor();
    allNodes.add(descriptor);
    int size = allNodes.size() + 1;
    FastBuildTree onlineRsp = new FastBuildTree(size);
    FastBuildTree offlineRsp = new FastBuildTree(size);
    // Online / offline nodes in request
    Tree onlineReq = data.get("online");
    Tree offlineReq = data.get("offline");
    // Loop in nodes
    LinkedList<NodeDescriptor> disconnectedNodes = new LinkedList<>();
    for (NodeDescriptor node : allNodes) {
        node.writeLock.lock();
        try {
            Tree online = onlineReq == null ? null : onlineReq.get(node.nodeID);
            Tree offline = offlineReq == null ? null : offlineReq.get(node.nodeID);
            // Online or offline sequence number
            long seq = 0;
            // CPU data
            long cpuSeq = 0;
            int cpu = 0;
            if (offline != null) {
                if (!offline.isPrimitive()) {
                    logger.warn("Invalid \"offline\" block: " + offline.toString(false));
                    continue;
                }
                seq = offline.asLong();
            } else if (online != null) {
                if (!online.isEnumeration() || online.size() != 3) {
                    logger.warn("Invalid \"online\" block: " + online.toString(false));
                    continue;
                }
                seq = online.get(0).asLong();
                cpuSeq = online.get(1).asLong();
                cpu = online.get(2).asInteger();
            }
            if ((seq == 0 || seq < node.seq) && node.seq > 0) {
                // We have newer info or requester doesn't know it
                if (node.offlineSince == 0) {
                    if (!node.info.isEmpty()) {
                        if ((cpuSeq == 0 || cpuSeq < node.cpuSeq) && node.cpuSeq > 0) {
                            ArrayList<Object> array = new ArrayList<>(3);
                            array.add(node.info.asObject());
                            array.add(node.cpuSeq);
                            array.add(node.cpu);
                            onlineRsp.putUnsafe(node.nodeID, array);
                        } else {
                            onlineRsp.putUnsafe(node.nodeID, Collections.singletonList(node.info.asObject()));
                        }
                    }
                } else {
                    offlineRsp.putUnsafe(node.nodeID, node.seq);
                }
            }
            if (offline != null) {
                // Requester said it is OFFLINE
                if (node.offlineSince > 0) {
                    // We also knew it as offline
                    node.markAsOffline(seq);
                    continue;
                }
                if (!node.local) {
                    if (node.offlineSince == 0) {
                        // We know it is online, so we change it to offline
                        if (node.markAsOffline(seq)) {
                            // Remove remote actions and listeners
                            registry.removeActions(node.nodeID);
                            eventbus.removeListeners(node.nodeID);
                            writer.close(node.nodeID);
                            disconnectedNodes.add(node);
                        } else if (seq == node.seq) {
                            // We send back that this node is online
                            node.seq = seq + 1;
                            node.info.put("seq", node.seq);
                            if (cpuSeq < node.cpuSeq && node.cpuSeq > 0) {
                                ArrayList<Object> array = new ArrayList<>(3);
                                array.add(node.info.asObject());
                                array.add(node.cpuSeq);
                                array.add(node.cpu);
                                onlineRsp.putUnsafe(node.nodeID, array);
                            } else {
                                onlineRsp.putUnsafe(node.nodeID, Collections.singletonList(node.info.asObject()));
                            }
                        }
                    }
                    continue;
                }
            } else if (online != null) {
                // Requester said it is ONLINE
                if (node.offlineSince == 0) {
                    if (cpuSeq > node.cpuSeq) {
                        // We update our CPU info
                        node.updateCpu(cpuSeq, cpu);
                    } else if (cpuSeq < node.cpuSeq && node.cpuSeq > 0) {
                        // We have newer CPU value, send back
                        ArrayList<Object> array = new ArrayList<>(2);
                        array.add(node.cpuSeq);
                        array.add(node.cpu);
                        onlineRsp.putUnsafe(node.nodeID, array);
                    }
                } else {
                    // request it and we'll receive its INFO
                    continue;
                }
            }
        } finally {
            node.writeLock.unlock();
        }
    }
    // Create gossip response
    FastBuildTree root = new FastBuildTree(4);
    root.putUnsafe("ver", ServiceBroker.PROTOCOL_VERSION);
    root.putUnsafe("sender", nodeID);
    // Remove empty blocks
    boolean emptyOnlineBlock = onlineRsp.isEmpty();
    boolean emptyOfflineBlock = offlineRsp.isEmpty();
    if (emptyOnlineBlock && emptyOfflineBlock) {
        // Message is empty
        return root;
    }
    if (!emptyOnlineBlock) {
        root.putUnsafe("online", onlineRsp.asObject());
    }
    if (!emptyOfflineBlock) {
        root.putUnsafe("offline", offlineRsp.asObject());
    }
    // Debug
    if (debug) {
        logger.info("Gossip response submitting to \"" + sender + "\" node:\r\n" + root);
    }
    // Serialize response
    byte[] packet = serialize(PACKET_GOSSIP_RSP_ID, root);
    // Send response
    writer.send(sender, packet);
    // Notify listeners (unexpected disconnection)
    for (NodeDescriptor node : disconnectedNodes) {
        logger.info("Node \"" + node.nodeID + "\" disconnected.");
        broadcastNodeDisconnected(node.info, true);
    }
    // For unit testing
    return root;
}
Also used : FastBuildTree(services.moleculer.util.FastBuildTree) NodeDescriptor(services.moleculer.transporter.tcp.NodeDescriptor) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) CommonUtils.readTree(services.moleculer.util.CommonUtils.readTree) FastBuildTree(services.moleculer.util.FastBuildTree) Tree(io.datatree.Tree)

Aggregations

NodeDescriptor (services.moleculer.transporter.tcp.NodeDescriptor)17 Tree (io.datatree.Tree)12 FastBuildTree (services.moleculer.util.FastBuildTree)9 CommonUtils.readTree (services.moleculer.util.CommonUtils.readTree)5 ArrayList (java.util.ArrayList)2 LinkedList (java.util.LinkedList)2 Color (java.awt.Color)1 PrintWriter (java.io.PrintWriter)1 StringWriter (java.io.StringWriter)1 HashMap (java.util.HashMap)1 ExecutorService (java.util.concurrent.ExecutorService)1 ScheduledExecutorService (java.util.concurrent.ScheduledExecutorService)1 Test (org.junit.Test)1 ServiceBroker (services.moleculer.ServiceBroker)1 ServiceBrokerConfig (services.moleculer.config.ServiceBrokerConfig)1 RemoteAddress (services.moleculer.transporter.tcp.RemoteAddress)1 TcpReader (services.moleculer.transporter.tcp.TcpReader)1 TcpWriter (services.moleculer.transporter.tcp.TcpWriter)1 UDPLocator (services.moleculer.transporter.tcp.UDPLocator)1