1. 单相Boost升压变换器控制策略解析
作为一名电力电子工程师,我最近在项目中尝试将传统PI控制与现代模型预测控制(MPC)相结合,实现了单相Boost升压变换器的精准控制。这种混合控制方案在实际应用中展现出优异的动态响应和稳态性能,特别适合对输出电压精度要求较高的场合。
Boost变换器作为最基本的DC-DC拓扑之一,其输出电压总是高于输入电压。在传统控制方案中,我们通常采用双环控制# 1. 概述
本文分享 Protocol 层。在 dubbo-rpc-api 模块,protocol 包下实现,如下图所示:

本文对应 《Dubbo 开发指南 —— 协议扩展》 文档。
2. Protocol
com.alibaba.dubbo.rpc.Protocol ,协议接口。代码如下:
Java复制@SPI("dubbo")
public interface Protocol {
/**
* 获取缺省端口,当用户没有配置端口时使用。
*
* @return 缺省端口
*/
int getDefaultPort();
/**
* 暴露远程服务:<br>
* 1. 协议在接收请求时,应记录请求来源方地址信息:RpcContext.getContext().setRemoteAddress();<br>
* 2. export() 必须是幂等的,也就是暴露同一个 URL 的 Invoker 两次,和暴露一次没有区别。<br>
* 3. export() 传入的 Invoker 由框架实现并传入,协议不需要关心。<br>
*
* @param <T> 服务的类型
* @param invoker 服务的执行体
* @return exporter 暴露服务的引用,用于取消暴露
* @throws RpcException 当暴露服务出错时抛出,比如端口已占用
*/
@Adaptive
<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
/**
* 引用远程服务:<br>
* 1. 当用户调用 refer() 所返回的 Invoker 对象的 invoke() 方法时,协议需相应执行同 URL 远端 export() 传入的 Invoker 对象的 invoke() 方法。<br>
* 2. refer() 返回的 Invoker 由协议实现,协议通常需要在此 Invoker 中发送远程请求。<br>
* 3. 当 url 中有设置 check=false 时,连接失败不能抛出异常,并内部自动恢复。<br>
*
* @param <T> 服务的类型
* @param type 服务的类型
* @param url 远程服务的URL地址
* @return invoker 服务的本地代理
* @throws RpcException 当连接服务提供方失败时抛出
*/
@Adaptive
<T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
/**
* 释放协议:<br>
* 1. 取消该协议所有已经暴露和引用的服务。<br>
* 2. 释放协议所占用的所有资源,比如连接和端口。<br>
* 3. 协议在释放后,依然能暴露和引用新的服务。<br>
*/
void destroy();
}
@SPI("dubbo")注解,Dubbo SPI 拓展点,默认为"dubbo"协议。@Adaptive注解,基于 Dubbo SPI Adaptive 机制,加载对应的 Protocol 实现,使用URL.protocol属性。#getDefaultPort()方法,获得缺省端口。#export(invoker)方法,暴露远程服务。- 幂等,任意暴露同一个服务,等价于暴露一次。例如,多次调用
#export(invoker)方法,传入同一个 Invoker ( 例如,URL 相同 ),应该返回同一个 Exporter 对象。
- 幂等,任意暴露同一个服务,等价于暴露一次。例如,多次调用
#refer(url)方法,引用远程服务。#destroy()方法,释放所有已经暴露和引用的服务,并且释放协议所占用的所有资源,例如连接和端口。
2.1 ProtocolListenerWrapper
com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper ,实现 Protocol 接口,Protocol 监听器包装器实现类。代码如下:
Java复制public class ProtocolListenerWrapper implements Protocol {
private final Protocol protocol;
public ProtocolListenerWrapper(Protocol protocol) {
if (protocol == null) {
throw new IllegalArgumentException("protocol == null");
}
this.protocol = protocol;
}
public int getDefaultPort() {
return protocol.getDefaultPort();
}
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
// 注册中心
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
return protocol.export(invoker);
}
// 暴露服务,创建 Exporter 对象
Exporter<T> exporter = protocol.export(invoker);
// 获得 ExporterListener 数组
List<ExporterListener> listeners = Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class).getActivateExtension(invoker.getUrl(), Constants.EXPORTER_LISTENER_KEY));
// 创建带 ExporterListener 的 Exporter 对象
return new ListenerExporterWrapper<T>(exporter, listeners);
}
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
// 注册中心
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
return protocol.refer(type, url);
}
// 引用服务
Invoker<T> invoker = protocol.refer(type, url);
// 获得 InvokerListener 数组
List<InvokerListener> listeners = Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(InvokerListener.class).getActivateExtension(url, Constants.INVOKER_LISTENER_KEY));
// 创建带 InvokerListener 的 Invoker 对象
return new ListenerInvokerWrapper<T>(invoker, listeners);
}
public void destroy() {
protocol.destroy();
}
}
protocol属性,真正的 Protocol 对象。#export(invoker)方法,暴露服务。- 第 14 行:当服务引用是注册中心时,直接暴露,无需加监听器。
- 第 17 行:调用
protocol#export(invoker)方法,暴露服务,创建 Exporter 对象。 - 第 19 行:调用
ExtensionLoader#getActivateExtension(url, key, group)方法,获得监听器数组。 - 第 21 行:创建带 ExporterListener 的 ListenerExporterWrapper 对象。
#refer(type, url)方法,引用服务。- 第 26 行:当服务引用是注册中心时,直接引用,无需加监听器。
- 第 29 行:调用
protocol#refer(type, url)方法,引用服务,创建 Invoker 对象。 - 第 31 行:调用
ExtensionLoader#getActivateExtension(url, key, group)方法,获得监听器数组。 - 第 33 行:创建带 InvokerListener 的 ListenerInvokerWrapper 对象。
#destroy()方法,销毁真正的 Protocol 对象。
2.2 ProtocolFilterWrapper
com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper ,实现 Protocol 接口,Protocol 过滤器包装器实现类。代码如下:
Java复制public class ProtocolFilterWrapper implements Protocol {
private final Protocol protocol;
public ProtocolFilterWrapper(Protocol protocol) {
if (protocol == null) {
throw new IllegalArgumentException("protocol == null");
}
this.protocol = protocol;
}
public int getDefaultPort() {
return protocol.getDefaultPort();
}
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
// 注册中心
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
return protocol.export(invoker);
}
// 建立带有 Filter 过滤链的 Invoker ,再暴露服务
return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
}
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
// 注册中心
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
return protocol.refer(type, url);
}
// 引用服务,并返回 Invoker 对象
Invoker<T> invoker = protocol.refer(type, url);
// 建立带有 Filter 过滤链的 Invoker
return buildInvokerChain(invoker, Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER);
}
public void destroy() {
protocol.destroy();
}
/**
* 创建带 Filter 链的 Invoker 对象
*
* @param invoker Invoker 对象
* @param key 获取 URL 参数名
* @param group 分组
* @param <T> 泛型
* @return Invoker 对象
*/
private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
Invoker<T> last = invoker;
// 获得过滤器数组
List<Filter> filters = Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group));
// 倒序循环 Filter ,创建带 Filter 链的 Invoker 对象
if (!filters.isEmpty()) {
for (int i = filters.size() - 1; i >= 0; i--) {
final Filter filter = filters.get(i);
final Invoker<T> next = last;
last = new Invoker<T>() {
public Class<T> getInterface() {
return invoker.getInterface();
}
public URL getUrl() {
return invoker.getUrl();
}
public boolean isAvailable() {
return invoker.isAvailable();
}
public Result invoke(Invocation invocation) throws RpcException {
return filter.invoke(next, invocation);
}
public void destroy() {
invoker.destroy();
}
@Override
public String toString() {
return invoker.toString();
}
};
}
}
return last;
}
}
protocol属性,真正的 Protocol 对象。#export(invoker)方法,暴露服务。- 第 14 行:当服务引用是注册中心时,直接暴露,无需加过滤器。
- 第 17 行:调用
#buildInvokerChain(invoker, key, group)方法,创建带 Filter 链的 Invoker 对象。 - 第 18 行:调用
protocol#export(invoker)方法,暴露服务,创建 Exporter 对象。
#refer(type, url)方法,引用服务。- 第 22 行:当服务引用是注册中心时,直接引用,无需加过滤器。
- 第 25 行:调用
protocol#refer(type, url)方法,引用服务,创建 Invoker 对象。 - 第 27 行:调用
#buildInvokerChain(invoker, key, group)方法,创建带 Filter 链的 Invoker 对象。
#destroy()方法,销毁真正的 Protocol 对象。#buildInvokerChain(invoker, key, group)方法,创建带 Filter 链的 Invoker 对象。- 第 41 行:调用
ExtensionLoader#getActivateExtension(url, key, group)方法,获得过滤器数组。 - 第 44 至 69 行:倒序循环 Filter ,创建带 Filter 链的 Invoker 对象。为什么是倒序?例如我们有过滤器如下:
- A , B , C
- 最终得到的过滤链如下:
- A ( B ( C ( Invoker ) ) )
- 第 41 行:调用
2.3 AbstractProtocol
com.alibaba.dubbo.rpc.protocol.AbstractProtocol ,实现 Protocol 接口,Protocol 抽象类。代码如下:
Java复制public abstract class AbstractProtocol implements Protocol {
/**
* Exporter 集合
*
* key: 服务键 {@link #serviceKey(URL)} 或 {@link URL#getServiceKey()} 。
* 不同协议会不同
*/
protected final Map<String, Exporter<?>> exporterMap = new ConcurrentHashMap<String, Exporter<?>>();
/**
* Invoker 集合
*/
protected final Set<Invoker<?>> invokers = new ConcurrentHashSet<Invoker<?>>();
public Collection<Exporter<?>> getExporters() {
return Collections.unmodifiableCollection(exporterMap.values());
}
protected static String serviceKey(URL url) {
return serviceKey(url.getPort(), url.getPath(), url.getParameter(Constants.VERSION_KEY), url.getParameter(Constants.GROUP_KEY));
}
protected static String serviceKey(int port, String serviceName, String serviceVersion, String serviceGroup) {
return ProtocolUtils.serviceKey(port, serviceName, serviceVersion, serviceGroup);
}
@Override
public void destroy() {
// 销毁 exporter
for (Exporter<?> exporter : exporterMap.values()) {
exporter.destroy();
}
exporterMap.clear();
// 销毁 invoker
for (Invoker<?> invoker : invokers) {
invoker.destroy();
}
invokers.clear();
}
}
exporterMap属性,Exporter 集合。其中 key 为服务键,不同协议会不同,例如:- Dubbo Protocol 的
key = group/serviceName:serviceVersion:port。 - 其他协议,例如 Injvm ,
key = serviceName。
- Dubbo Protocol 的
invokers属性,Invoker 集合。#destroy()方法,销毁所有 Exporter 和 Invoker 。
2.4 AbstractProxyProtocol
com.alibaba.dubbo.rpc.protocol.AbstractProxyProtocol ,实现 AbstractProtocol 抽象类,Proxy 协议抽象类。主要实现远程调用,基于动态代理,将远程调用转换成本地调用。
2.4.1 构造方法
Java复制/**
* 需要代理的接口数组
*/
private final List<Class<?>> rpcInterfaces = new ArrayList<Class<?>>();
/**
* 代理执行器
*/
private ProxyFactory proxyFactory;
public AbstractProxyProtocol() {
}
public AbstractProxyProtocol(Class<?>... interfaces) {
for (Class<?> type : interfaces) {
addRpcInterfaces(type);
}
}
public void addRpcInterfaces(Class<?> type) {
if (type != null && type.isInterface()) {
rpcInterfaces.add(type);
}
}
public void setProxyFactory(ProxyFactory proxyFactory) {
this.proxyFactory = proxyFactory;
}
rpcInterfaces属性,需要代理的接口数组。通过构造方法,或#addRpcInterfaces(type)方法,可以添加。在#refer(type, url)方法中,会使用到该属性。proxyFactory属性,代理执行器。通过#setProxyFactory(proxyFactory)方法,可以设置。目前有两种实现方式:- JavassistProxyFactory
- JdkProxyFactory
2.4.2 export
Java复制@Override
@SuppressWarnings("unchecked")
public <T> Exporter<T> export(final Invoker<T> invoker) throws RpcException {
// 获得服务键
final String uri = serviceKey(invoker.getUrl());
// 获得 Exporter 对象。若已经暴露,直接返回。
Exporter<T> exporter = (Exporter<T>) exporterMap.get(uri);
if (exporter != null) {
return exporter;
}
// 创建 Runnable 对象
final Runnable runnable = doExport(proxyFactory.getProxy(invoker, true), invoker.getInterface(), invoker.getUrl());
// 创建 Exporter 对象
exporter = new AbstractExporter<T>(invoker) {
@Override
public void unexport() {
// 取消暴露
super.unexport();
exporterMap.remove(uri);
// 执行取消暴露的回调
if (runnable != null) {
try {
runnable.run();
} catch (Throwable t) {
logger.warn(t.getMessage(), t);
}
}
}
};
// 添加到 Exporter 集合
exporterMap.put(uri, exporter);
return exporter;
}
-
第 5 行:调用
#serviceKey(url)方法,获得服务键。 -
第 7 至 9 行:获得 Exporter 对象。若已经暴露,直接返回。
-
第 12 行:调用
ProxyFactory#getProxy(invoker)方法,获得 Proxy 对象。 -
第 12 行:调用
#doExport(impl, type, url)抽象方法,执行暴露服务,并返回取消暴露的回调 Runnable 。代码如下:Java复制/** * 执行暴露服务 * * @param impl 服务 Proxy 对象 * @param type 服务接口 * @param url URL * @param <T> 服务接口 * @return 取消暴露的回调 Runnable * @throws RpcException 当发生异常 */ protected abstract <T> Runnable doExport(T impl, Class<T> type, URL url) throws RpcException;- 子类实现该方法,不同协议不同实现。例如,HTTP 协议,需要启动服务器,并暴露服务。而 Injvm 协议,内存中完成即可。
-
第 14 至 29 行:创建 Exporter 对象。实现
#unexport()方法,取消暴露时,执行runnable的方法。 -
第 31 行:添加到 Exporter 集合。
2.4.3 refer
Java复制@Override
public <T> Invoker<T> refer(final Class<T> type, final URL url) throws RpcException {
// 获得远程服务的 Proxy 对象
final Invoker<T> target = proxyFactory.getInvoker(doRefer(type, url), type, url);
// 创建 Invoker 对象
Invoker<T> invoker = new AbstractInvoker<T>(type, url) {
@Override
protected Result doInvoke(Invocation invocation) throws Throwable {
try {
// 调用
Result result = target.invoke(invocation);
// 若返回结果带有异常,并且为本地做泛化调用,可能返回异常是远程的异常,通过序列化传输后,需要反序列化
Throwable e = result.getException();
if (e != null) {
for (Class<?> rpcInterface : rpcInterfaces) {
if (rpcInterface.isAssignableFrom(type)) {
try {
// 获得异常类
Throwable cause = e.getCause();
if (cause != null) {
Class<?> cls = cause.getClass();
// 非白名单的异常类,包装成 RuntimeException 返回
if (!RpcUtils.isGenericReturnType(invocation.getReturnType()) && !cls.isArray() && !(cause instanceof RuntimeException) && !(cause instanceof IOException) && !cls.isAssignableFrom(RemoteException.class)) {
return new RpcResult(new RuntimeException(StringUtils.toString(e)));
}
}
} catch (Throwable t) {
logger.warn(t.getMessage(), t);
}
break;
}
}
}
return result;
} catch (RpcException e) {
// 若是业务性质的异常,直接抛出
if (e.isBiz()) {
throw e;
}
// 抛出包装后的异常
throw new RpcException("Failed to invoke remote service: " + url + ", cause: " + e.getMessage(), e);
}
}
};
// 添加到 Invoker 集合
invokers.add(invoker);
return invoker;
}
-
第 4 行:调用
#doRefer(type, url)抽象方法,引用服务,并返回远程服务的 Service 对象。代码如下:Java复制/** * 执行引用服务 * * @param type 服务接口 * @param url URL * @param <T> 服务接口 * @return 远程服务的 Service 对象 * @throws RpcException 当发生异常 */ protected abstract <T> T doRefer(Class<T> type, URL url) throws RpcException;- 子类实现该方法,不同协议不同实现。例如,HTTP 协议,需要发起远程调用。而 Injvm 协议,内存中完成即可。
-
第 5 行:调用
ProxyFactory#getInvoker(proxy, type, url)方法,获得 Invoker 对象。通过该 Invoker 对象,使用者可以调用远程服务。 -
第 6 至 44 行:创建 Invoker 对象。通过该 Invoker 对象,使用者可以调用远程服务。
- 第 13 行:调用
target#invoke(invocation)方法,调用远程服务。 - 第 15 至 32 行:若返回结果带有异常,并且为本地做泛化调用,可能返回异常是远程的异常,通过序列化传输后,需要反序列化。并且,非白名单的异常类,包装成 RuntimeException 返回。白名单如下:
java.lang.RuntimeExceptionjava.io.IOExceptionjava.lang.Exceptionjava.lang.Throwablejava.lang.Errorjava.lang.RemoteException
- 第 36 至 39 行:若是业务性质的异常,直接抛出。
- 第 41 行:若是非业务性质的异常,包装成 RpcException 异常抛出。
- 第 13 行:调用
-
第 46 行:添加到 Invoker 集合。
3. Exporter
com.alibaba.dubbo.rpc.Exporter ,Exporter 接口。代码如下:
Java复制public interface Exporter<T> {
/**
* get invoker.
*
* 获得 Invoker 对象
*
* @return invoker
*/
Invoker<T> getInvoker();
/**
* unexport.
*
* 取消暴露服务
*
* @throws UnsupportedOperationException 当不支持时,抛出该异常
*/
void unexport();
}
- Exporter 内嵌 Invoker 对象。
- 可以通过
#unexport()方法,取消暴露服务。
3.1 AbstractExporter
com.alibaba.dubbo.rpc.protocol.AbstractExporter ,实现 Exporter 接口,Exporter 抽象类。代码如下:
Java复制public abstract class AbstractExporter<T> implements Exporter<T> {
protected final Logger logger = LoggerFactory.getLogger(getClass());
/**
* Invoker 对象
*/
private final Invoker<T> invoker;
/**
* 是否取消暴露服务
*/
private volatile boolean unexported = false;
public AbstractExporter(Invoker<T> invoker) {
if (invoker == null) {
throw new IllegalStateException("service invoker == null");
}
if (invoker.getInterface() == null) {
throw new IllegalStateException("service type == null");
}
if (invoker.getUrl() == null) {
throw new IllegalStateException("service url == null");
}
this.invoker = invoker;
}
@Override
public Invoker<T> getInvoker() {
return invoker;
}
@Override
public void unexport() {
// 已经取消暴露,直接返回
if (unexported) {
return;
}
// 设置取消暴露
unexported = true;
// 销毁 Invoker
getInvoker().destroy();
}
@Override
public String toString() {
return getInvoker().toString();
}
}
3.2 ListenerExporterWrapper
com.alibaba.dubbo.rpc.listener.ListenerExporterWrapper ,实现 Exporter 接口,Exporter 监听器包装器实现类。代码如下:
Java复制public class ListenerExporterWrapper<T> implements Exporter<T> {
/**
* 真实的 Exporter 对象
*/
private final Exporter<T> exporter;
/**
* Exporter 监听器数组
*/
private final List<ExporterListener> listeners;
public ListenerExporterWrapper(Exporter<T> exporter, List<ExporterListener> listeners) {
if (exporter == null) {
throw new IllegalArgumentException("exporter == null");
}
this.exporter = exporter;
this.listeners = listeners;
// 执行监听器
if (listeners != null && !listeners.isEmpty()) {
RuntimeException exception = null;
for (ExporterListener listener : listeners) {
if (listener != null) {
try {
listener.exported(this);
} catch (RuntimeException t) {
logger.error(t.getMessage(), t);
exception = t;
}
}
}
if (exception != null) {
throw exception;
}
}
}
@Override
public Invoker<T> getInvoker() {
return exporter.getInvoker();
}
@Override
public void unexport() {
try {
exporter.unexport();
} finally {
// 执行监听器
if (listeners != null && !listeners.isEmpty()) {
RuntimeException exception = null;
for (ExporterListener listener : listeners) {
if (listener != null) {
try {
listener.unexported(this);
} catch (RuntimeException t) {
logger.error(t.getMessage(), t);
exception = t;
}
}
}
if (exception != null) {
throw exception;
}
}
}
}
}
exporter属性,真实的 Exporter 对象。listeners属性,Exporter 监听器数组。- 构造方法,循环
listeners,执行ExporterListener#exported(exporter)方法。 #unexport()方法,循环listeners,执行ExporterListener#unexported(exporter)方法。
3.2.1 ExporterListener
com.alibaba.dubbo.rpc.ExporterListener ,Exporter 监听器接口。代码如下:
Java复制@SPI
public interface ExporterListener {
/**
* The exporter exported.
*
* 当服务暴露完成
*
* @param exporter
* @throws RpcException
* @see com.alibaba.dubbo.rpc.Protocol#export(Invoker)
*/
void exported(Exporter<?> exporter) throws RpcException;
/**
* The exporter unexported.
*
* 当服务取消暴露完成
*
* @param exporter
* @throws RpcException
* @see com.alibaba.dubbo.rpc.Exporter#unexport()
*/
void unexported(Exporter<?> exporter);
}
3.2.2 ExporterListenerAdapter
com.alibaba.dubbo.rpc.listener.ExporterListenerAdapter ,实现 ExporterListener 接口,ExporterListener 适配器抽象类。代码如下:
Java复制public abstract class ExporterListenerAdapter implements ExporterListener {
public void exported(Exporter<?> exporter) throws RpcException {
}
public void unexported(Exporter<?> exporter) throws RpcException {
}
}
3.3 DubboExporter
com.alibaba.dubbo.rpc.protocol.dubbo.DubboExporter ,实现 AbstractExporter 抽象类,Dubbo Exporter 实现类。代码如下:
Java复制public class DubboExporter<T> extends AbstractExporter<T> {
/**
* 服务键
*/
private final String key;
/**
* Exporter 集合
*
* key: 服务键
*
* 在 {@link DubboProtocol#exporterMap}
*/
private final Map<String, Exporter<?>> exporterMap;
public DubboExporter(Invoker<T> invoker, String key, Map<String, Exporter<?>> exporterMap) {
super(invoker);
this.key = key;
this.exporterMap = exporterMap;
}
@Override
public void unexport() {
// 取消暴露
super.unexport();
// 移除
exporterMap.remove(key);
}
}
key属性,服务键。exporterMap属性,Exporter 集合,在DubboProtocol#exporterMap属性。#unexport()方法,取消暴露,并移除自己到exporterMap中。
4. Invoker
com.alibaba.dubbo.rpc.Invoker ,Invoker 接口。代码如下:
Java复制public interface Invoker<T> extends Node {
/**
* get service interface.
*
* 获得服务接口
*
* @return service interface.
*/
Class<T> getInterface();
/**
* invoke.
*
* 调用服务
*
* @param invocation
* @return result
* @throws RpcException
*/
Result invoke(Invocation invocation) throws RpcException;
}
- Invoker 是服务域,它是 Dubbo 的核心模型,其它模型都向它靠扰,或转换成它。
- 它代表一个可执行体,可向它发起 invoke 调用。
- 它有可能是一个本地的实现,也可能是一个远程的实现,还可能一个集群实现。
4.1 AbstractInvoker
com.alibaba.dubbo.rpc.protocol.AbstractInvoker ,实现 Invoker 接口,Invoker 抽象类。代码如下:
Java复制public abstract class AbstractInvoker<T> implements Invoker<T> {
protected final Logger logger = LoggerFactory.getLogger(getClass());
/**
* 服务类型
*/
private final Class<T> type;
/**
* URL 对象
*/
private final URL url;
/**
* 公用的隐式传参。在 {@link #invoke(Invocation)} 方法中使用。
*/
private final Map<String, String> attachment;
/**
* 是否可用
*/
private volatile boolean available = true;
/**
* 是否销毁
*/
private volatile boolean destroyed = false;
public AbstractInvoker(Class<T> type, URL url) {
this(type, url, (Map<String, String>) null);
}
public AbstractInvoker(Class<T> type, URL url, String[] keys) {
this(type, url, convertAttachment(url, keys));
}
public AbstractInvoker(Class<T> type, URL url, Map<String, String> attachment) {
if (type == null) {
throw new IllegalArgumentException("service type == null");
}
if (url == null) {
throw new IllegalArgumentException("service url == null");
}
this.type = type;
this.url = url;
this.attachment = attachment == null ? null : Collections.unmodifiableMap(attachment);
}
private static Map<String, String> convertAttachment(URL url, String[] keys) {
if (keys == null || keys.length == 0) {
return null;
}
Map<String, String> attachment = new HashMap<String, String>();
// 遍历 key ,获得对应的属性值
for (String key : keys) {
String value = url.getParameter(key);
if (value != null && value.length() > 0) {
attachment.put(key, value);
}
}
return attachment;
}
@Override
public Class<T> getInterface() {
return type;
}
@Override
public URL getUrl() {
return url;
}
@Override
public boolean isAvailable() {
return available;
}
protected void setAvailable(boolean available) {
this.available = available;
}
@Override
public void destroy() {
if (destroyed) {
return;
}
destroyed = true;
setAvailable(false);
}
public boolean isDestroyed() {
return destroyed;
}
@Override
public String toString() {
return getInterface() + " -> " + (getUrl() == null ? "" : getUrl().toString());
}
@Override
public Result invoke(Invocation inv) throws RpcException {
if (destroyed) {
throw new RpcException("Rpc invoker for service " + this + " on consumer " + NetUtils.getLocalHost()
+ " is DESTROYED, can not be invoked any more!");
}
// 创建 RpcInvocation 对象
RpcInvocation invocation = (RpcInvocation) inv;
// 设置 `invoker` 属性
invocation.setInvoker(this);
// 添加公用的隐式传参
if (attachment != null && attachment.size() > 0) {
invocation.addAttachmentsIfAbsent(attachment);
}
// 添加自定义的隐式传参
Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();
if (contextAttachments != null && contextAttachments.size() != 0) {
invocation.addAttachments(contextAttachments);
}
// 设置 `async=true` ,若为异步方法
if (getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false)) {
invocation.setAttachment(Constants.ASYNC_KEY, Boolean.TRUE.toString());
}
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
try {
// 执行调用
return doInvoke(invocation);
} catch (InvocationTargetException e) { // biz exception
Throwable te = e.getTargetException();
if (te == null) {
return new RpcResult(e);
} else {
if (te instanceof RpcException) {
((RpcException) te).setCode(RpcException.BIZ_EXCEPTION);
}
return new RpcResult(te);
}
} catch (RpcException e) {
if (e.isBiz()) {
return new RpcResult(e);
} else {
throw e;
}
} catch (Throwable e) {
return new RpcResult(e);
}
}
protected abstract Result doInvoke(Invocation invocation) throws Throwable;
}
type属性,服务接口。url属性,服务提供者 URL 。attachment属性,公用的隐式传参。在#invoke(invocation)方法中,会添加到Invocation.attachments属性中。available属性,是否可用。destroyed属性,是否销毁。#invoke(invocation)方法,通用的执行调用