一、负载均衡的概念
在大型的分布式架构中,对于负载较高的服务来说,往往对应着多台机器组成的集群,当请求到来的时候,为了将请求均衡的分配给后端服务器需要有相应的负载均衡算法来支持,通过相应的负载均衡算法选取一台机器来处理客户端请求,这个过程称为服务的负载均衡。
二、常用负载均衡算法实现
常用的负载均衡算法主要有随机法,轮询法,加权随机,加权轮询,最小连接数,一致性hash等。随机法,轮询法都比较简单,随机算法不考虑服务器的负载实际中很少使用,轮询算法在服务的上线下线时无法及时感应到也较少使用,下面重点介绍比较常用的加权轮询和一致性hash。
2.1 负载均衡接口
import java.util.List;
import cn.fzjh.vo.ServiceInstance;
public interface LoadBalance {
//根据请求选择一个服务实例
ServiceInstance chooseServerInstance();
/**
* 设置服务的信息
*
* @param serviceName 服务名
* @param version 服务版本
*/
void setService(String serviceName, String version);
/**
* 初始化
*/
void init();
/**
* 获取全部服务列表
*
* @return
*/
List<serviceinstance> getServiceInstanceList();
/**
* 更新服务实例列表
*/
void updateServerInstanceList();
/**
* 隔离一个服务实例
*
* @param server
*/
void isolateServerInstance(String server);
/**
* 恢复一个服务实例
*
* @param server
*/
void resumeServerInstance(String server);
}
2.2 抽象负载均衡基类
import java.util.List;
import java.util.Random;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cn.fzjh.jk.LoadBalance;
import cn.fzjh.rule.DynamicUploadRule;
import cn.fzjh.vo.ServiceInstance;
//抽象的负载均衡基类,提供基本的服务信息和相关服务实例列表的管理
public abstract class AbstractLoadBalance implements LoadBalance {
protected final Logger logger = LoggerFactory
.getLogger(AbstractLoadBalance.class);
@Resource(name="dynamicUploadRule")
private transient DynamicUploadRule dynamicUploadRule;
protected String serviceName;
protected String version;
// 特定版本的服务的标识
private transient String serviceKey;
protected List<serviceinstance> serviceInstanceList;
@Override
public void setService(String serviceName, String version) {
this.serviceName = serviceName;
this.version = version;
this.serviceKey = genKey(serviceName, version);
}
// 随机算法获取可利用的服务列表
@Override
public ServiceInstance chooseServerInstance() {
List<serviceinstance> allServiceList = getAllServiceInstanceList();
if (null == allServiceList) {
return null;
}
ServiceInstance serviceInstance = null;
int indexOfLoop = 0;
Random random = new Random();
if (null != allServiceList && allServiceList.size() > 0) {
int serviceCount = allServiceList.size();
while (null == serviceInstance && indexOfLoop < serviceCount * 5) {// 由于是随机选取,不能在serverCount内选出
int index = random.nextInt(serviceCount);
serviceInstance = allServiceList.get(index);
logger.info("随机选择算法获取可用的服务:" + serviceInstance.getServerName());
if (serviceInstance.isIsolated()) {
logger.info("选择的服务暂时不可用:" + serviceInstance.getServerName()
+ ",重新选择");
indexOfLoop++;
serviceInstance = null;
}
}
}
return serviceInstance;
}
@Override
public void init() {
// 拿到所有的服务器列表
List<serviceinstance> serviceInstances = getAllServiceInstanceList();
setServiceInstanceList(serviceInstances);
}
@Override
public List<serviceinstance> getServiceInstanceList() {
return serviceInstanceList;
}