Spring Cloud中的LoadBalance Client做前段的负载均衡,可以通过一些自带的规则实现负载均衡算法。例如轮询,随机等等。如下图是默认的一些规则实现

本文是介绍如何通过自定义规则,实现基于权重的服务流量分配。

思路如下:

注册服务时,定义服务Tags。本文例子中定义的Tags如下:ENV=XXX,VERSION=XXX。其中ENV定义环境,VERSION定义服务版本

那么如何实现基于服务版本来分配流量呢?比如对于版本v2.0分配2/3的流量,版本V1.0分配1/3的流量?

实现思路就在于自定义LoadBalance Rule, 在选择可用的Server是,加入自己的逻辑,把不符合规则的可用Server过滤掉,就可以啦。如下是具体实现。

1)自定义一个类,这个类中记录服务的配置信息,包括服务的名字,环境,版本,权重,调用次数,以及计算下一个可用服务节点的变量AtomicInteger,这是线程安全的自增变量

 

2)定义一个List,存储所有服务配置信息列表

 

3)自定义LoadBalanceRule

 

这个类中最重要的就是choose选择可用服务的方法,在这个方法里我自定义了两个用于选择可用server的方法

chooseSmallestVersion,这个方法用于选择对应服务version中流量最小的服务Version,也就是接下来流量要分配到这个版本的服务上去

getENVPrdServer,这个方法用于选择对应版本的可用Server

经过这样的自定义可用server过滤,就可以实现基于权重的服务分配啦~

涉及到的一些类见附件。

 

具体代码见如下:

 

 

protected List<Server> getENVPrdServer(ILoadBalancer lb,String version)
{
List<Server> upList = lb.getReachableServers();
List<Server> filterList = new ArrayList<Server>();
for(Server s : upList)
{
ConsulServer cs = (ConsulServer)s;

Map<String, String> md = cs.getMetadata();
log.warn("env is:" + md.get("ENV"));
String userRole = CustomRuleEntity.getInstance().getUserRole();
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;

String ENV = "";
String VERSION = "";
if(sra.getAttribute("ENV", ra.SCOPE_REQUEST) != null) {
ENV = sra.getAttribute("ENV", ra.SCOPE_REQUEST).toString();
}
if(sra.getAttribute("VERSION", ra.SCOPE_REQUEST) != null)
{
VERSION = sra.getAttribute("VERSION", ra.SCOPE_REQUEST).toString();
}
String apidoc = "";
if(sra.getAttribute("APIDOC", ra.SCOPE_REQUEST) != null)
{
apidoc = "TRUE";
}
Boolean flag_env = (md.get("ENV") != null && md.get("ENV").equals(ENV));
Boolean flag_version = (md.get("VERSION") != null && md.get("VERSION").equals(version));
if((flag_env && flag_version) || apidoc == "TRUE")
{
filterList.add(s);
}

}
return filterList;
}

private ServerDispatchConfig chooseSmallestVersion(String name)
{
List<ServerDispatchConfig> sdcl_local = sdcL.getSdcLByName(name);
//0 stands for go on compare. 1 stands for minimal value has been found.
Integer goon = 1;
String version = "";
ServerDispatchConfig sdc = null;
for(int i=0; i<sdcl_local.size();i++)
{
goon = 1;
for(int j=i+1;j<sdcl_local.size();j++)
{
ServerDispatchConfig sdc_i = sdcl_local.get(i);
ServerDispatchConfig sdc_j = sdcl_local.get(j);
if((sdc_i.getCallcount()/sdc_i.getWeight()) > sdc_j.getCallcount()/sdc_j.getWeight())
{
goon = 0;
break;
}
}
if(goon==1)
{
sdc = sdcl_local.get(i);
version = sdc.getVersion();
sdc.setCallcount(sdc.getCallcount() + 1);
System.out.println("version:" + version);
System.out.println("weight:" + sdc.getWeight().toString());
System.out.println("callcount:" + sdc.getCallcount().toString());
return sdc;
}
}
return sdc;
}

 

 

---恢复内容结束---

posted on 2018-02-09 14:55  zhangjinxiang  阅读(331)  评论(0编辑  收藏  举报