dubbo_URL分析

本文探讨了Dubbo框架中的URL核心概念,它作为框架的总线,承载着各种配置信息。内容涉及URL的格式、重要方法如构造函数、字符串转换及参数处理,揭示了URL如何在Dubbo运行中传递和获取系统状态数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



    看dubbo源码是我第一次研究开源框架的源码,也不知道从何处下手,限于自身水平也就一个类一个类的先看着找找感觉吧。希望自己能够坚持下去,在这里先给自己加个油吧!

    dubbo-common包是公共逻辑模块,包括Util类和通用模型。

    DUBBO中所有配置最终都将转换为URL表示,并由服务提供方生成,经注册中心传递给消费方,各属性对应URL的参数,参见配置项一览表中的"对应URL参数"列。

    URL格式: protocol://username:password@host:port/path?key=value&key=value

      Dubbo框架是以URL为总线的模式,即运行过程中所有的状态数据信息都可以通过URL来获取,比如当前系统采用什么序列化,采用什么通信,采用什么负载均衡等信息,都是通过URL的参数来呈现的,所以在框架运行过程中,运行到某个阶段需要相应的数据,都可以通过对应的Key从URL的参数列表中获取,比如在cluster模块,到服务调用触发到该模块,则会从URL中获取当前调用服务的负载均衡策略,以及mock信息等。


    那我首先就先看看URL类中都有什么东西吧。

1、变量:

	private final String protocol;

	private final String username;

	private final String password;

	private final String host;

	private final int port;

	private final String path;

    private final Map<String, String> parameters;
    
    // ==== cache ====
    
    private volatile transient Map<String, Number> numbers;

    private volatile transient Map<String, URL> urls;

    private volatile transient String ip;

    private volatile transient String full;

    private volatile transient String identity;
    
    private volatile transient String parameter;

    private volatile transient String string;

整体来看包含final类型的URL基本信息变量,还有用于缓存用的volatile transient类型变量。

2、方法:

此类方法很多,但并不复杂,大部分是一些构造方法和一些参数的get/set方法,以及一些其它方法.

其中我认为重要一点的方法如下:

(1)构造方法

public URL(String protocol, String username, String password, String host, int port, String path, Map<String, String> parameters) {
		if ((username == null || username.length() == 0) 
				&& password != null && password.length() > 0) {
			throw new IllegalArgumentException("Invalid url, password without username!");
		}
		this.protocol = protocol;
		this.username = username;
		this.password = password;
		this.host = host;
		this.port = (port < 0 ? 0 : port);
		this.path = path;
		// trim the beginning "/"
		while(path != null && path.startsWith("/")) {
		    path = path.substring(1);
		}
		if (parameters == null) {
		    parameters = new HashMap<String, String>();
		} else {
		    parameters = new HashMap<String, String>(parameters);
		}
		this.parameters = Collections.unmodifiableMap(parameters);
	}

其中Collections.unmodifiableMap(parameters);是为了返回一个只读访问的map类型,保证安全。


(2)valueOf(String url)用来将url字符串转为URL对象,方法实现很简单,就是字符串的拆分。

public static URL valueOf(String url) {
        if (url == null || (url = url.trim()).length() == 0) {
            throw new IllegalArgumentException("url == null");
        }
        String protocol = null;
        String username = null;
        String password = null;
        String host = null;
        int port = 0;
        String path = null;
        Map<String, String> parameters = null;
        int i = url.indexOf("?"); // seperator between body and parameters 
        if (i >= 0) {
            String[] parts = url.substring(i + 1).split("\\&");
            parameters = new HashMap<String, String>();
            for (String part : parts) {
                part = part.trim();
                if (part.length() > 0) {
                    int j = part.indexOf('=');
                    if (j >= 0) {
                        parameters.put(part.substring(0, j), part.substring(j + 1));
                    } else {
                        parameters.put(part, part);
                    }
                }
            }
            url = url.substring(0, i);
        }
        i = url.indexOf("://");
        if (i >= 0) {
            if(i == 0) throw new IllegalStateException("url missing protocol: \"" + url + "\"");
            protocol = url.substring(0, i);
            url = url.substring(i + 3);
        }
        else {
            // case: file:/path/to/file.txt
            i = url.indexOf(":/");
            if(i>=0) {
                if(i == 0) throw new IllegalStateException("url missing protocol: \"" + url + "\"");
                protocol = url.substring(0, i);
                url = url.substring(i + 1);
            }
        }
        
        i = url.indexOf("/");
        if (i >= 0) {
            path = url.substring(i + 1);
            url = url.substring(0, i);
        }
        i = url.indexOf("@");
        if (i >= 0) {
            username = url.substring(0, i);
            int j = username.indexOf(":");
            if (j >= 0) {
                password = username.substring(j + 1);
                username = username.substring(0, j);
            }
            url = url.substring(i + 1);
        }
        i = url.indexOf(":");
        if (i >= 0 && i < url.length() - 1) {
            port = Integer.parseInt(url.substring(i + 1));
            url = url.substring(0, i);
        }
        if(url.length() > 0) host = url;
        return new URL(protocol, username, password, host, port, path, parameters);
    }


