All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.ejb.client.DeploymentNodeSelector Maven / Gradle / Ivy

The newest version!
/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2017 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jboss.ejb.client;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;

import org.jboss.ejb._private.Logs;
import org.wildfly.common.Assert;

/**
 * A selector which selects and returns a node, from among the passed eligible nodes, that can handle a specific
 * deployment within an Enterprise Bean client context. Typical usage of {@link DeploymentNodeSelector} involves load balancing
 * calls to multiple nodes which can all handle the same deployment. This allows the application to have a deterministic
 * node selection policy while dealing with multiple nodes with same deployment.
 * 

* Node selection is only used when discovery yields nodes as a result of its query to locate an Enterprise Bean. If discovery * yields a URI or cluster, this mechanism is not used. * * @author Jaikiran Pai * @author Wolf Dieter Fink */ public interface DeploymentNodeSelector { /** * Selects and returns a node from among the eligibleNodes to handle the invocation on a deployment * represented by the passed appName, moduleName and distinctName combination. * Implementations of this method must not return null or any other node name which isn't in the * eligibleNodes * * @param eligibleNodes the eligible nodes which can handle the deployment; not {@code null}, will not be empty * @param appName the app name of the deployment * @param moduleName the module name of the deployment * @param distinctName the distinct name of the deployment * @return the node selection (must not be {@code null}) */ String selectNode(final String[] eligibleNodes, final String appName, final String moduleName, final String distinctName); /** * Create a deployment node selector that prefers one or more favorite nodes, falling back to another selector if * none of the favorites are found. * * @param favorites the favorite nodes, in decreasing order of preference (must not be {@code null}) * @param fallback the fallback selector (must not be {@code null}) * @return the selector (not {@code null}) * * @deprecated will be removed in future version */ @Deprecated static DeploymentNodeSelector favorite(Collection favorites, DeploymentNodeSelector fallback) { Assert.checkNotNullParam("favorites", favorites); Assert.checkNotNullParam("fallback", fallback); return (eligibleNodes, appName, moduleName, distinctName) -> { final HashSet set = new HashSet(eligibleNodes.length); Collections.addAll(set, eligibleNodes); for (String favorite : favorites) { if (set.contains(favorite)) { if (Logs.MAIN.isDebugEnabled()) { Logs.MAIN.debugf("FAVORITE node %s for [app: %s, module: %s, distinctname: %s]", favorite, appName, moduleName, distinctName); } return favorite; } } if(Logs.MAIN.isDebugEnabled()) { Logs.MAIN.debugf("FAVORITE no favorite found use fallback for [eligibleNodes %s, app: %s, module: %s, distinctname: %s]", Arrays.deepToString(eligibleNodes), appName, moduleName, distinctName); } return fallback.selectNode(eligibleNodes, appName, moduleName, distinctName); }; } /** * A deployment node selector which prefers the first node always. This will generally avoid load balancing in most * cases. */ DeploymentNodeSelector FIRST = (eligibleNodes, appName, moduleName, distinctName) -> eligibleNodes[0]; /** * A deployment node selector which randomly chooses the next node. This will generally provide the best possible * load balancing over a large number of requests. */ DeploymentNodeSelector RANDOM = (eligibleNodes, appName, moduleName, distinctName) -> eligibleNodes[ThreadLocalRandom.current().nextInt(eligibleNodes.length)]; /** * A deployment node selector which uses an approximate round-robin policy among all of the eligible nodes. Note * that the round-robin node count may be shared among multiple node sets, thus certain specific usage patterns * may defeat the round-robin behavior. */ DeploymentNodeSelector ROUND_ROBIN = new DeploymentNodeSelector() { private final AtomicInteger counter = new AtomicInteger(); public String selectNode(final String[] eligibleNodes, final String appName, final String moduleName, final String distinctName) { final int length = eligibleNodes.length; assert length > 0; if(Logs.MAIN.isTraceEnabled()) { Logs.MAIN.tracef("ROUND_ROBIN [nodes=%s appName=%s moduleName=%s, distinctName=%s]", Arrays.deepToString(eligibleNodes), appName, moduleName, distinctName); } String node = eligibleNodes[Math.floorMod(counter.getAndIncrement(), length)]; if(Logs.MAIN.isDebugEnabled()) { Logs.MAIN.debugf("ROUND_ROBIN select node %s for [app: %s, module: %s, distinctname: %s]", node, appName, moduleName, distinctName); } return node; } }; /** * A deployment node selector which check the server name if inside and prefer it if available for selection. */ DeploymentNodeSelector RANDOM_PREFER_LOCAL = new DeploymentNodeSelector() { private final String localNodeName = SecurityUtils.getString(SystemProperties.JBOSS_NODE_NAME); public String selectNode(final String[] eligibleNodes, final String appName, final String moduleName, final String distinctName) { if(Logs.MAIN.isTraceEnabled()) { Logs.MAIN.tracef("RANDOM_PREFER_LOCAL (%s) [nodes=%s appName=%s moduleName=%s, distinctName=%s]", localNodeName, Arrays.deepToString(eligibleNodes), appName, moduleName, distinctName); } // Just a single node available, so just return it if (eligibleNodes.length == 1) { return eligibleNodes[0]; } // prefer local node if available if(localNodeName != null) { for (final String eligibleNode : eligibleNodes) { if (localNodeName.equals(eligibleNode)) { if (Logs.MAIN.isDebugEnabled()) { Logs.MAIN.debugf("RANDOM_PREFER_LOCAL select local node %s for [app: %s, module: %s, distinctname: %s]", eligibleNode, appName, moduleName, distinctName); } return eligibleNode; } } } // select one randomly if (Logs.MAIN.isDebugEnabled()) { Logs.MAIN.debug("RANDOM_PREFER_LOCAL local node not avaialble, fallback to RANDOM selection"); } return RANDOM.selectNode(eligibleNodes, appName, moduleName, distinctName); } }; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy