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();
}
}
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;
}
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;
}
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);
}
});
}
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;
}
Aggregations