(3)buildString和buildParameters方法,是将URL对象中的变量,通过StringBuilder对象转换成URL字符串格式。


private String buildString(boolean appendUser, boolean appendParameter, boolean useIP, boolean useService, String... parameters) {
		StringBuilder buf = new StringBuilder();
		if (protocol != null && protocol.length() > 0) {
			buf.append(protocol);
			buf.append("://");
		}
		if (appendUser && username != null && username.length() > 0) {
			buf.append(username);
			if (password != null && password.length() > 0) {
				buf.append(":");
				buf.append(password);
			}
			buf.append("@");
		}
		String host;
		if (useIP) {
			host = getIp();
		} else {
			host = getHost();
		}
		if(host != null && host.length() > 0) {
    		buf.append(host);
    		if (port > 0) {
    			buf.append(":");
    			buf.append(port);
    		}
		}
		String path;
		if (useService) {
			path = getServiceKey();
		} else {
			path = getPath();
		}
		if (path != null && path.length() > 0) {
			buf.append("/");
			buf.append(path);
		}
		if (appendParameter) {
		    buildParameters(buf, true, parameters);
		}
		return buf.toString();
	}

private void buildParameters(StringBuilder buf, boolean concat, String[] parameters) {
	    if (getParameters() !=null && getParameters().size() > 0) {
            List<String> includes = (parameters == null || parameters.length == 0 ? null : Arrays.asList(parameters));
            boolean first = true;
            for (Map.Entry<String, String> entry : new TreeMap<String, String>(getParameters()).entrySet()) {
                if (entry.getKey() != null && entry.getKey().length() > 0
                        && (includes == null || includes.contains(entry.getKey()))) {
                    if (first) {
                        if (concat) {
                            buf.append("?");
                        }
                        first = false;
                    } else {
                        buf.append("&");
                    }
                    buf.append(entry.getKey());
                    buf.append("=");
                    buf.append(entry.getValue() == null ? "" : entry.getValue().trim());
                }
            }
        }
	}

本类的内容我主要看了这些,第一次看代码,大部分都看懂了,算是给自己的一份信心吧。加油。这里只是当自己的一些笔记进行了记录,没有太详细的分析,希望在以后随着自己理解的深入在慢慢补充。




