dubbo-详解URL

1. URL

URL(Uniform Resource Locator,统一资源定位符),它是互联网的统一资源定位标志,也就是指网络地址。URL 本质上就是一个特殊格式的字符串。一个标准的 URL 格式可以包含如下的几个部分:
protocol://username:password@host:port/path?key=value&key=value

2. dubbo中的URL

在 dubbo 中,也使用了类似的 URL,主要用于在各个扩展点之间传递数据,组成此 URL 对象的具体参数如下:

  • protocol:一般是 dubbo 中的各种协议 如:dubbo thrift http zk
  • username/password:用户名/密码
  • host/port:主机/端口
  • path:接口名称
  • parameters:参数键值对

任意的一个领域中的一个实现都可以认为是一类 URL,dubbo 使用 URL 来统一描述了元数据,配置信息,贯穿在整个框架之中。

// URL中主要的构造函数
public URL(String protocol,
               String username,
               String password,
               String host,
               int port,
               String path,
               Map<String, String> parameters) {
  if (StringUtils.isEmpty(username)
      && StringUtils.isNotEmpty(password)) {
      throw new IllegalArgumentException("Invalid url, password without username!");
  }

  this.urlAddress = new PathURLAddress(protocol, username, password, path, host, port);
  this.urlParam = URLParam.parse(parameters);
  this.attributes = null;
}


# 3.0之后新增的构造函数
public URL(URLAddress urlAddress, URLParam urlParam) {
   this(urlAddress, urlParam, null);
}

在 dubbo 3.0 中新增了 URLAddress 和 URLParam 两个类。原来的 parameters 属性被移动到了 URLParam 中的 params,其他的属性则移动到了 URLAddress 及其子类中。

dubbo 3.0之后新增了3个 URL 子类,其中 InstanceAddressURL 属于应用级接口地址。 而 ServiceConfigURL 及 ServiceAddressURL 主要的差别就是,ServiceConfigURL 是程序读取配置文件时生成的 URL;而 ServiceAddressURL 则是注册中心推送一些信息(如 providers)过来时生成的 URL。

在 dubbo-common 包中还提供了 URL 的辅助类:URLBuilder, 辅助构造 URL;URLStrParser, 将字符串解析成 URL 对象。

3. dubbo中URL示例

3.1 URL 在 SPI 中的应用

dubbo SPI 中有一个依赖 URL 的重要场景——适配器方法,是被 @Adaptive 注解标注的 。URL 一个很重要的作用就是与 @Adaptive 注解一起选择合适的扩展实现类。
例如,在 dubbo-registry-api 模块中我们可以看到 RegistryFactory 这个接口,其中的 getRegistry() 方法上有 @Adaptive({“protocol”}) 注解,说明这是一个适配器方法,Dubbo 在运行时会为其动态生成相应的 “$Adaptive” 类型,如下所示:

@SPI(scope = APPLICATION)
public interface RegistryFactory {

    /**
     * Connect to the registry
     * <p>
     * Connecting the registry needs to support the contract: <br>
     * 1. When the check=false is set, the connection is not checked, otherwise the exception is thrown when disconnection <br>
     * 2. Support username:password authority authentication on URL.<br>
     * 3. Support the backup=10.20.153.10 candidate registry cluster address.<br>
     * 4. Support file=registry.cache local disk file cache.<br>
     * 5. Support the timeout=1000 request timeout setting.<br>
     * 6. Support session=60000 session timeout or expiration settings.<br>
     *
     * @param url Registry address, is not allowed to be empty
     * @return Registry reference, never return empty value
     */
     // PROTOCOL_KEY = "protocol";
    @Adaptive({PROTOCOL_KEY})
    Registry getRegistry(URL url);
}

public class RegistryFactory$Adaptive implements org.apache.dubbo.registry.RegistryFactory {
	public org.apache.dubbo.registry.Registry 	getRegistry(org.apache.dubbo.common.URL arg0)  {
		if (arg0 == null) 
			throw new IllegalArgumentException("url == null");
		org.apache.dubbo.common.URL url = arg0;
		// // 尝试获取URL的Protocol,如果Protocol为空,则使用默认值"dubbo" 
		String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
		if(extName == null) 
			throw new IllegalStateException("Failed to get extension (org.apache.dubbo.registry.RegistryFactory) name from url (" + url.toString() + ") use keys([protocol])");
		ScopeModel scopeModel =
			ScopeModelUtil.getOrDefault(
			url.getScopeModel(), 	org.apache.dubbo.registry.RegistryFactory.class);
		 // 根据扩展名选择相应的扩展实现
		org.apache.dubbo.registry.RegistryFactory extension = 
			(org.apache.dubbo.registry.RegistryFactory)
			scopeModel.getExtensionLoader(
				org.apache.dubbo.registry.RegistryFactory.class)
			.getExtension(extName);
		return extension.getRegistry(arg0);
	}
}

如上在生成的 RegistryFactory$Adaptive 类中会自动实现 getRegistry() 方法,其中会根据 URL 的 Protocol 确定扩展名称,从而确定使用的具体扩展实现类。

3.2 URL在服务订阅和暴露中的应用

Provider 在启动时,会将自身暴露的服务信息封装成URL注册到 ZooKeeper 上,URL 中包含了 Provider 的地址(如:192.168.0.12:20880)、暴露的接口(org.apache.dubbo.demo.DemoService)等信息, 也会根据传入的 URL 参数确定在 ZooKeeper 上创建的节点路径,还会通过 URL 中的 dynamic 参数值确定创建的 ZNode 是临时节点还是持久节点。

Consumer 启动后会向注册中心进行订阅操作,将订阅的Privder信息封装成一个URL, 如:

consumer://...?application=dubbo-demo-api-consumer&category=providers,configurators,routers&interface=org.apache.dubbo.demo.DemoService...

其中 Protocol 为 consumer ,表示是 Consumer 的订阅协议,其中的 category 参数表示要订阅的分类,这里要订阅 providers、configurators 以及 routers 三个分类;interface 参数表示订阅哪个服务接口,这里要订阅的是暴露 org.apache.dubbo.demo.DemoService 实现的 Provider。通过 URL 中的上述参数将其整理成一个 ZooKeeper 路径,然后调用 zkClient 在其上添加监听。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值