文章系列
【一、dubbo源码解析之框架粗谈】
【二、dubbo源码解析之dubbo配置解析】
【三、dubbo源码解析之服务发布与注册】
【四、dubbo源码解析之服务发现】
【五、dubbo源码解析之服务调用(通信)流程】
【六、dubbo获取服务提供者IP列表】
在 dubbo 源码分析中可知,所有服务地址都是通过 org.apache.dubbo.rpc.cluster.Directory
获取的,如下:
public interface Directory<T> extends Node {
Class<T> getInterface();
List<Invoker<T>> list(Invocation invocation) throws RpcException;
// 获取所有 Invoker
List<Invoker<T>> getAllInvokers();
URL getConsumerUrl();
boolean isDestroyed();
void discordAddresses();
}
而在 org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster
类的 Interceptors(AbstractClusterInvoker<T> clusterInvoker, String key)
方法中,构建集群拦截器时,存在一个扩展点,如下:
public abstract class AbstractCluster implements Cluster {
private <T> Invoker<T> buildClusterInterceptors(AbstractClusterInvoker<T> clusterInvoker, String key) {
AbstractClusterInvoker<T> last = clusterInvoker;
List<ClusterInterceptor> interceptors = ExtensionLoader.getExtensionLoader(ClusterInterceptor.class).getActivateExtension(clusterInvoker.getUrl(), key);
if (!interceptors.isEmpty()) {
for (int i = interceptors.size() - 1; i >= 0; i--) {
final ClusterInterceptor interceptor = interceptors.get(i);
final AbstractClusterInvoker<T> next = last;
last = new InterceptorInvokerNode<>(clusterInvoker, interceptor, next);
}
}
return last;
}
@Override
public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
return buildClusterInterceptors(doJoin(directory), directory.getUrl().getParameter(REFERENCE_INTERCEPTOR_KEY));
}
}
List<ClusterInterceptor> interceptors = ExtensionLoader.getExtensionLoader(ClusterInterceptor.class).getActivateExtension(clusterInvoker.getUrl(), key);
ClusterInterceptor 为集群处理拦截器 SPI 扩展点,在进行创建 InterceptorInvokerNode
(拦截器调用节点)时,传入了一个 clusterInvoker,我们可通过 clusterInvoker 获取 Directory
对象,进而获取所有服务提供者IP列表,如下:
@Activate // 添加激活扩展点注解
public class TestClusterInterceptor implements ClusterInterceptor{
@Override
public void before(AbstractClusterInvoker<?> clusterInvoker, Invocation invocation) {
List<? extends Invoker<?>> allInvokers = clusterInvoker.getDirectory().getAllInvokers();
if (CollectionUtils.isEmpty(allInvokers)) {
return;
}
List<String> addressList = new ArrayList<>(allInvokers.size());
for (Invoker<?> allInvoker : allInvokers) {
// 通过url获取 address
String address = allInvoker.getUrl().getAddress();
addressList.add(address);
}
System.out.println(addressList);
}
@Override
public void after(AbstractClusterInvoker<?> clusterInvoker, Invocation invocation) {
}
}
SPI扩展文件
打印结果
[127.0.0.1:20881, 127.0.0.1:20880]