use of services.moleculer.util.FastBuildTree in project moleculer-java by moleculer-java.
the class TcpTransporter method sendGossipRequest.
/**
* Create and send a Gossip request packet.
*/
protected Tree sendGossipRequest() {
try {
// Update CPU
NodeDescriptor descriptor = getDescriptor();
int cpu = monitor.getTotalCpuPercent();
descriptor.writeLock.lock();
try {
descriptor.updateCpu(cpu);
} finally {
descriptor.writeLock.unlock();
}
// Are we alone?
if (nodes.isEmpty()) {
return null;
}
// Add "online" and "offline" blocks
Collection<NodeDescriptor> descriptors = nodes.values();
int size = nodes.size() + 32;
FastBuildTree online = new FastBuildTree(size);
FastBuildTree offline = new FastBuildTree(size);
// Add current node
descriptor.readLock.lock();
try {
ArrayList<Object> array = new ArrayList<>(3);
array.add(descriptor.seq);
array.add(descriptor.cpuSeq);
array.add(descriptor.cpu);
online.putUnsafe(nodeID, array);
} finally {
descriptor.readLock.unlock();
}
// Separate online and offline nodes
String[] liveEndpoints = new String[size];
String[] unreachableEndpoints = new String[size];
int liveEndpointCount = 0;
int unreachableEndpointCount = 0;
// Loop on registered nodes
for (NodeDescriptor node : descriptors) {
node.readLock.lock();
try {
if (node.offlineSince > 0) {
// Offline
if (unreachableEndpointCount < unreachableEndpoints.length) {
unreachableEndpoints[unreachableEndpointCount++] = node.nodeID;
}
if (node.seq > 0) {
offline.put(node.nodeID, node.seq);
}
} else {
if (!node.local) {
// Online
if (liveEndpointCount < liveEndpoints.length) {
liveEndpoints[liveEndpointCount++] = node.nodeID;
}
if (node.seq > 0) {
ArrayList<Object> array = new ArrayList<>(3);
array.add(node.seq);
array.add(node.cpuSeq);
array.add(node.cpu);
online.putUnsafe(node.nodeID, array);
}
}
}
} finally {
node.readLock.unlock();
}
}
// Create gossip request
FastBuildTree root = new FastBuildTree(4);
root.putUnsafe("ver", ServiceBroker.PROTOCOL_VERSION);
root.putUnsafe("sender", nodeID);
root.putUnsafe("online", online.asObject());
if (!offline.isEmpty()) {
root.putUnsafe("offline", offline.asObject());
}
// Serialize gossip packet (JSON, MessagePack, etc.)
byte[] packet = serialize(PACKET_GOSSIP_REQ_ID, root);
// Do gossiping with a live endpoint
if (liveEndpointCount > 0) {
sendGossipToRandomEndpoint(liveEndpoints, liveEndpointCount, packet, root);
}
// Do gossiping with a unreachable endpoint
if (unreachableEndpointCount > 0) {
// 10 nodes:
// 1 offline / (9 online + 1) = 0.10
// 3 offline / (7 online + 1) = 0.37
// 5 offline / (5 online + 1) = 0.83
// 9 offline / (1 online + 1) = 4.50
double ratio = (double) unreachableEndpointCount / ((double) liveEndpointCount + 1);
// Random number between 0.0 and 1.0
double random = rnd.nextDouble();
if (random < ratio) {
sendGossipToRandomEndpoint(unreachableEndpoints, unreachableEndpointCount, packet, root);
}
}
// For unit testing
return root;
} catch (Exception cause) {
logger.error("Unable to send gossip message to peer!", cause);
}
return null;
}
use of services.moleculer.util.FastBuildTree in project moleculer-java by moleculer-java.
the class DefaultServiceRegistry method throwableToTree.
// --- CONVERT THROWABLE TO RESPONSE MESSAGE ---
protected Tree throwableToTree(String id, String sender, Throwable error) {
FastBuildTree msg = new FastBuildTree(6);
msg.putUnsafe("id", id);
msg.putUnsafe("ver", ServiceBroker.PROTOCOL_VERSION);
msg.putUnsafe("sender", sender);
msg.putUnsafe("success", false);
msg.putUnsafe("data", null);
if (error != null) {
// Add message
FastBuildTree errorMap = new FastBuildTree(2);
msg.putUnsafe("error", errorMap);
errorMap.putUnsafe("message", error.getMessage());
// Add trace
StringWriter sw = new StringWriter(128);
PrintWriter pw = new PrintWriter(sw);
error.printStackTrace(pw);
errorMap.putUnsafe("trace", sw.toString());
}
return msg;
}
use of services.moleculer.util.FastBuildTree in project moleculer-java by moleculer-java.
the class DefaultServiceRegistry method receiveRequest.
// --- RECEIVE REQUEST FROM REMOTE SERVICE ---
@Override
public void receiveRequest(Tree message) {
// Verify protocol version
if (checkVersion) {
String ver = message.get("ver", "unknown");
if (!ServiceBroker.PROTOCOL_VERSION.equals(ver)) {
logger.warn("Invalid protocol version (" + ver + ")!");
return;
}
}
// Get action property
String action = message.get("action", (String) null);
if (action == null || action.isEmpty()) {
logger.warn("Missing \"action\" property!");
return;
}
// Get strategy (action endpoint array) by action name
Strategy<ActionEndpoint> strategy;
readLock.lock();
try {
strategy = strategies.get(action);
} finally {
readLock.unlock();
}
if (strategy == null) {
logger.warn("Invalid action name (" + action + ")!");
return;
}
// Get local action endpoint (with cache handling)
ActionEndpoint endpoint = strategy.getEndpoint(nodeID);
if (endpoint == null) {
logger.warn("Not a local action (" + action + ")!");
return;
}
// Get request's unique ID
String id = message.get("id", (String) null);
if (id == null || id.isEmpty()) {
logger.warn("Missing \"id\" property!");
return;
}
// Get sender's nodeID
String sender = message.get("sender", (String) null);
if (sender == null || sender.isEmpty()) {
logger.warn("Missing \"sender\" property!");
return;
}
// Create CallOptions
int timeout = message.get("timeout", 0);
Tree params = message.get("params");
// TODO Process other properties:
// Tree meta = message.get("meta");
// int level = message.get("level", 1);
// boolean metrics = message.get("metrics", false);
// String parentID = message.get("parentID", (String) null);
// String requestID = message.get("requestID", (String) null);
CallOptions.Options opts = CallOptions.nodeID(nodeID).timeout(timeout);
Context ctx = contextFactory.create(action, params, opts, null);
// Invoke action
try {
new Promise(endpoint.handler(ctx)).then(data -> {
// Send response
FastBuildTree msg = new FastBuildTree(5);
msg.putUnsafe("sender", nodeID);
msg.putUnsafe("id", id);
msg.putUnsafe("ver", ServiceBroker.PROTOCOL_VERSION);
msg.putUnsafe("success", true);
msg.putUnsafe("data", data);
transporter.publish(Transporter.PACKET_RESPONSE, sender, msg);
}).catchError(error -> {
// Send error
transporter.publish(Transporter.PACKET_RESPONSE, sender, throwableToTree(id, sender, error));
});
} catch (Throwable error) {
// Send error
transporter.publish(Transporter.PACKET_RESPONSE, sender, throwableToTree(id, sender, error));
}
}
use of services.moleculer.util.FastBuildTree in project moleculer-java by moleculer-java.
the class Transporter method sendDisconnectPacket.
protected void sendDisconnectPacket() {
FastBuildTree msg = new FastBuildTree(1);
msg.putUnsafe("sender", nodeID);
publish(disconnectChannel, msg);
}
use of services.moleculer.util.FastBuildTree in project moleculer-java by moleculer-java.
the class Transporter method sendHeartbeatPacket.
protected void sendHeartbeatPacket() {
FastBuildTree msg = new FastBuildTree(3);
msg.putUnsafe("ver", PROTOCOL_VERSION);
msg.putUnsafe("sender", nodeID);
msg.putUnsafe("cpu", monitor.getTotalCpuPercent());
publish(heartbeatChannel, msg);
}
Aggregations