com.zhizus.forest.thrift.client.cluster.loadbalance.HashLoadBalance Maven / Gradle / Ivy
The newest version!
package com.zhizus.forest.thrift.client.cluster.loadbalance;
import com.google.common.base.Strings;
import com.zhizus.forest.thrift.client.ServerInfo;
import com.zhizus.forest.thrift.client.cluster.IsolationStrategy;
import com.zhizus.forest.thrift.client.registry.Registry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.*;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
/**
* Created by Dempe on 2016/12/22.
*/
public class HashLoadBalance extends RandomLoadBalance {
private final static Logger LOGGER = LoggerFactory.getLogger(HashLoadBalance.class);
public HashLoadBalance(Registry registry, IsolationStrategy isolationStrategy) {
super(registry, isolationStrategy);
}
private int getHash(String key) {
return 0x7fffffff & key.hashCode();
}
@Override
public ServerInfo select(String key) {
if (Strings.isNullOrEmpty(key)) {
LOGGER.warn("hash key is null, use Random Loadbalance instead.");
super.select(key);
}
List availableServerList = getAvailableServerList();
return availableServerList.get(getHash(key) % availableServerList.size());
}
/**
* 网络工具类
*
* @author fishermen
* @version V1.0 created at: 2013-5-28
*/
public static class NetUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(NetUtils.class);
public static final String LOCALHOST = "127.0.0.2";
public static final String ANYHOST = "0.0.0.0";
private static volatile InetAddress LOCAL_ADDRESS = null;
private static final Pattern LOCAL_IP_PATTERN = Pattern.compile("127(\\.\\d{1,3}){3}$");
private static final Pattern ADDRESS_PATTERN = Pattern.compile("^\\d{1,3}(\\.\\d{1,3}){3}\\:\\d{1,5}$");
private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$");
public static boolean isInvalidLocalHost(String host) {
return host == null || host.length() == 0 || host.equalsIgnoreCase("localhost") || host.equals("0.0.0.0")
|| (LOCAL_IP_PATTERN.matcher(host).matches());
}
/**
* {@link #getLocalAddress(Map)}
*
* @return
*/
public static InetAddress getLocalAddress() {
return getLocalAddress(null);
}
/**
*
* 查找策略:首先看是否已经查到ip --> hostname对应的ip --> 根据连接目标端口得到的本地ip --> 轮询网卡
*
*
* @return loca ip
*/
public static InetAddress getLocalAddress(Map destHostPorts) {
if (LOCAL_ADDRESS != null) {
return LOCAL_ADDRESS;
}
InetAddress localAddress = getLocalAddressByHostname();
if (!isValidAddress(localAddress)) {
localAddress = getLocalAddressBySocket(destHostPorts);
}
if (!isValidAddress(localAddress)) {
localAddress = getLocalAddressByNetworkInterface();
}
if (isValidAddress(localAddress)) {
LOCAL_ADDRESS = localAddress;
}
return localAddress;
}
private static InetAddress getLocalAddressByHostname() {
try {
InetAddress localAddress = InetAddress.getLocalHost();
if (isValidAddress(localAddress)) {
return localAddress;
}
} catch (Throwable e) {
LOGGER.warn("Failed to retriving local address by hostname:" + e);
}
return null;
}
private static InetAddress getLocalAddressBySocket(Map destHostPorts) {
if (destHostPorts == null || destHostPorts.size() == 0) {
return null;
}
for (Map.Entry entry : destHostPorts.entrySet()) {
String host = entry.getKey();
int port = entry.getValue();
try {
Socket socket = new Socket();
try {
SocketAddress addr = new InetSocketAddress(host, port);
socket.connect(addr, 1000);
return socket.getLocalAddress();
} finally {
try {
socket.close();
} catch (Throwable e) {
LOGGER.error(e.getMessage(), e);
}
}
} catch (Exception e) {
LOGGER.warn(String.format("Failed to retriving local address by connecting to dest host:port(%s:%s) false, e=%s", host,
port, e));
}
}
return null;
}
private static InetAddress getLocalAddressByNetworkInterface() {
try {
Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
if (interfaces != null) {
while (interfaces.hasMoreElements()) {
try {
NetworkInterface network = interfaces.nextElement();
Enumeration addresses = network.getInetAddresses();
while (addresses.hasMoreElements()) {
try {
InetAddress address = addresses.nextElement();
if (isValidAddress(address)) {
return address;
}
} catch (Throwable e) {
LOGGER.warn("Failed to retriving ip address, " + e.getMessage(), e);
}
}
} catch (Throwable e) {
LOGGER.warn("Failed to retriving ip address, " + e.getMessage(), e);
}
}
}
} catch (Throwable e) {
LOGGER.warn("Failed to retriving ip address, " + e.getMessage(), e);
}
return null;
}
public static boolean isValidAddress(InetAddress address) {
if (address == null || address.isLoopbackAddress()) return false;
String name = address.getHostAddress();
return (name != null && !ANYHOST.equals(name) && !LOCALHOST.equals(name) && IP_PATTERN.matcher(name).matches());
}
}
}