/** * Dianping.com Inc. * Copyright (c) 2003-2013 All Rights Reserved. */ package com.dianping.pigeon.remoting.invoker.route.balance; import java.util.List; import java.util.Random; import com.dianping.pigeon.log.Logger; import com.dianping.pigeon.config.ConfigManagerLoader; import com.dianping.pigeon.log.LoggerLoader; import com.dianping.pigeon.remoting.common.domain.InvocationRequest; import com.dianping.pigeon.remoting.invoker.Client; import com.dianping.pigeon.remoting.invoker.config.InvokerConfig; import com.dianping.pigeon.remoting.invoker.route.statistics.ServiceStatisticsHolder; import com.dianping.pigeon.util.LangUtils; public class WeightedAutoawareLoadBalance extends AbstractLoadBalance { private static final Logger logger = LoggerLoader.getLogger(WeightedAutoawareLoadBalance.class); public static final String NAME = "weightedAutoaware"; public static final LoadBalance instance = new WeightedAutoawareLoadBalance(); private static int defaultFactor = ConfigManagerLoader.getConfigManager().getIntValue( "pigeon.loadbalance.defaultFactor", 100); private static Random random = new Random(); @Override public Client doSelect(List<Client> clients, InvokerConfig<?> invokerConfig, InvocationRequest request, int[] weights) { assert (clients != null && clients.size() >= 1); if (clients.size() == 1) { return clients.get(0); } float minCapacity = Float.MAX_VALUE; int clientSize = clients.size(); Client[] candidates = new Client[clientSize]; int candidateIdx = 0; for (int i = 0; i < clientSize; i++) { Client client = clients.get(i); float capacity = ServiceStatisticsHolder.getCapacity(client.getAddress()); if (logger.isDebugEnabled()) { logger.debug("capacity:" + LangUtils.toString(capacity, 4) + ", weight:" + weights[i] + " for address:" + client.getAddress()); } // 根据权重重新调整请求容量 if (weights[i] > 0) { capacity /= weights[i]; } else { capacity = Float.MAX_VALUE; } if (capacity < minCapacity) { minCapacity = capacity; candidateIdx = 0; candidates[candidateIdx++] = client; } else if (Math.abs(capacity - minCapacity) < 1e-6) { candidates[candidateIdx++] = client; } } Client client = candidateIdx == 1 ? candidates[0] : candidates[random.nextInt(candidateIdx)]; if (logger.isDebugEnabled()) { logger.debug("select address:" + client.getAddress()); } return client; } }