use of services.moleculer.transporter.tcp.NodeDescriptor in project moleculer-java by moleculer-java.
the class ClusterTest method run.
public void run() {
System.out.println("START");
try {
// Load Sigar DLLs
String nativeDir = "./native";
System.setProperty("java.library.path", nativeDir);
ExecutorService executor = Executors.newFixedThreadPool(Math.min(NODES, 100));
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(Math.min(NODES, 100));
String[] urls = new String[NODES];
for (int i = 0; i < NODES; i++) {
int port = 6000 + i;
urls[i] = "tcp://127.0.0.1:" + port + "/node-" + i;
}
ServiceBroker[] brokers = new ServiceBroker[NODES];
for (int i = 0; i < NODES; i++) {
// urls
TcpTransporter transporter = new TcpTransporter();
transporter.setGossipPeriod(3);
transporter.setDebug(false);
transporter.setOfflineTimeout(0);
ServiceBrokerConfig settings = new ServiceBrokerConfig();
settings.setShutDownThreadPools(false);
settings.setExecutor(executor);
settings.setScheduler(scheduler);
settings.setTransporter(transporter);
settings.setNodeID("node-" + i);
ServiceBroker broker = new ServiceBroker(settings);
brokers[i] = broker;
}
for (int i = 0; i < NODES; i++) {
brokers[i].start();
System.out.println("node-" + i + " started.");
}
boolean turnOn = true;
HashMap<String, Long> maxSeqs = new HashMap<>();
ServiceBroker broker;
TcpTransporter transporter;
int counter = 0;
while (true) {
Thread.sleep(1000);
counter++;
if (counter % 70 == 0) {
if (turnOn) {
for (int n = 0; n < NODES / 3; n++) {
int i = rnd.nextInt(NODES);
broker = brokers[i];
transporter = (TcpTransporter) broker.getConfig().getTransporter();
if (transporter.writer == null) {
transporter.connect();
}
}
}
int i = rnd.nextInt(NODES);
broker = brokers[i];
transporter = (TcpTransporter) broker.getConfig().getTransporter();
if (transporter.writer != null) {
transporter.nodes.clear();
transporter.disconnect();
}
}
maxSeqs.clear();
for (int i = 0; i < NODES; i++) {
broker = brokers[i];
transporter = (TcpTransporter) broker.getConfig().getTransporter();
maxSeqs.put(broker.getNodeID(), transporter.getDescriptor().cpuSeq);
}
for (int i = 0; i < NODES; i++) {
broker = brokers[i];
transporter = (TcpTransporter) broker.getConfig().getTransporter();
for (int n = 0; n < NODES; n++) {
NodeDescriptor d = transporter.nodes.get("node-" + n);
boolean online = transporter.isOnline("node-" + n);
Color color;
Long seq = null;
if (online) {
if (d != null) {
long cpuSeq = d.cpuSeq;
long maxSeq = maxSeqs.get("node-" + n);
if (maxSeq > 0) {
if (maxSeq < cpuSeq) {
maxSeq = cpuSeq;
maxSeqs.put("node-" + n, maxSeq);
}
long c = Math.max(0, 255 - 20 * (maxSeq - cpuSeq));
color = new Color(0, (int) c, 0);
} else {
color = Color.WHITE;
}
seq = d.seq;
} else {
color = Color.YELLOW;
}
} else {
color = Color.RED;
if (d != null) {
seq = d.seq;
}
}
image.draw(n, i, color, seq);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("STOP");
System.exit(0);
}
use of services.moleculer.transporter.tcp.NodeDescriptor in project moleculer-java by moleculer-java.
the class TcpTransporterTest method createOnlineDescriptorWithoutInfo.
protected NodeDescriptor createOnlineDescriptorWithoutInfo(boolean local, String nodeID) {
Tree info = new Tree();
info.put("seq", 1);
info.put("port", 1);
info.put("hostname", nodeID);
return new NodeDescriptor(nodeID, true, local, info);
}
use of services.moleculer.transporter.tcp.NodeDescriptor in project moleculer-java by moleculer-java.
the class TcpTransporterTest method testProcessGossipRequest.
// --- GOSSIP REQUEST PROCESSING ---
@Test
public void testProcessGossipRequest() throws Exception {
// Add "node2" (hidden)
tr.nodes.put("node2", createOfflineDescriptor(false, "node2"));
// Simple request
Tree req = createGossipRequest("node3", 1, 2, 3);
Tree rsp = tr.processGossipRequest(req);
assertEquals(1, rsp.get("online").size());
assertNull(rsp.get("offline"));
assertEquals(1, rsp.get("online.node1").size());
assertNotNull(rsp.get("online.node1[0].hostname"));
assertTrue(rsp.get("online.node1[0].port", 0) > 0);
assertTrue(rsp.get("online.node1[0].seq", 0) > 0);
assertTrue(rsp.get("online.node1[0].services").size() > 0);
// Update local CPU
tr.getDescriptor().updateCpu(4);
rsp = tr.processGossipRequest(req);
assertEquals(3, rsp.get("online.node1").size());
assertEquals(1, rsp.get("online.node1[1]", 0));
assertEquals(4, rsp.get("online.node1[2]", 0));
tr.getDescriptor().updateCpu(5);
rsp = tr.processGossipRequest(req);
assertEquals(2, rsp.get("online.node1[1]", 0));
assertEquals(5, rsp.get("online.node1[2]", 0));
tr.getDescriptor().updateCpu(0);
rsp = tr.processGossipRequest(req);
assertEquals(3, rsp.get("online.node1[1]", 0));
assertEquals(0, rsp.get("online.node1[2]", 0));
// Add offline node
// Node4 -> offline & hidden
tr.registerAsNewNode("node3", "host3", 1003);
rsp = tr.processGossipRequest(req);
assertEquals(1, rsp.get("online").size());
assertNull(rsp.get("offline"));
assertEquals(3, rsp.get("online.node1").size());
// Node5 -> online
NodeDescriptor node4 = createOnlineDescriptorWithInfo(false, "node4");
node4.info.put("seq", "3");
node4.seq = 3;
tr.nodes.put("node4", node4);
rsp = tr.processGossipRequest(req);
assertEquals(2, rsp.get("online").size());
assertNull(rsp.get("offline"));
assertEquals(3, rsp.get("online.node1").size());
assertEquals(1, rsp.get("online.node4").size());
assertEquals(1, rsp.get("online.node4[0].port", 0));
assertEquals(3, rsp.get("online.node4[0].seq", 0));
assertEquals("node4", rsp.get("online.node4[0].hostname", "?"));
// Add "node4" to request (low seq)
req.get("online").putList("node4").add(1).add(1).add(0);
rsp = tr.processGossipRequest(req);
assertEquals(2, rsp.get("online").size());
assertNull(rsp.get("offline"));
assertEquals(3, rsp.get("online.node1").size());
assertEquals(3, rsp.get("online.node1[1]", 0));
assertEquals(0, rsp.get("online.node1[2]", 0));
// Add "node4" to request (correct seq)
req.get("online").get("node4").clear().add(3).add(1).add(0);
rsp = tr.processGossipRequest(req);
assertEquals(1, rsp.get("online").size());
assertEquals(3, rsp.get("online.node1").size());
// Add "node4" to request (high seq)
req.get("online").get("node4").clear().add(4).add(1).add(0);
rsp = tr.processGossipRequest(req);
assertEquals(1, rsp.get("online").size());
assertNull(rsp.get("offline"));
assertEquals(3, rsp.get("online.node1").size());
// Add "node4" to request (higher CPU seq)
req.get("online").get("node4").clear().add(3).add(2).add(1);
rsp = tr.processGossipRequest(req);
assertEquals(1, rsp.get("online").size());
assertEquals(1, tr.getCpuUsage("node4"));
// Add "node4" to request (lower CPU seq)
req.get("online").get("node4").clear().add(3).add(1).add(2);
rsp = tr.processGossipRequest(req);
assertEquals(2, rsp.get("online").size());
assertNull(rsp.get("offline"));
assertEquals(2, rsp.get("online.node4").size());
assertEquals(2, rsp.get("online.node4[0]", 0));
assertEquals(1, rsp.get("online.node4[1]", 0));
assertEquals(1, tr.getCpuUsage("node4"));
// Add "node4" to request (same CPU seq)
req.get("online").get("node4").clear().add(3).add(2).add(2);
rsp = tr.processGossipRequest(req);
assertEquals(1, rsp.get("online").size());
assertNull(rsp.get("offline"));
assertNull(rsp.get("online.node4"));
assertEquals(1, tr.getCpuUsage("node4"));
// Add "node4" to request (higher CPU seq)
req.get("online").get("node4").clear().add(3).add(3).add(5);
rsp = tr.processGossipRequest(req);
assertEquals(1, rsp.get("online").size());
assertNull(rsp.get("offline"));
assertNull(rsp.get("online.node4"));
assertEquals(5, tr.getCpuUsage("node4"));
// Add "node4" to request (lower CPU seq)
req.get("online").get("node4").clear().add(3).add(1).add(2);
rsp = tr.processGossipRequest(req);
assertEquals(2, rsp.get("online").size());
assertNull(rsp.get("offline"));
assertEquals(2, rsp.get("online.node4").size());
assertEquals(3, rsp.get("online.node4[0]", 0));
assertEquals(5, rsp.get("online.node4[1]", 0));
assertEquals(5, tr.getCpuUsage("node4"));
assertEquals(1, tr.getDescriptor().seq);
}
use of services.moleculer.transporter.tcp.NodeDescriptor in project moleculer-java by moleculer-java.
the class TcpTransporterTest method createOfflineDescriptor.
protected NodeDescriptor createOfflineDescriptor(boolean local, String nodeID) {
Tree info = new Tree();
info.put("seq", 0);
info.put("port", 1);
info.put("hostname", nodeID);
NodeDescriptor nd = new NodeDescriptor(nodeID, true, local, info);
nd.offlineSince = 1;
return nd;
}
use of services.moleculer.transporter.tcp.NodeDescriptor in project moleculer-java by moleculer-java.
the class TcpTransporter method unableToSend.
// --- CONNECTION ERROR ---
public void unableToSend(String nodeID, LinkedList<byte[]> packets, Throwable cause) {
if (nodeID != null) {
executor.execute(() -> {
// Debug
if (debug) {
logger.warn("Unable to send message to \"" + nodeID + "\".", cause);
}
// Mark endpoint as offline
NodeDescriptor node = nodes.get(nodeID);
boolean disconnected = false;
if (node != null) {
node.writeLock.lock();
try {
if (node != null && node.markAsOffline()) {
// Remove actions and listeners
registry.removeActions(nodeID);
eventbus.removeListeners(nodeID);
writer.close(node.nodeID);
disconnected = true;
}
} catch (Exception error) {
logger.warn("Unable to turn off node!", error);
} finally {
node.writeLock.unlock();
}
}
if (node != null && disconnected) {
// Notify listeners (unexpected disconnection)
logger.info("Node \"" + nodeID + "\" disconnected.");
broadcastNodeDisconnected(node.info, true);
}
// Send error back to the source
if (packets != null) {
FastBuildTree errorMap = null;
if (cause != null) {
errorMap = new FastBuildTree(2);
// Add message
errorMap.putUnsafe("message", cause.getMessage());
// Add trace
StringWriter sw = new StringWriter(128);
PrintWriter pw = new PrintWriter(sw);
cause.printStackTrace(pw);
errorMap.putUnsafe("trace", sw.toString());
}
for (byte[] packet : packets) {
try {
// Remove header
if (packet != null && packet.length > 6) {
byte[] copy = new byte[packet.length - 6];
System.arraycopy(packet, 6, copy, 0, copy.length);
// Deserialize packet
Tree message = serializer.read(copy);
// Get request's unique ID
String id = message.get("id", (String) null);
if (id == null || id.isEmpty()) {
// Not a request
return;
}
// Create response message
FastBuildTree response = new FastBuildTree(6);
response.putUnsafe("id", id);
response.putUnsafe("ver", ServiceBroker.PROTOCOL_VERSION);
response.putUnsafe("sender", nodeID);
response.putUnsafe("success", false);
response.putUnsafe("data", (String) null);
if (errorMap != null) {
response.putUnsafe("error", errorMap);
}
registry.receiveResponse(response);
}
} catch (Exception error) {
logger.warn("Unable to handle error!", error);
}
}
}
});
}
}
Aggregations