在AI Agent的开发过程中,我们常常面临多个相互冲突的优化目标。比如在游戏AI中需要同时考虑胜率和计算效率,在客服机器人中要平衡回答准确率和响应速度。传统单目标优化方法往往难以应对这种复杂场景,而多目标优化(Multi-Objective Optimization, MOO)技术为此提供了系统性的解决方案。
我最近在一个电商推荐系统Agent项目中深有体会:当同时优化点击率、转化率和用户停留时长时,单目标优化会导致指标严重失衡。通过引入多目标优化框架,最终实现了各项指标的均衡提升。下面分享一些实战经验。
在实际项目中,我们主要对比了以下几种算法:
| 算法类型 | 代表算法 | 适用场景 | 计算成本 | 解集质量 |
|---|---|---|---|---|
| 基于权重 | Weighted Sum | 目标维度<3 | 低 | 一般 |
| 进化算法 | NSGA-II | 复杂非凸问题 | 中高 | 优 |
| 分解方法 | MOEA/D | 大规模问题 | 中 | 良 |
| 元启发式 | SPEA2 | 高维目标 | 高 | 优 |
经过benchmark测试,我们最终选择NSGA-II作为基础框架,主要考虑:
设计良好的目标函数是多目标优化的关键。在我们的推荐Agent项目中,定义了三个核心目标:
python复制
本文分享 Protocol 层。在 dubbo-rpc-api 模块,com.alibaba.dubbo.rpc.protocol 包下实现,如下图所示:

老艿艿:本文对应 《Dubbo 开发指南 —— 协议扩展》 文档。
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) 方法,暴露远程服务。
ProtocolListener#export(Invoker) 方法,触发监听器的 #export(invoker) 方法。#refer(type, url) 方法,引用远程服务,创建 Invoker 对象。
ProtocolListener#refer(type, url) 方法,触发监听器的 #refer(type, url) 方法。#destroy() 方法,释放协议。
#destroy() 方法,释放每个协议的资源。com.alibaba.dubbo.rpc.protocol.AbstractProtocol ,实现 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 集合
*/
//TODO SOFEREFENCE
protected final Set<Invoker<?>> invokers = new ConcurrentHashSet<Invoker<?>>();
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.unexport();
}
exporterMap.clear();
// 循环销毁 Invoker
for (Invoker<?> invoker : invokers) {
if (invoker != null) {
invokers.remove(invoker);
invoker.destroy();
}
}
invokers.clear();
}
}
exporterMap 属性,Exporter 集合。其中 Key 为 服务键,不同协议会不同,例如:
URL#getServiceKey() 。URL#getPath() 。invokers 属性,Invoker 集合。#destroy() 方法,循环 exporterMap 和 invokers ,分别调用 Exporter#unexport() 和 Invoker#destroy() 方法,进行销毁。在 Protocol 中,每次暴露远程服务时,会创建一个 Exporter 对象。而每个 Exporter 对象,会包含一个 Invoker 对象。通过 Invoker 对象,可以执行调用服务。流程如下图:

