想了解Dubbo自定义负载均衡实现策略,
首先要了解SPI机制,参看文章(https://www.jianshu.com/p/46b42f7f593c)
了解了SPI机制那么我们基于Dubbo的SPI机制对Dubbo的负载均衡策略进行扩展
这里简单阐述下,dubbo的SPI是自己进行了扩展和实现的,所以它的功能比java原生的SPI要丰富
一、实现目标
1、如果只有一个dubbo服务提供者,那么直接返回唯一的服务提供者
2、如果没有指定的服务提供者IP,那么使用dubbo默认的随机权重负载均衡
3、如果指定的IP没有对应的服务提供者,那么使用dubbo默认的随机权重负载均衡
二、实现代码如下
package com.xxx.balance;
import java.util.List;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.cluster.loadbalance.RandomLoadBalance;
/**
* Dubbo负载均衡指定服务IP调用实现(实现规则)
* 如果只有一个dubbo服务提供者
* 那么直接返回,详情代码看AbstractLoadBalance
* 如果RpcInvoker中没有指定ip,使用dubbo默认的随机权重负载均衡
* 如果RpcInvoker中指定了ip,但是提供者列表没有这个ip地址,依然使用dubbo默认的随机权重负载均衡
*
*/
public class DispatcherLoadBalance extends RandomLoadBalance {
@Override
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
String ip = RpcInvoker.get();
if (ip == null) {
return super.doSelect(invokers, url, invocation);
}
RpcInvoker.remove();
for (Invoker<T> invoker : invokers) {
String host = invoker.getUrl().getHost();
if (host.equals(ip)) {
return invoker;
}
}
return super.doSelect(invokers, url, invocation);
}
}
package com.xxx.balance;
/**
* 指定dubbo服务IP调用
*
*/
public class RpcInvoker {
private static ThreadLocal<String> holder = new ThreadLocal<>();
public static void set(String ip){
holder.set(ip);
}
//****** 访问级别不暴露给非同包的其他类 ********//
static void remove(){
holder.remove();
}
static String get(){
return holder.get();
}
}
这里使用了ThreadLocal保证线程变量安全问题
三、配置DubboSpi
首先在项目的classpath目录下增加一个叫做META-INF的目录
目录结构如下:
文件内容如下,这里注意包和类名以你自己的项目实际路径为准
dispatcher=com.xxx.balance.DispatcherLoadBalance
4、服务提供者消费配置
在dubbo:reference节点中增加,loadbalance="dispatcher",实例如下
<dubbo:reference check="false" interface="com.xxx.HelloService" id="helloService" loadbalance="dispatcher"/>
上述过程就完成了一个dubbo自定义负载均衡的策略实现
关于SPI可扩展哪些功能可以查看dubbo源码,如下图