/** * Returns the node metrics at a given index. * If there is no entry at the given index it is created by this call. */ private NodeMetrics getNodeMetrics(Mirror.Entry entry) { int index = getIndex(entry.getName()); // expand node array as needed while (nodeWeights.size() < (index + 1)) nodeWeights.add(null); NodeMetrics nodeMetrics = nodeWeights.get(index); if (nodeMetrics == null) { // initialize statistics for this node nodeMetrics = new NodeMetrics("node_" + index, metrics.targets); nodeWeights.set(index, nodeMetrics); } return nodeMetrics; }
@GET @Path("/{instanceId}/slobrok") @Produces(MediaType.APPLICATION_JSON) public List<SlobrokEntryResponse> getSlobrokEntries( @PathParam("instanceId") String instanceId, @QueryParam("pattern") String pattern) { ApplicationInstanceReference reference = parseInstanceId(instanceId); ApplicationId applicationId = OrchestratorUtil.toApplicationId(reference); if (pattern == null) { pattern = DEFAULT_SLOBROK_PATTERN; } List<Mirror.Entry> entries = slobrokApi.lookup(applicationId, pattern); return entries.stream() .map(entry -> new SlobrokEntryResponse(entry.getName(), entry.getSpec())) .collect(Collectors.toList()); }
@Override public Mirror.Entry[] lookup(String pattern) { List<Mirror.Entry> out = new ArrayList<>(); Pattern regex = Pattern.compile(pattern.replace("*", "[a-zA-Z0-9_-]+")); for (String key : services.keySet()) { if (regex.matcher(key).matches()) { out.add(new Mirror.Entry(key, key)); } } return out.toArray(new Mirror.Entry[out.size()]); }
/** * Updates and returns the cache entry for the given routing context. This method assumes that synchronization is * handled outside of it. * * @param ctx The routing context. * @return The updated cache entry. */ private CacheEntry update(RoutingContext ctx) { String key = getCacheKey(ctx); CacheEntry entry = cache.get(key); if (entry == null) { entry = new CacheEntry(); cache.put(key, entry); } int upd = ctx.getMirror().updates(); if (entry.generation != upd) { entry.generation = upd; entry.recipients.clear(); Mirror.Entry[] arr = ctx.getMirror().lookup(ctx.getHopPrefix() + "*" + ctx.getHopSuffix()); String self = localAddress != null ? localAddress : toAddress(ctx.getMessageBus().getConnectionSpec()); for (Mirror.Entry item : arr) { if (self.equals(toAddress(item.getSpec()))) { entry.recipients.add(Hop.parse(item.getName())); } } } return entry; }
/** * Resolve a concrete address from this service. This service may represent multiple remote sessions, so this will * select one that is online. * * @return A concrete service address. */ public RPCServiceAddress resolve() { if (pattern.startsWith("tcp/")) { int pos = pattern.lastIndexOf('/'); if (pos > 0 && pos < pattern.length() - 1) { RPCServiceAddress ret = new RPCServiceAddress(pattern, pattern.substring(0, pos)); if (!ret.isMalformed()) { return ret; } } } else { if (addressGen != mirror.updates()) { addressGen = mirror.updates(); addressList = mirror.lookup(pattern); } if (addressList != null && addressList.length > 0) { addressIdx = ++addressIdx % addressList.length; Mirror.Entry entry = addressList[addressIdx]; return new RPCServiceAddress(entry.getName(), entry.getSpec()); } } return null; }
/** * Updates and returns the cache entry for the given routing context. This method assumes that synchronization is * handled outside of it. * * @param ctx The routing context. * @return The updated cache entry. */ private CacheEntry update(RoutingContext ctx) { String key = getCacheKey(ctx); CacheEntry entry = cache.get(key); if (entry == null) { entry = new CacheEntry(); cache.put(key, entry); } int upd = ctx.getMirror().updates(); if (entry.generation != upd) { entry.generation = upd; entry.recipients.clear(); for (int i = 0; i < ctx.getNumRecipients(); ++i) { Mirror.Entry[] arr = ctx.getMirror().lookup(ctx.getRecipient(i).getHop(0).toString()); for (Mirror.Entry item : arr) { entry.recipients.add(Hop.parse(item.getName())); } } } return entry; }
/** * Updates and returns the cache entry for the given routing context. This method assumes that synchronization is * handled outside of it. * * @param ctx The routing context. * @return The updated cache entry. */ private CacheEntry update(RoutingContext ctx) { String key = getCacheKey(ctx); CacheEntry entry = cache.get(key); if (entry == null) { entry = new CacheEntry(); cache.put(key, entry); } int upd = ctx.getMirror().updates(); if (entry.generation != upd) { entry.generation = upd; entry.recipients.clear(); Mirror.Entry[] arr = ctx.getMirror().lookup(ctx.getHopPrefix() + "*" + ctx.getHopSuffix()); int pos = ctx.getMessageBus().getConnectionSpec().hashCode(); for (int i = 0; i < subsetSize && i < arr.length; ++i) { entry.recipients.add(Hop.parse(arr[((pos + i) & Integer.MAX_VALUE) % arr.length].getName())); } } return entry; }
public String getTargetSpec(Integer distributor, RoutingContext context) { Mirror.Entry[] arr = getEntries(patternGenerator.getDistributorHostPattern(distributor), context); if (arr.length == 0) return null; if (distributor != null) { if (arr.length == 1) { return convertSlobrokNameToSessionName(arr[0].getSpec()); } else { log.log(LogLevel.WARNING, "Got " + arr.length + " matches for a distributor."); } } else { return convertSlobrokNameToSessionName(arr[randomizer.nextInt(arr.length)].getSpec()); } return null; } }
/** * Updates the list of matching recipients by querying the extern slobrok. */ private void update() { int upd = mirror.updates(); if (generation != upd) { generation = upd; recipients.clear(); Mirror.Entry[] arr = mirror.lookup(pattern); for (Mirror.Entry entry : arr) { recipients.add(Hop.parse(entry.getSpec() + session)); } } }
@Override public void doSelect(RoutingContext context) { LoadBalancer.Node node = getRecipient(context); if (node != null) { context.setContext(node); Route route = new Route(context.getRoute()); route.setHop(0, Hop.parse(node.entry.getSpec() + "/" + session)); context.addChild(route); } else { context.setError(ErrorCode.NO_ADDRESS_FOR_SERVICE, "Could not resolve any nodes to send to in pattern " + pattern); } }
@Override public Entry[] lookup(String pattern) { ArrayList<Entry> found = new ArrayList<>(); char[] p = pattern.toCharArray(); for (Entry specEntry : specs) { if (match(specEntry.getNameArray(), p)) { found.add(specEntry); } } return found.toArray(new Entry[found.size()]); }