com.alibaba.dubbo.rpc.protocol.AbstractExporter ,实现 Exporter 接口,Exporter 抽象类。代码如下:
Java复制public abstract class AbstractExporter<T> implements Exporter<T> {
/**
* Invoker 对象
*/
protected 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;
// 销毁
getInvoker().destroy();
}
@Override
public String toString() {
return getInvoker().toString();
}
}
com.alibaba.dubbo.rpc.protocol.AbstractInvoker ,实现 Invoker 接口,Invoker 抽象类。代码如下:
Java复制public abstract class AbstractInvoker<T> implements Invoker<T> {
/**
* 服务类型
*/
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 IllegalStateException("service type == null");
if (url == null)
throw new IllegalStateException("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()
+ " use dubbo version " + Version.getVersion()
+ " is DESTROYED, can not be invoked any more!");
}
// 创建 RpcInvocation 对象
RpcInvocation invocation = (RpcInvocation) inv;
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);
}
// 设置异步
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) 方法中,会添加到 RpcInvocation.attachments 属性中。available 属性,是否可用。destroyed 属性,是否销毁。#invoke(invocation) 实现方法,整体流程如下:
RpcInvocation.attachments 。RpcInvocation.attachments 。#doInvoke(invocation) 抽象方法,执行调用。该方法由子类实现,实现不同协议的调用逻辑。#doInvoke(invocation) 抽象方法,由子类实现,实现不同协议的调用逻辑。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;
}
@Override
public int getDefaultPort() {
return protocol.getDefaultPort();
}
@Override
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));
}
@Override
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 对象,包装 Filter 过滤链
return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER);
}
@Override
public void destroy() {
protocol.destroy();
}
private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
Invoker<T> last = invoker;
// 获得过滤器数组
List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
// 倒序循环,创建带过滤链的 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>() {
@Override
public Class<T> getInterface() {
return invoker.getInterface();
}
@Override
public URL getUrl() {
return invoker.getUrl();
}
@Override
public boolean isAvailable() {
return invoker.isAvailable();
}
@Override
public Result invoke(Invocation invocation) throws RpcException {
return filter.invoke(next, invocation);
}
@Override
public void destroy() {
invoker.destroy();
}
@Override
public String toString() {
return invoker.toString();
}
};
}
}
return last;
}
}
protocol 属性,协议对象。#export(invoker) 方法,暴露服务。
#buildInvokerChain(invoker, key, group) 方法,创建带 Filter 过滤链的 Invoker 对象。#refer(type, url) 方法,引用服务。
#buildInvokerChain(invoker, key, group) 方法,创建带 Filter 过滤链的 Invoker 对象。#buildInvokerChain(invoker, key, group) 静态方法,创建带 Filter 过滤链的 Invoker 对象。
ExtensionLoader 加载对应的 Filter 实现类数组。因为 @Activate 支持配置 group 和 key 属性,所以可以过滤。例如,key = Constants.CACHE_KEY 时,对应 CacheFilter 。A => B => C ,那么创建的顺序是 last = C => B => A ,最终返回的是 A ,形成 A => B => C 的调用链。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;
}
@Override
public int getDefaultPort() {
return protocol.getDefaultPort();
}
@Override
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
// 注册中心协议
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
return protocol.export(invoker);
}
// 暴露服务,创建 ExporterListener 监听器
return new ListenerExporterWrapper<T>(protocol.export(invoker),
Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class)
.getActivateExtension(invoker.getUrl(), Constants.EXPORTER_LISTENER_KEY)));
}
@Override
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
// 注册中心协议
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
return protocol.refer(type, url);
}
// 引用服务,创建 InvokerListener 监听器
return new ListenerInvokerWrapper<T>(protocol.refer(type, url),
Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(InvokerListener.class)
.getActivateExtension(url, Constants.INVOKER_LISTENER_KEY)));
}
@Override
public void destroy() {
protocol.destroy();
}
}
protocol 属性,协议对象。#export(invoker) 方法,暴露服务。
#refer(type, url) 方法,引用服务。
com.alibaba.dubbo.rpc.protocol.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 属性,ExporterListener 监听器数组。ExporterListener#exported(exporter) 方法。#unexport() 方法中,会执行 ExporterListener#unexported(exporter) 方法。com.alibaba.dubbo.rpc.protocol.ListenerInvokerWrapper ,实现 Invoker 接口,Invoker 监听器包装实现类。代码如下:
Java复制public class ListenerInvokerWrapper<T> implements Invoker<T> {
/**
* 真实的 Invoker 对象
*/
private final Invoker<T> invoker;
/**
* Invoker 监听器数组
*/
private final List<InvokerListener> listeners;
public ListenerInvokerWrapper(Invoker<T> invoker, List<InvokerListener> listeners) {
if (invoker == null) {
throw new IllegalArgumentException("invoker == null");
}
this.invoker = invoker;
this.listeners = listeners;
// 执行监听器
if (listeners != null && !listeners.isEmpty()) {
for (InvokerListener listener : listeners) {
if (listener != null) {
try {
listener.referred(invoker);
} catch (Throwable t) {
logger.error(t.getMessage(), t);
}
}
}
}
}
@Override
public Class<T> getInterface() {
return invoker.getInterface();
}
@Override
public URL getUrl() {
return invoker.getUrl();
}
@Override
public boolean isAvailable() {
return invoker.isAvailable();
}
@Override
public Result invoke(Invocation invocation) throws RpcException {
return invoker.invoke(invocation);
}
@Override
public void destroy() {
try {
invoker.destroy();
} finally {
// 执行监听器
if (listeners != null && !listeners.isEmpty()) {
for (InvokerListener listener : listeners) {
if (listener != null) {
try {
listener.destroyed(invoker);
} catch (Throwable t) {
logger.error(t.getMessage(), t);
}
}
}
}
}
}
@Override
public String toString() {
return getInterface() + " -> " + (getUrl() == null ? " " : getUrl().toString());
}
}
invoker 属性,真实的 Invoker 对象。listeners 属性,InvokerListener 监听器数组。InvokerListener#referred(invoker) 方法。#destroy() 方法中,会执行 InvokerListener#destroyed(invoker) 方法。com.alibaba.dubbo.rpc.protocol.injvm.InjvmProtocol ,实现 AbstractProtocol 抽象类,Injvm 协议实现类。
注意,Injvm 协议是 Dubbo 内部伪协议,执行本地调用,不会进行网络通信。相关文档,请参考 《Dubbo 用户指南 —— 本地调用》 。
Java复制/**
* 协议名
*/
public static final String NAME = Constants.LOCAL_PROTOCOL;
/**
* 默认端口
*/
public static final int DEFAULT_PORT = 0;
/**
* 单例。在 Dubbo SPI 中,被初始化,有且仅有一次。
*/
private static InjvmProtocol INSTANCE;
public InjvmProtocol() {
INSTANCE = this;
}
public static InjvmProtocol getInjvmProtocol() {
if (INSTANCE == null) {
ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(InjvmProtocol.NAME); // load
}
return INSTANCE;
}
NAME 静态属性,injvm ,协议名。DEFAULT_PORT 静态属性,默认端口为 0 。INSTANCE 静态属性,单例。通过 Dubbo SPI 加载创建,有且仅有一次。Java复制@Override
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
// 创建 InjvmExporter 对象
return new InjvmExporter<T>(invoker, invoker.getUrl().getServiceKey(), exporterMap);
}
AbstractProtocol.exporterMap 属性中。Java复制@Override
public <T> Invoker<T> refer(Class<T> serviceType, URL url) throws RpcException {
// 创建 InjvmInvoker 对象
return new InjvmInvoker<T>(serviceType, url, url.getServiceKey(), exporterMap);
}
com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol ,实现 AbstractProtocol 抽象类,Dubbo 协议实现类。
Java复制/**
* 协议名
*/
public static final String NAME = "dubbo";
/**
* 默认端口
*/
public static final int DEFAULT_PORT = 20880;
/**
* Dubbo 协议头长度
*/
private static final int HEADER_LENGTH = 16;
/**
* 消息体长度
*/
// header length.
protected static final int PAYLOAD_LENGTH = 8;
/**
* 魔法数
*/
protected static final short MAGIC = (short) 0xdabb;
/**
* 消息头掩码
*/
protected static final byte MAGIC_HIGH = Bytes.short2bytes(MAGIC)[0];
protected static final byte MAGIC_LOW = Bytes.short2bytes(MAGIC)[1];
/**
* 消息 Flag 位:是否是请求
*/
protected static final byte FLAG_REQUEST = (byte) 0x80;
/**
* 消息 Flag 位:是否是双向
*/
protected static final byte FLAG_TWOWAY = (byte) 0x40;
/**
* 消息 Flag 位:是否是事件
*/
protected static final byte FLAG_EVENT = (byte) 0x20;
/**
* 消息序列化类型掩码
*/
protected static final int SERIALIZATION_MASK = 0x1f;
/**
* 默认最大可接受数据大小
*/
private static final int DEFAULT_PAYLOAD = 8 * 1024 * 1024; // 8M
/**
* 交换处理器
*/
private ExchangeHandler requestHandler = new ExchangeHandlerAdapter() {
@Override
public Object reply(ExchangeChannel channel, Object message) throws RemotingException {
// ... 省略代码,在本文 7.4 小节详细解析。
}
@Override
public void received(Channel channel, Object message) throws RemotingException {
// ... 省略代码,在本文 7.4 小节详细解析。
}
@Override
public void connected(Channel channel) throws RemotingException {
this.invoke(new ChannelEventRunnable(channel, handler, ChannelState.CONNECTED));
}
@Override
public void disconnected(Channel channel) throws RemotingException {
this.invoke(new ChannelEventRunnable(channel, handler, ChannelState.DISCONNECTED));
}
private void invoke(Runnable runnable) {
// 获得线程池
ExecutorService executor = getSharedExecutorService();
try {
// 提交线程池,执行任务
executor.execute(runnable);
} catch (Throwable t) {
logger.error("Exception when execute method ." + t.getMessage(), t);
}
}
};
/**
* 服务器集合
*
* key: 服务器地址。例如:192.168.1.1:20880
*/
private final Map<String, ExchangeServer> serverMap = new ConcurrentHashMap<String, ExchangeServer>(); // <host:port,Exchanger>
/**
* 客户端集合
*
* key: 服务器地址。例如:192.168.1.1:20880
*/
private final Map<String, ReferenceCountExchangeClient> referenceClientMap = new ConcurrentHashMap<String, ReferenceCountExchangeClient>(); // <host:port,Exchanger>
/**
* 隐士参数集合
*/
private final ConcurrentMap<String, LazyConnectExchangeClient> ghostClientMap = new ConcurrentHashMap<String, LazyConnectExchangeClient>();
/**
* 线程池
*/
private ExecutorService executor;
/**
* 服务器实现
*/
private Server server;
// === 构造方法 ===
public DubboProtocol() {
}
public void setServer(Server server) {
this.server = server;
}
NAME 静态属性,dubbo ,协议名。DEFAULT_PORT 静态属性,默认端口为 20880 。HEADER_LENGTH 静态属性,Dubbo 协议头长度,16 字节。详细解析,见 《Dubbo 协议》 文档。requestHandler 属性,交换处理器,处理请求、消息、连接、断开连接等事件。详细解析,见本文 「7.4 requestHandler」 小节。serverMap 属性,服务器集合。其中,Key 为服务器地址,格式为 host:port 。referenceClientMap 属性,客户端集合。其中,Key 为服务器地址,格式为 host:port 。ghostClientMap 属性,隐士参数集合。详细解析,见本文 「7.3.2.1 initClient」 小节。executor 属性,线程池。详细解析,见本文 「7.5.1 getSharedExecutorService」 小节。server 属性,服务器实现。详细解析,见本文 「7.5.2 createServer」 小节。Java复制 1: @Override
2: public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
3: URL url = invoker.getUrl();
4:
5: // 创建 ServiceKey
6: String key = serviceKey(url);
7: // 创建 DubboExporter 对象
8: DubboExporter<T> exporter = new DubboExporter<T>(invoker, key, exporterMap);
9: // 添加到 `exporterMap` 中
10: exporterMap.put(key, exporter);
11:
12: // 【TODO 8026】 本地存根相关,先忽略
13: //export an stub service for dispatching event
14: Boolean isStubSupportEvent = url.getParameter(Constants.STUB_EVENT_KEY, Constants.DEFAULT_STUB_EVENT);
15: Boolean isCallbackservice = url.getParameter(Constants.IS_CALLBACK_SERVICE, false);
16: if (isStubSupportEvent && !isCallbackservice) {
17: String stubServiceMethods = url.getParameter(Constants.STUB_EVENT_METHODS_KEY);
18: if (stubServiceMethods == null || stubServiceMethods.length() == 0) {
19: if (logger.isWarnEnabled()) {
20: logger.warn(new IllegalStateException("consumer [" + url.getParameter(Constants.INTERFACE_KEY) +