Dubbo Invoker创建与服务引用解析

📅 2026/7/13 11:05:36
Dubbo Invoker创建与服务引用解析
1. 锂离子电池过压保护的必要性与挑战锂离子电池因其高能量密度和长循环寿命已成为便携式设备和储能系统的首选电源。但这类电池对工作电压极其敏感——单节电池的充电截止电压通常为4.2V±50mV超过这个范围就会引发电解液分解、电极材料氧化等连锁反应。我曾亲眼见过某款无人机电池因过压导致壳体鼓胀最终在充电过程中爆燃的案例。传统保护方案多采用MOSFET直接切断充电路径这种方式虽然简单粗暴但存在两个致命缺陷一是电压骤降可能损坏负载设备二是电池组中各单体电压不均衡时会以最低电压单体为标准提前终止充电造成容量浪费。TI的BQ29200芯片正是为解决这些问题而设计它通过动态均衡技术实现了软保护实测显示其可将电池组容量利用率提升15%-20%。2. BQ29200保护芯片的架构解析2.1 核心功能模块拆解这颗DFN-10封装的芯片内部集成了三大关键子系统电压监测单元包含两个独立ADC通道采样精度±15mV可实时检测两节串联电池的电压适用于7.4V标称电压系统平衡控制引擎当检测到某节电池电压超过4.25V可调时自动激活并联的泄放电阻以100mA典型电流进行能量耗散状态指示接口通过开漏输出的/ALERT引脚触发MCU中断典型响应延迟仅50μs2.2 关键外围电路设计要点在实际PCB布局时要特别注意以下三点采样走线必须采用Kelvin连接方式避免IR# 1. 概述本文分享服务引用的最后一部分创建 Invoker 对象。在 《精尽 Dubbo 源码分析 —— 服务引用一本地引用》 和 《精尽 Dubbo 源码分析 —— 服务引用二远程引用》 中我们已经看到Dubbo 基于Dubbo SPI机制调用对应的 Protocol 实现类创建不同的 Invoker 对象。本文我们将解析所有的 Protocol 实现类进行创建 Invoker 对象。涉及的 Protocol 实现类如下图旁白君整体过程和 《精尽 Dubbo 源码分析 —— 服务暴露》 差不多。下面我们逐一对每个 Protocol 进行解析。2. AbstractProtocolcom.alibaba.dubbo.rpc.protocol.AbstractProtocol实现 Protocol 接口Protocol 抽象类。代码如下/** * 服务暴露者集合 * * key: 服务键 {link #serviceKey(URL)} 或 {link URL#getServiceKey()} 。 * 不同协议会不同 */ protected final MapString, Exporter? exporterMap new ConcurrentHashMapString, Exporter?(); /** * 服务引用者集合 * * key: {link #serviceKey(URL)} */ //TODO SOFEREFENCE protected final MapString, Invoker? invokerMap new ConcurrentHashMapString, Invoker?(); public CollectionInvoker? getInvokers() { return Collections.unmodifiableCollection(invokerMap.values()); }exporterMap属性Exporter 集合。在 《精尽 Dubbo 源码分析 —— 服务暴露》 中我们已经看到使用它进行存储暴露的服务。invokerMap属性Invoker 集合。在本文中我们会看到使用它进行存储引用的服务。#getInvokers()方法获得 Invoker 集合。3. DubboProtocolcom.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol实现 AbstractProtocol 抽象类Dubbo 协议实现类。3.1 属性属性相关代码如下/** * 通信服务器集合 * * key: 服务器地址。例如192.168.1.1:20880 */ private final MapString, ExchangeServer serverMap new ConcurrentHashMapString, ExchangeServer(); // host:port,Exchanger /** * 通信客户端集合 * * key: 服务器地址。例如192.168.1.1:20880 */ private final MapString, ReferenceCountExchangeClient referenceClientMap new ConcurrentHashMapString, ReferenceCountExchangeClient(); // host:port,Exchanger /** * 通信客户端实例集合 * * key: 服务器地址。例如192.168.1.1:20880 */ private final ConcurrentMapString, LazyConnectExchangeClient ghostClientMap new ConcurrentHashMapString, LazyConnectExchangeClient(); /** * 服务器锁集合 */ private final ConcurrentMapString, Object locks new ConcurrentHashMapString, Object(); /** * Dubbo Protocol 的默认端口 */ private static final int DEFAULT_PORT 20880; /** * 共享的通信客户端 */ private ExchangeClient sharedClient;服务器相关serverMap属性通信服务器集合。键为服务器地址值为通信服务器 ExchangeServer 对象。DEFAULT_PORT静态属性Dubbo Protocol 的默认端口为 20880。客户端相关referenceClientMap属性通信客户端集合。键为服务器地址值为通信客户端 ExchangeClient 对象。在 《精尽 Dubbo 源码分析 —— 服务引用二远程引用》 中我们会看到#getClients(URL url)方法会创建 ExchangeClient 对象。referenceClientMap和ghostClientMap的相同点两者都是通信客户端集合。referenceClientMap和ghostClientMap的不同点前者是普通通信客户端集合后者是 LazyConnectExchangeClient 通信客户端集合。在#initClient(URL url)方法中我们可以看到两者的详细差异。ghostClientMap属性幽灵客户端集合。在#initClient(URL url)方法中我们可以看到它的具体用途。sharedClient属性共享的通信客户端。在#getSharedClient(URL url)方法中我们可以看到它的具体用途。locks属性锁集合。在#getSharedClient(URL url)方法中我们可以看到它的具体用途。3.2 refer本文涉及的#refer(ClassT serviceType, URL url)方法代码如下1: Override 2: public T InvokerT refer(ClassT serviceType, URL url) throws RpcException { 3: // 创建 DubboInvoker 对象 4: optimizeSerialization(url); 5: DubboInvokerT invoker new DubboInvokerT(serviceType, url, getClients(url), invokers); 6: // 添加到 invokerMap 7: invokers.add(invoker); 8: return invoker; 9: }第 4 行调用#optimizeSerialization(URL url)方法优化序列化。具体参见 《精尽 Dubbo 源码分析 —— 服务引用一本地引用》 的 「4.2 refer」 的【第 4 行】。第 5 行创建 DubboInvoker 对象。其中调用#getClients(URL url)方法获得 ExchangeClient 对象数组。第 7 行添加到invokerMap集合。第 8 行返回 Invoker 对象。3.2.1 getClients#getClients(URL url)方法获得 ExchangeClient 对象数组。代码如下1: private ExchangeClient[] getClients(URL url) { 2: // 是否共享连接 3: boolean service_share_connect false; 4: int connections url.getParameter(Constants.CONNECTIONS_KEY, 0); 5: // 如果未配置 connections 则共享连接 6: if (connections 0) { 7: service_share_connect true; 8: connections 1; 9: } 10: 11: ExchangeClient[] clients new ExchangeClient[connections]; 12: for (int i 0; i clients.length; i) { 13: if (service_share_connect) { 14: // 共享连接 15: clients[i] getSharedClient(url); 16: } else { 17: // 不共享连接创建新的连接 18: clients[i] initClient(url); 19: } 20: } 21: return clients; 22: }connections属性服务引用连接数。一般情况下我们不会设置connections配置项即service_share_connect true共享连接。第 15 行调用#getSharedClient(URL url)方法获得共享连接 ExchangeClient 对象。第 18 行调用#initClient(URL url)方法创建新的 ExchangeClient 对象。3.2.2 getSharedClient#getSharedClient(URL url)方法获得共享连接 ExchangeClient 对象。代码如下1: private ExchangeClient getSharedClient(URL url) { 2: // 从集合中查找 ReferenceCountExchangeClient 对象 3: String key url.getAddress(); 4: ReferenceCountExchangeClient client referenceClientMap.get(key); 5: if (client ! null) { 6: // 若未关闭增加引用计数返回它 7: if (!client.isClosed()) { 8: client.incrementAndGetCount(); 9: return client; 10: // 若已关闭移除 11: } else { 12: referenceClientMap.remove(key); 13: } 14: } 15: 16: // 同步创建 ExchangeClient 对象 17: synchronized (key.intern()) { // 保证 key 的原子性因为要获得锁进行创建 ExchangeClient 对象 18: // 创建 ExchangeClient 对象 19: ExchangeClient exchangeClient initClient(url); 20: // 将 ExchangeClient 对象包装创建 ReferenceCountExchangeClient 对象 21: client new ReferenceCountExchangeClient(exchangeClient, ghostClientMap); 22: // 添加到集合 23: referenceClientMap.put(key, client); 24: // 添加到幽灵集合 25: ghostClientMap.remove(key); 26: return client; 27: } 28: }第 3 至 4 行从referenceClientMap集合中查找 ReferenceCountExchangeClient 对象。第 5 至 14 行若 ReferenceCountExchangeClient 对象未关闭增加引用计数并返回它否则移除该 ReferenceCountExchangeClient 对象。第 17 行同步保证相同key顺序创建 ExchangeClient 对象。因为相同key意味着是同一个服务提供者。第 19 行调用#initClient(URL url)方法创建 ExchangeClient 对象。第 21 行将 ExchangeClient 对象包装创建 ReferenceCountExchangeClient 对象。第 23 行添加到referenceClientMap集合。第 25 行从ghostClientMap集合中移除对应的 LazyConnectExchangeClient 对象。第 26 行返回 ReferenceCountExchangeClient 对象。3.2.3 initClient#initClient(URL url)方法创建新的 ExchangeClient 对象。代码如下1: private ExchangeClient initClient(URL url) { 2: 3: // 校验 Client 的 Dubbo 版本 4: // client type setting. 5: String str url.getParameter(Constants.CLIENT_KEY, url.getParameter(Constants.SERVER_KEY, Constants.DEFAULT_REMOTING_CLIENT)); 6: // 添加编解码和心跳包参数 7: url url.addParameter(Constants.CODEC_KEY, DubboCodec.NAME); 8: // 默认开启 heartbeat 9: // enable heartbeat by default 10: url url.addParameterIfAbsent(Constants.HEARTBEAT_KEY, String.valueOf(Constants.DEFAULT_HEARTBEAT)); 11: 12: // BIO is not allowed since it has severe performance issue. 13: if (str ! null str.length() 0 !ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(str)) { 14: throw new RpcException(Unsupported client type: str , 15: supported client type is StringUtils.join(ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions(), )); 16: } 17: 18: ExchangeClient client; 19: try { 20: // 懒加载模式创建连接 21: // connection should be lazy 22: if (url.getParameter(Constants.LAZY_CONNECT_KEY, false)) { 23: client new LazyConnectExchangeClient(url, requestHandler); 24: // 直接创建连接 25: } else { 26: client Exchangers.connect(url, requestHandler); 27: } 28: } catch (RemotingException e) { 29: throw new RpcException(Fail to create remoting client for service( url ): e.getMessage(), e); 30: } 31: return client; 32: }第 5 行获得 Client 的 Dubbo 版本。目前有nettymina等等。第 7 行添加编解码的键为codec值为dubbo。第 10 行添加心跳间隔的键为heartbeat值为60000毫秒。第 12 至 16 行校验 Client 的 Dubbo 版本是否存在。若不存在抛出 RpcException 异常。第 18 至 31 行创建 ExchangeClient 对象。第 20 至 23 行配置lazy为懒加载模式创建 LazyConnectExchangeClient 对象。第 24 至 27 行调用Exchangers#connect(url, handler)方法创建 ExchangeClient 对象。第 31 行返回 ExchangeClient 对象。3.2.4 LazyConnectExchangeClientcom.alibaba.dubbo.rpc.protocol.dubbo.LazyConnectExchangeClient实现 ExchangeClient 接口支持懒加载的 ExchangeClient 实现类。构造方法/** * 通信客户端数组 */ private final URL url; /** * 通道处理器 */ private final ExchangeHandler requestHandler; /** * 连接锁 */ private final Lock connectLock new ReentrantLock(); /** * lazy connect 如果没有初始化时的连接状态 * * 当调用 {link #request(Object)} 方法时才创建连接 */ private final boolean initialState; /** * 通信客户端 */ private volatile ExchangeClient client; public LazyConnectExchangeClient(URL url, ExchangeHandler requestHandler) { // lazy connect, need set send.reconnect true, to avoid channel bad status. this.url url.addParameter(Constants.SEND_RECONNECT_KEY, Boolean.TRUE.toString()); this.requestHandler requestHandler; this.initialState url.getParameter(Constants.LAZY_CONNECT_KEY, Constants.DEFAULT_LAZY_CONNECT); }initialState属性初始状态。即是否延迟初始化客户端连接。通过url.lazy配置项设置默认为true。client属性通信客户端。在#request(Object request)方法中延迟初始化。requestOverride public CompletableFutureObject request(Object request) throws RemotingException { warning(); // 初始化客户端 initClient(); // 发起请求 return client.request(request); } private void initClient() throws RemotingException { // 已初始化跳过 if (client ! null) { return; } if (logger.isInfoEnabled()) { logger.info(Lazy connect to url); } // 获得锁 connectLock.lock(); try { // 已初始化跳过 if (client ! null) { return; } // 初始化 ExchangeClient 对象 this.client Exchangers.connect(url, requestHandler); } finally { connectLock.unlock(); } }在#request(Object request)方法中会调用#initClient()方法初始化 ExchangeClient 对象。之后调用ExchangeClient#request(Object request)方法发起请求。3.2.5 ReferenceCountExchangeClientcom.alibaba.dubbo.rpc.protocol.dubbo.ReferenceCountExchangeClient实现 ExchangeClient 接口支持引用计数的 ExchangeClient 实现类。构造方法/** * 幽灵客户端集合 */ private final static MapString, LazyConnectExchangeClient ghostClientMap new ConcurrentHashMapString, LazyConnectExchangeClient(); /** * 通信客户端 */ private final ExchangeClient client; /** * 引用计数 */ private final AtomicInteger refenceCount new AtomicInteger(0); public ReferenceCountExchangeClient(ExchangeClient client, ConcurrentMapString, LazyConnectExchangeClient ghostClientMap) { this.client client; // 增加引用计数 refenceCount.incrementAndGet(); // 添加到 ghostClientMap String key getKey(client); ghostClientMap.put(key, new LazyConnectExchangeClient(client.getUrl(), client.getExchangeHandler())); }ghostClientMap属性幽灵客户端集合。在构造方法中会创建对应的 LazyConnectExchangeClient 对象添加到ghostClientMap中。这样当该客户端关闭时可以幽灵访问。client属性通信客户端。refenceCount属性引用计数。包装Override public CompletableFutureObject request(Object request) throws RemotingException { return client.request(request); } Override public CompletableFutureObject request(Object request, int timeout) throws RemotingException { return client.request(request, timeout); } Override public URL getUrl() { return client.getUrl(); } Override public InetSocketAddress getRemoteAddress() { return client.getRemoteAddress(); } Override public ChannelHandler getChannelHandler() { return client.getChannelHandler(); } Override public ExchangeHandler getExchangeHandler() { return client.getExchangeHandler(); } Override public boolean isConnected() { return client.isConnected(); } Override public void reconnect() throws RemotingException { client.reconnect(); } Override public InetSocketAddress getLocalAddress() { return client.getLocalAddress(); } Override public boolean hasAttribute(String key) { return client.hasAttribute(key); } Override public void reset(URL url) { client.reset(url); } Override public void reset(Parameters parameters) { client.reset(parameters); } Override public Object getAttribute(String key) { return client.getAttribute(key); } Override public void setAttribute(String key, Object value) { client.setAttribute(key, value); } Override public void removeAttribute(String key) { client.removeAttribute(key); } Override public void send(Object message) throws RemotingException { client.send(message); } Override public void send(Object message, boolean sent) throws RemotingException { client.send(message, sent); }每个方法直接调用client对应的方法。关闭Override public void close() { close(0); } Override public void close(int timeout) { // 减少引用计数 if (refenceCount.decrementAndGet() 0) { // 关闭 client if (timeout 0) { client.close(); } else { client.close(timeout); } // 替换 client 为 LazyConnectExchangeClient 对象 client replaceWithLazyClient(); } } private LazyConnectExchangeClient replaceWithLazyClient() { // 创建 LazyConnectExchangeClient 对象 URL lazyUrl url.addParameter(Constants.LAZY_CONNECT_KEY, Boolean.TRUE.toString()) .addParameter(Constants.RECONNECT_KEY, Boolean.FALSE.toString()) .addParameter(Constants.SEND_RECONNECT_KEY, Boolean.TRUE.toString()) .addParameter(warning, Boolean.TRUE.toString()) .addParameter(LazyConnectExchangeClient.REQUEST_WITH_WARNING_KEY, true) .addParameter(_client_memo, referencecounthandler.replacewithlazyclient); // 获得 LazyConnectExchangeClient 对象 String key getKey(url); LazyConnectExchangeClient gclient ghostClientMap.get(key); if (gclient null || gclient.isClosed()) { gclient new LazyConnectExchangeClient(lazyUrl, client.getExchangeHandler()); ghostClientMap.put(key, gclient); } return gclient; } }当引用计数refenceCount减少到 0 时关闭client并替换成 LazyConnectExchangeClient 对象。3.2.6 DubboInvokercom.alibaba.dubbo.rpc.protocol.dubbo.DubboInvoker实现 AbstractInvoker 抽象类Dubbo Invoker 实现类。代码如下/** * 通信客户端数组 */ private final ExchangeClient[] clients; /** * 使用的 {link #clients} 的位置 */ private final AtomicPositiveInteger index new AtomicPositiveInteger(); /** * 版本 * * 用于 {link #clients} 重置 */ private final String version; /** * 销毁锁 */ private final ReentrantLock destroyLock new ReentrantLock(); /** * Invoker 集合 */ private final SetInvoker? invokers; public DubboInvoker(ClassT serviceType, URL url, ExchangeClient[] clients, SetInvoker? invokers) { super(serviceType, url, new String[]{Constants.INTERFACE_KEY, Constants.GROUP_KEY, Constants.TOKEN_KEY, Constants.TIMEOUT_KEY}); this.clients clients; // get version. this.version url.getParameter(Constants.VERSION_KEY, 0.0.0); this.invokers invokers; }clients属性通信客户端数组。在#doInvoke(Invocation invocation)方法中我们会看到循环调用实现负载均衡。index属性使用的clients的位置。在#doInvoke(Invocation invocation)方法中我们会看到循环调用实现负载均衡。version属性版本用于clients重置。详细解析见#isAvailable()方法。destroyLock属性销毁锁。在#destroy()方法中我们可以看到获得该锁保证关闭clients的原子性。invokers属性Invoker 集合。在#destroy()方法中我们可以看到移除自己。doInvoke1: Override 2: protected Result doInvoke(final Invocation invocation) throws Throwable { 3: RpcInvocation inv (RpcInvocation) invocation; 4: // 获得方法名 5: final String methodName RpcUtils.getMethodName(invocation); 6: // 设置 path version 到 invocation 中 7: inv.setAttachment(Constants.PATH_KEY, getUrl().getPath()); 8: inv.setAttachment(Constants.VERSION_KEY, version); 9: 10: // 获得 ExchangeClient 对象 11: ExchangeClient currentClient; 12: if (clients.length 1) { 13: currentClient clients[0]; 14: } else { 15: currentClient clients[index.getAndIncrement() % clients.length]; 16: } 17: // 远程调用 18: try { 19: // 获得是否异步调用 20: boolean isAsync RpcUtils.isAsync(getUrl(), invocation); 21: // 获得是否单向调用 22: boolean isOneway RpcUtils.isOneway(getUrl(), invocation); 23: // 获得超时时间 24: int timeout getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT); 25: // 单向调用 26: if (isOneway) { 27: boolean isSent getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false); 28: currentClient.send(inv, isSent); 29: RpcContext.getContext().setFuture(null); 30: return new RpcResult(); 31: // 异步调用 32: } else if (isAsync) { 33: ResponseFuture future currentClient.request(inv, timeout); 34: RpcContext.getContext().setFuture(new FutureAdapterObject(future)); 35: return new RpcResult(); 36: // 同步调用 37: } else { 38: RpcContext.getContext().setFuture(null); 39: return (Result) currentClient.request(inv, timeout).get(); 40: } 41: } catch (TimeoutException e) { 42: throw new RpcException(RpcException.TIMEOUT_EXCEPTION, Invoke remote method timeout. method: invocation.getMethodName() , provider: getUrl() , cause: e.getMessage(), e); 43: } catch (RemotingException e) { 44: throw new RpcException(RpcException.NETWORK_EXCEPTION, Failed to invoke remote method: invocation.getMethodName() , provider: getUrl() , cause: e.getMessage(), e); 45: } 46: }第 4 行调用RpcUtils#getMethodName(Invocation)方法获得方法名。第 5 至 8 行设置pathversion到invocation中。第 10 至 16 行获得 ExchangeClient 对象。根据clients的数量循环获得从而实现负载均衡。第 20 行调用RpcUtils#isAsync(url, invocation)方法判断是否异步调用。第 22 行调用RpcUtils#isOneway(url, invocation)方法判断是否异步调用。第 24 行获得远程调用超时时间。第 25 至 30 行单向调用。第 27 行调用URL#getMethodParameter(method, key, defaultValue)方法获得是否等待消息发出。sent配置项true等待消息发出消息发送失败将抛出异常。false不等待消息发出将消息放入 IO 队列即刻返回。默认值为false。第 28 行调用ExchangeClient#send(invocation, sent)方法发送请求不需要返回值。第 29 行调用RpcContext#setFuture(null)方法移除future。第 30 行创建 RpcResult 对象空返回。第 31 至 36 行异步调用。第 33 行调用ExchangeClient#request(invocation, timeout)方法发送请求需要返回值。第 34 行调用RpcContext#setFuture(future)方法设置future。第 35 行创建 RpcResult 对象空返回。第 37 至 40 行同步调用。第 38 行调用RpcContext#setFuture(null)方法移除future。第 39 行调用ExchangeClient#request(invocation, timeout)方法发送请求需要返回值。因为同步调用所以调用ResponseFuture#get()方法阻塞等待返回结果。第 41 至 45 行处理异常。isAvailableOverride public boolean isAvailable() { if (!super.isAvailable()) { return false; } for (ExchangeClient client : clients) { if (client.isConnected() // 校验连接状态 !client.hasAttribute(Constants.CHANNEL_ATTRIBUTE_READONLY_KEY)) { // 校验非只读状态 return true; } } return false; }当有一个 ExchangeClient 处于连接状态并且非只读时返回true表示处于可用状态。destroyOverride public void destroy() { // 防止重复销毁 if (super.isDestroyed()) { return; } else { // double check to avoid dup destroy destroyLock.lock(); try { if (super.isDestroyed()) { return; } // 销毁 super.destroy(); // 移除出 invokers 集合 if (invokers ! null) { invokers.remove(this); } // 销毁 ExchangeClient for (ExchangeClient client : clients) { try { client.close(); } catch (Throwable t) { logger.warn(t.getMessage(), t); } } } finally { destroyLock.unlock(); } } }第 6 至 16 行获得锁保证关闭clients的原子性。第 19 行调用super#destroy()方法标记自己已经销毁。第 21 至 23 行移除出invokers集合。第 25 至 31 行销毁 ExchangeClient 对象。3.3 destroy#destroy()方法销毁所有服务器关闭所有客户端。代码如下Override public void destroy() { // 销毁服务器 for (String key : new ArrayListString(serverMap.keySet())) { ExchangeServer server serverMap.remove(key); if (server ! null) { try { if (logger.isInfoEnabled()) { logger.info(Close dubbo server: server.getLocalAddress()); } server.close(ConfigUtils.getServerShutdownTimeout()); } catch (Throwable t) { logger.warn(t.getMessage(), t); } } } // 销毁客户端 for (String key : new ArrayListString(referenceClientMap.keySet())) { ExchangeClient client referenceClientMap.remove(key); if (client ! null) { try { if (logger.isInfoEnabled()) { logger.info(Close dubbo connect: client.getLocalAddress() -- client.getRemoteAddress()); } client.close(ConfigUtils.getServerShutdownTimeout()); } catch (Throwable t) { logger.warn(t.getMessage(), t); } } } // 销毁幽灵客户端 for (String key : new ArrayListString(ghostClientMap.keySet())) { ExchangeClient client ghostClientMap.remove(key); if (client ! null) { try { if (logger.isInfoEnabled()) { logger.info(Close dubbo connect: client.getLocalAddress() -- client.getRemoteAddress()); } client.close(ConfigUtils.getServerShutdownTimeout()); } catch (Throwable t) { logger.warn(t.getMessage(), t); } } } // 销毁 Invoker 集合 for (Invoker? invoker : new ArrayListInvoker?(invokers)) { if (invoker ! null) { invokers.remove(invoker); try { if (logger.isInfoEnabled()) { logger.info(Destroy reference: invoker.getUrl()); } invoker.destroy(); } catch (Throwable t) { logger.warn(t.getMessage(), t); } } } }分成四部分分别销毁服务器、客户端、幽灵客户端、Invoker 集合。4. InjvmProtocolcom.alibaba.dubbo.rpc.protocol.injvm.InjvmProtocol实现 AbstractProtocol 抽象类Injvm 协议实现类。构造方法/** * 单例。在 Dubbo SPI 中被初始化有且仅有一次。 */ private static InjvmProtocol INSTANCE; public Injvm