我的Dubbo Router功能完全不生效,我已经全部按照规范配置了: Router实现类: package com.htsc.gtp.quant.cm.domestic.router; import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.common.extension.Activate; import com.alibaba.dubbo.rpc.Invocation; import com.alibaba.dubbo.rpc.Invoker; import com.alibaba.dubbo.rpc.RpcException; import com.alibaba.dubbo.rpc.cluster.Router; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; import static com.htsc.gtp.quant.cm.domestic.enums.StrategyCodeEnum.DOM_GRID_COND_ORDER; /** * @Project: gtp-quant-cm-domestic * @Author: 022679 * @CreateTime: 2025-08-20 15:00 * @Description: * @Version: **/ @Slf4j @Activate(group = {"provider"}) public class StraTransServiceRouter implements Router { public StraTransServiceRouter() { log.info("StraTransServiceRouter loaded successfully!"); } @Override public URL getUrl() { return null; } @Override public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException { log.info("Enter StraTransServiceRouter"); String interfaceName = invocation.getInvoker().getInterface().getName(); if ("ICondStraTransService".equals(interfaceName)) { Object[] args = invocation.getArguments(); if (args != null && args.length == 1) { String reqDtoJsonStr = JSON.toJSONString(args[0]); JSONObject reqDtoJsonObject = JSON.parseObject(reqDtoJsonStr); Integer strategyCode = reqDtoJsonObject.getInteger("strategyCode"); if (Objects.nonNull(strategyCode) && strategyCode.equals(DOM_GRID_COND_ORDER.getVal())) { // 网格策略大厅跟单请求,筛选Service注解group为gridHall的实现类 return invokers.stream().filter(tInvoker -> "gridHall".equals(tInvoker.getUrl().getParameter("group"))) .collect(Collectors.toList()); } else { // 非网格策略大厅跟单请求,筛选Service注解group不为gridHall的实现类 return invokers.stream().filter(tInvoker -> !"gridHall".equals(tInvoker.getUrl().getParameter("group"))) .collect(Collectors.toList()); } } } // 非ICondStraTransService接口,不做路由 return invokers; } @Override public int getPriority() { return 0; } @Override public int compareTo(Router o) { return 0; } } RouterFactory实现类: package com.htsc.gtp.quant.cm.domestic.router; import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.common.extension.Activate; import com.alibaba.dubbo.rpc.cluster.Router; import com.alibaba.dubbo.rpc.cluster.RouterFactory; import org.springframework.stereotype.Component; /** * @Project: gtp-quant-cm-domestic * @Author: 022679 * @CreateTime: 2025-08-20 18:16 * @Description: * @Version: **/ @Activate(group = {"provider"}) public class StraTransServiceRouterFactory implements RouterFactory { @Override public Router getRouter(URL url) { return new StraTransServiceRouter(); } } SPI配置: D:\JavaProject\gtp-quant\gtp-quant-cm-domestic\gtp-quant-cm-domestic-server\src\main\resources\META-INF\dubbo\com.alibaba.dubbo.rpc.cluster.Router straTransServiceRouter=com.htsc.gtp.quant.cm.domestic.router.StraTransServiceRouter D:\JavaProject\gtp-quant\gtp-quant-cm-domestic\gtp-quant-cm-domestic-server\src\main\resources\META-INF\dubbo\com.alibaba.dubbo.rpc.cluster.RouterFactory straTransServiceRouterFactory=com.htsc.gtp.quant.cm.domestic.router.StraTransServiceRouterFactory dubbo-config.xml: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <!-- 应用信息配置 --> <dubbo:application name="${dubbo.application.name}" owner="${dubbo.application.owner}" logger="${dubbo.application.logger}" /> <!-- 服务注册中心配置 --> <dubbo:registry id="dubbo_zookeeper" address="${dubbo.registry.address}" register="true" subscribe="true" check="false" file="${dubbo.application.name}" session="${dubbo.session.timeout}"/> <!-- 灰度服务注册中心配置 --> <dubbo:registry id="dubbo_grey_zookeeper" address="${dubbo.grey.registry.address}" register="true" subscribe="true" check="false" file="${dubbo.application.name}" session="${dubbo.session.timeout}"/> <!-- 监控中心配置 --> <!-- <dubbo:monitor protocol="${dubbo.monitor.protocol}" /> --> <!-- 服务协议&端口 --> <dubbo:protocol name="dubbo" port="${dubbo.dubbo.port}" /> <!-- dubbo:protocol name="dubbo" port="${dubbo.dubbo.port}" serialization="${dubbo.dubbo.serialization}" / --> <!-- 服务协议&端口 --> <dubbo:protocol name="rest" port="${dubbo.rest.port}" contextpath="${dubbo.rest.contextpath}" server="${dubbo.rest.server}" extension=""/> <!-- dubbo:service 默认配置 --> <dubbo:provider filter="rpcinfocollect,globalFilter,logFilter,traceFilter" validation="false" registry="dubbo_zookeeper" protocol="${dubbo.protocol}" payload="883886080" retries="${dubbo.retries}" timeout="${dubbo.session.timeout}" executes="${dubbo.executes}" actives="${dubbo.actives}" loadbalance="${dubbo.loadbalance}" threads="${dubbo.threads}" accepts="${dubbo.accepts}" /> <!-- dubbo:reference 默认配置 --> <dubbo:consumer filter="rpcinfocollect,traceFilter" validation="false" check="false" registry="dubbo_zookeeper" retries="${dubbo.retries}" timeout="${dubbo.session.timeout}" loadbalance="${dubbo.loadbalance}" /> <!-- 跨系统调用接口 --> <dubbo:reference id="custRegisterApi" interface="com.htsc.gtp.quant.cust.api.CustRegisterApi" version="1.0.0" registry="dubbo_zookeeper"/> <dubbo:reference id="acctManagerApi" interface="com.htsc.gtp.quant.cust.api.AcctManagerApi" version="1.0.0" registry="dubbo_zookeeper"/> <dubbo:reference id="equityManagerApi" interface="com.htsc.gtp.quant.cust.api.EquityManagerApi" version="1.0.0" registry="dubbo_zookeeper"/> <dubbo:reference id="abnormalCliQueryApi" interface="com.htsc.gtp.quant.cust.api.AbnormalCliQueryApi" version="1.0.0" registry="dubbo_zookeeper"/> <!--<dubbo:reference id="quantStaticInfoService" interface="com.htsc.gtp.pmdsproxy.api.QuantStaticInfoService" version="${prdt.dubbo.version}" registry="dubbo_zookeeper"/>--> <dubbo:reference id="strategyCondOrderQueryApi" interface="com.htsc.gtp.sem.dqs.api.StrategyCondOrderQueryApi" version="1.1.0" registry="dubbo_zookeeper"/> <dubbo:reference id="strategyCondOrderHisQueryApi" interface="com.htsc.gtp.sem.dqs.api.StrategyCondOrderHisQueryApi" version="1.1.0" registry="dubbo_zookeeper"/> <!--旧微服务dubbo接口--> <dubbo:reference id="oldMaQuantOrderService" interface = "com.htsc.uf.api.IMaQuantOrderService" version="1.1.8" registry="dubbo_grey_zookeeper"/> <dubbo:reference id="oldCondAcctService" interface = "com.htsc.uf.api.ICondAcctService" registry="dubbo_grey_zookeeper"/> <!-- 对外接口 --> <dubbo:service ref = "maQuantOrderService" interface = "com.htsc.gtp.quant.cm.domestic.api.IMaQuantOrderService" version="1.1.8" registry="dubbo_grey_zookeeper"/> <!-- <dubbo:service ref = "condOrdSuitService" interface = "com.htsc.uf.api.ICondOrdSuitService" version="1.1.8" />--> <dubbo:service ref = "condAcctService" interface = "com.htsc.gtp.quant.cm.domestic.api.ICondAcctService" registry="dubbo_grey_zookeeper"/> <!-- <dubbo:service ref = "maQuoteService" interface = "com.htsc.uf.api.IMaQuoteService" version="1.1.8" />--> <!-- <dubbo:service ref = "condOrdQryService" interface = "com.htsc.uf.api.ICondOrdQryService" version="1.1.8" /> --> <dubbo:service ref = "maManageService" interface = "com.htsc.gtp.quant.cm.domestic.api.IMaManageService" registry="dubbo_grey_zookeeper"/> <dubbo:service ref = "condStraTransServiceImpl" group="default" interface = "com.htsc.gtp.quant.cm.domestic.api.ICondStraTransService" registry="dubbo_grey_zookeeper"/> <bean id="condStraTransServiceImpl" class="com.htsc.gtp.quant.cm.domestic.api.impl.CondStraTransServiceImpl"/> <dubbo:service ref = "gridHallCondStraTransServiceImpl" group="gridHall" interface = "com.htsc.gtp.quant.cm.domestic.api.ICondStraTransService" registry="dubbo_grey_zookeeper"/> <bean id="gridHallCondStraTransServiceImpl" class="com.htsc.gtp.quant.cm.domestic.api.impl.GridHallCondStraTransServiceImpl"/> </beans>
最新发布
08-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值