LoadBalancer.java
- /*
- * GovWay - A customizable API Gateway
- * https://govway.org
- *
- * Copyright (c) 2005-2025 Link.it srl (https://link.it).
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3, as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- package org.openspcoop2.pdd.core.behaviour.built_in.load_balance;
- import java.security.SecureRandom;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Set;
- import org.openspcoop2.pdd.core.PdDContext;
- import org.openspcoop2.pdd.core.behaviour.BehaviourException;
- /**
- * LoadBalancer
- *
- * @author Andrea Poli (apoli@link.it)
- * @author $Author$
- * @version $Rev$, $Date$
- */
- public class LoadBalancer {
- private static java.util.Random _rnd = null;
- private static synchronized void initRandomInstance() {
- if(_rnd==null) {
- _rnd = new SecureRandom();
- }
- }
- public static java.util.Random getRandomInstance() {
- if(_rnd==null) {
- initRandomInstance();
- }
- return _rnd;
- }
-
- private PdDContext pddContext;
- private LoadBalancerPool pool;
- private LoadBalancerType type;
-
- public LoadBalancer(LoadBalancerType type, LoadBalancerPool pool, PdDContext pddContext) {
- this.pddContext = pddContext;
- this.type = type;
- this.pool = pool;
- }
-
- public String selectConnector() throws BehaviourException {
- switch (this.type) {
- case ROUND_ROBIN:
- return getRoundRobin();
- case WEIGHT_ROUND_ROBIN:
- return getWeightRoundRobin();
- case RANDOM:
- return getRandom();
- case WEIGHT_RANDOM:
- return getWeightRandom();
- case IP_HASH:
- return getIpSourceHash();
- case LEAST_CONNECTIONS:
- return getLeastConnections();
- }
-
- throw new BehaviourException("Type '"+this.type+"' unknown");
- }
- private String getRoundRobin() throws BehaviourException {
- Set<String> servers = this.pool.getConnectorNames(false); // il passive health check viene effettuato dentro il metodo nextPosition
- List<String> serverList = new ArrayList<>();
- serverList.addAll(servers);
- int position = this.pool.getNextPosition(false);
- String target = serverList.get(position);
- return target;
- }
- private String getWeightRoundRobin() throws BehaviourException {
- List<String> serverList = this.pool.getWeightList(false); // il passive health check viene effettuato dentro il metodo nextPosition
- int position = this.pool.getNextPosition(true);
- String target = serverList.get(position);
- return target;
- }
- private String getRandom() throws BehaviourException {
- Set<String> servers = this.pool.getConnectorNames(true);
- if(servers.isEmpty()) {
- throw new BehaviourException("Nessun connettore selezionabile (passive health check)");
- }
- List<String> serverList = new ArrayList<>();
- serverList.addAll(servers);
- int randomIndex = getRandomInstance().nextInt(serverList.size());
- String target = serverList.get(randomIndex);
- return target;
- }
- private String getWeightRandom() throws BehaviourException {
- List<String> serverList = this.pool.getWeightList(true);
- Integer index = getRandomInstance().nextInt(serverList.size());
- String target = serverList.get(index);
- return target;
- }
- public static String getIpSourceFromContet(PdDContext pddContext) {
- Object oIpAddressRemote = pddContext.getObject(org.openspcoop2.core.constants.Costanti.CLIENT_IP_REMOTE_ADDRESS);
- String ipAddressRemote = null;
- if(oIpAddressRemote!=null && (oIpAddressRemote instanceof String)){
- ipAddressRemote = (String)oIpAddressRemote;
- }
- if (ipAddressRemote == null) {
- ipAddressRemote = "127.0.0.1";
- }
-
- Object oIpAddressTransport = pddContext.getObject(org.openspcoop2.core.constants.Costanti.CLIENT_IP_TRANSPORT_ADDRESS);
- String ipAddressTransport = null;
- if(oIpAddressTransport!=null && (oIpAddressTransport instanceof String)){
- ipAddressTransport = (String)oIpAddressTransport;
- }
- if (ipAddressTransport == null) {
- ipAddressTransport = "-";
- }
-
- String clientIp = ipAddressRemote+" "+ipAddressTransport;
-
- return clientIp;
- }
-
- private String getIpSourceHash() throws BehaviourException {
-
- String clientIp = getIpSourceFromContet(this.pddContext);
-
- Set<String> servers = this.pool.getConnectorNames(false);
- List<String> serverList = new ArrayList<>();
- serverList.addAll(servers);
- String remoteId = clientIp;
- int hashCodeCalcolato = remoteId.hashCode();
- if(hashCodeCalcolato == Integer.MIN_VALUE) {
- hashCodeCalcolato = Integer.MIN_VALUE+1; // altrimenti viene negativo l'abs
- }
- int absoluteHashCode = java.lang.Math.abs(hashCodeCalcolato);
- Integer index = absoluteHashCode % serverList.size();
- String target = serverList.get(index);
-
- if(this.pool.isPassiveHealthCheck()) {
-
- Set<String> setAfterPassiveHealthCheck = this.pool.getConnectorNames(true);
-
- // prima verifica
- if(setAfterPassiveHealthCheck.contains(target)) {
- return target;
- }
-
- // controllo prossime posizioni fino a tornare a quella attuale
- int nextPos = index.intValue()+1;
- if(nextPos==serverList.size()) {
- nextPos = 0;
- }
- while(nextPos!=index.intValue()) {
- target = serverList.get(nextPos);
- if(setAfterPassiveHealthCheck.contains(target)) {
- return target;
- }
- nextPos++;
- if(nextPos==serverList.size()) {
- nextPos = 0;
- }
- }
-
- throw new BehaviourException("Nessun connettore selezionabile (passive health check)");
-
- }
-
- return target;
- }
-
- private String getLeastConnections() {
- return this.pool.getNextConnectorLeastConnections();
- }
- }