前面两节,dubbo准备好了配置了,那么接下来就可以进行服务的暴露了,暴露的代码在RegistryProtocol#export中,RegistryProtocol这个协议会执行暴露,然后执行注册。
public <T> Exporter<T> com.alibaba.dubbo.registry.integration.RegistryProtocol#export(final Invoker<T> originInvoker) throws RpcException {
//export invoker
//暴露
final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker);
。。。。。。省略部分注册代码
//Ensure that a new exporter instance is returned every time export
return new DestroyableExporter<T>(exporter, originInvoker, overrideSubscribeUrl, registeredProviderUrl);
}
本地暴露
private <T> ExporterChangeableWrapper<T> com.alibaba.dubbo.registry.integration.RegistryProtocol#doLocalExport(final Invoker<T> originInvoker) {
//获取key,这个key是提供者url地址,按照我们上面配置例子,那么这里的key的值就是
//dubbo://192.168.56.1:20880/com.dubbo.service.UserService?anyhost=true&application=hello-world-app&bean.name=com.dubbo.service.UserService
//&bind.ip=192.168.56.1&bind.port=20880&dubbo=2.0.2&generic=false&interface=com.dubbo.service.UserService&methods=sayHello
//&pid=26392&side=provider×tamp=1567943599518
String key = getCacheKey(originInvoker);
//从缓存中获取已经暴露的包装对象,如果不存在,则需要暴露
ExporterChangeableWrapper<T> exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
if (exporter == null) {
synchronized (bounds) {
//双重检查
exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
if (exporter == null) {
//创建提供者Invoker,这个Invoker与原始的originInvoker相比,其对应url变成了提供者的url地址
//dubbo://192.168.56.1:20880/com.dubbo.service.UserService?...
final Invoker<?> invokerDelegete = new InvokerDelegete<T>(originInvoker, getProviderUrl(originInvoker));
//这里这个protocol是dubbo通过spi生成的一个类,它的名字叫做Protocol$Adaptive,它的方法内部会调用ExtensLoader去寻找能够符合
//条件的协议,我们例子中设置的提供者协议是dubbo,所以这里最终调用的协议是DubboProtocol
//这里的ExporterChangeableWrapper对象,主要是维护Exporter,与原始Invoker的关系,同时提供了unexport的方法用于取消服务的暴露
exporter = new ExporterChangeableWrapper<T>((Exporter<T>) protocol.export(invokerDelegete), originInvoker);
//缓存
bounds.put(key, exporter);
}
}
}
return exporter;
}
以下代码就是Adaptive类型的类去寻找适合处理当前协议的export方法
public com.alibaba.dubbo.rpc.Exporter com.alibaba.dubbo.rpc.Protocol$Adaptive#export(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException {
//invoker对象,就是我们上面创建的InvokerDelegete方法
if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
if (arg0.getUrl() == null)
throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
//提供者url
com.alibaba.dubbo.common.URL url = arg0.getUrl();
//很明显我们在配置例子中设置的暴露协议就是dubbo
String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
if (extName == null)
throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
//此处通过spi去获取合适的协议处理,很显然合适的处理就是DubboProtocol,但是Protocol还实现了三个装饰器
//他们分别为ProtocolListenerWrapper,ProtocolFilterWrapper,QosProtocolWrapper
//这个装饰器会依次包装ProtocolListenerWrapper,ProtocolFilterWrapper,QosProtocolWrapper,DubboProtocol
com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
return extension.export(arg0);
}
ProtocolListenerWrapper.export
public <T> Exporter<T> com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper#export(Invoker<T> invoker) throws RpcException {
//是否registry协议,如果是将会先暴露,在进行注册
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
return protocol.export(invoker);
}
//创建了一个ListenerExporterWrapper,看下它的构造方法
//(*1*),可以发现在创建ListenerExporterWrapper的时候就会触发暴露事件,如果再查看一下它的取消暴露方法,会触发取消暴露事件
//ExtensionLoader.getExtensionLoader(ExporterListener.class)方法去构建了
return new ListenerExporterWrapper<T>(protocol.export(invoker),
//获取暴露的监听器与被@Activate标注且符合条件的监听器,spi
//部分的代码我们将在分析SPI的时候分析
Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class)
.getActivateExtension(invoker.getUrl(), Constants.EXPORTER_LISTENER_KEY)));
}
//(*1*)
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;
}
}
}
ProtocolFilterWrapper#export
public <T> Exporter<T> com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper#export(Invoker<T> invoker) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
return protocol.export(invoker);
}
//创建过滤器链,一看就是构建了一个责任链
return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
}
构建过滤器链
private static <T> Invoker<T> com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper#buildInvokerChain(final Invoker<T> invoker, String key, String group) {
Invoker<T> last = invoker;
//获取符合条件的过滤器,与获取暴露监听器是一样的逻辑,不过对于提供者的group,默认是provider,消费者的就是consumer
List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
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;
}
形成了一个如下图的链条
QosProtocolWrapper#export
public <T> Exporter<T> com.alibaba.dubbo.qos.protocol.QosProtocolWrapper#export(Invoker<T> invoker) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
//用于启动命令服务,可以通过telnet命令查看消费者,提供者
//默认端口是2222
startQosServer(invoker.getUrl());
return protocol.export(invoker);
}
//暴露
return protocol.export(invoker);
}
public <T> Exporter<T> com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol#export(Invoker<T> invoker) throws RpcException {
//获取提供者暴露地址
URL url = invoker.getUrl();
// export service.
//group/serviceName:serviceVersion:端口
String key = serviceKey(url);
//创建Dubbo协议暴露者,维护这Invoker,key,exporterMap<key, Exporter>之间的关系
DubboExporter<T> exporter = new DubboExporter<T>(invoker, key, exporterMap);
exporterMap.put(key, exporter);
//export an stub service for dispatching event
Boolean isStubSupportEvent = url.getParameter(Constants.STUB_EVENT_KEY, Constants.DEFAULT_STUB_EVENT);
Boolean isCallbackservice = url.getParameter(Constants.IS_CALLBACK_SERVICE, false);
if (isStubSupportEvent && !isCallbackservice) {
String stubServiceMethods = url.getParameter(Constants.STUB_EVENT_METHODS_KEY);
if (stubServiceMethods == null || stubServiceMethods.length() == 0) {
if (logger.isWarnEnabled()) {
logger.warn(new IllegalStateException("consumer [" + url.getParameter(Constants.INTERFACE_KEY) +
"], has set stubproxy support event ,but no stub methods founded."));
}
} else {
stubServiceMethodsMap.put(url.getServiceKey(), stubServiceMethods);
}
}
//开启服务
openServer(url);
//优化序列化
//如果配置了SerializationOptimizer,那么会进行注册
//在序列化的时候就可以从SerializableClassRegistry的一个静态Map中获取
optimizeSerialization(url);
return exporter;
}
DubboProtocol#openServer
private void com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol#openServer(URL url) {
// find server.
//获取地址
//ip:port
String key = url.getAddress();
//client can export a service which's only for server to invoke
boolean isServer = url.getParameter(Constants.IS_SERVER_KEY, true);
if (isServer) {
//从缓存中获取
ExchangeServer server = serverMap.get(key);
if (server == null) {
//创建ExchangeServer
serverMap.put(key, createServer(url));
} else {
// server supports reset, use together with override
server.reset(url);
}
}
}
创建ExchangeServer
private ExchangeServer com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol#createServer(URL url) {
// send readonly event when server closes, it's enabled by default
//添加通道只读参数
url = url.addParameterIfAbsent(Constants.CHANNEL_READONLYEVENT_SENT_KEY, Boolean.TRUE.toString());
// enable heartbeat by default
//添加心跳周期参数
url = url.addParameterIfAbsent(Constants.HEARTBEAT_KEY, String.valueOf(Constants.DEFAULT_HEARTBEAT));
//使用netty还是mina等Transporter
String str = url.getParameter(Constants.SERVER_KEY, Constants.DEFAULT_REMOTING_SERVER);
//是否存在对应的Transporter extension
if (str != null && str.length() > 0 && !ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(str))
throw new RpcException("Unsupported server type: " + str + ", url: " + url);
//添加参数,codec -》 dubbo,用于激活筛选,在前面的监听器和过滤器都使用到了这样的筛选条件
//比如@Adaptive({Constants.CODEC_KEY})
url = url.addParameter(Constants.CODEC_KEY, DubboCodec.NAME);
ExchangeServer server;
try {
//(*1*)
server = Exchangers.bind(url, requestHandler);
} catch (RemotingException e) {
throw new RpcException("Fail to start server(url: " + url + ") " + e.getMessage(), e);
}
str = url.getParameter(Constants.CLIENT_KEY);
if (str != null && str.length() > 0) {
Set<String> supportedTypes = ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions();
if (!supportedTypes.contains(str)) {
throw new RpcException("Unsupported client type: " + str);
}
}
return server;
}
//(*1*)
public static ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
if (url == null) {
throw new IllegalArgumentException("url == null");
}
if (handler == null) {
throw new IllegalArgumentException("handler == null");
}
url = url.addParameterIfAbsent(Constants.CODEC_KEY, "exchange");
return getExchanger(url).bind(url, handler);
}
|
V
public static Exchanger getExchanger(URL url) {
//Constants.EXCHANGER_KEY = exchanger, Constants.DEFAULT_EXCHANGER = header
String type = url.getParameter(Constants.EXCHANGER_KEY, Constants.DEFAULT_EXCHANGER);
return getExchanger(type);
}
|
V
public static Exchanger getExchanger(String type) {
//因为没有指定exchanger参数,所以返回的Exchanger是HeaderExchanger
return ExtensionLoader.getExtensionLoader(Exchanger.class).getExtension(type);
}
HeaderExchanger的bind方法
public ExchangeServer HeaderExchanger#bind(URL url, ExchangeHandler handler) throws RemotingException {
//创建HeaderExchangeServer对象,在这个类的构造器中还进行心跳的启动
return new HeaderExchangeServer(Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler))));
}
public HeaderExchangeServer(Server server) {
if (server == null) {
throw new IllegalArgumentException("server == null");
}
this.server = server;
//获取心跳周期
this.heartbeat = server.getUrl().getParameter(Constants.HEARTBEAT_KEY, 0);
//超时时间默认是心跳周期的三倍
this.heartbeatTimeout = server.getUrl().getParameter(Constants.HEARTBEAT_TIMEOUT_KEY, heartbeat * 3);
//如果超时间少于心跳周期的2倍,抛错
if (heartbeatTimeout < heartbeat * 2) {
throw new IllegalStateException("heartbeatTimeout < heartbeatInterval * 2");
}
//启动心跳
startHeartbeatTimer();
}
private void startHeartbeatTimer() {
//先关掉可能已经启动的心跳,避免造成内存泄露和驻留无法关闭的心跳
stopHeartbeatTimer();
if (heartbeat > 0) {
//启动任务调度
heartbeatTimer = scheduled.scheduleWithFixedDelay(
new HeartBeatTask(new HeartBeatTask.ChannelProvider() {
@Override
public Collection<Channel> getChannels() {
return Collections.unmodifiableCollection(
HeaderExchangeServer.this.getChannels());
}
}, heartbeat, heartbeatTimeout),
heartbeat, heartbeat, TimeUnit.MILLISECONDS);
}
}
public void com.alibaba.dubbo.remoting.exchange.support.header.HeartBeatTask#run() {
try {
long now = System.currentTimeMillis();
for (Channel channel : channelProvider.getChannels()) {
if (channel.isClosed()) {
continue;
}
try {
Long lastRead = (Long) channel.getAttribute(
HeaderExchangeHandler.KEY_READ_TIMESTAMP);
Long lastWrite = (Long) channel.getAttribute(
HeaderExchangeHandler.KEY_WRITE_TIMESTAMP);
if ((lastRead != null && now - lastRead > heartbeat)
|| (lastWrite != null && now - lastWrite > heartbeat)) {
//发送心跳
Request req = new Request();
req.setVersion(Version.getProtocolVersion());
req.setTwoWay(true);
req.setEvent(Request.HEARTBEAT_EVENT);
channel.send(req);
。。。。。。省略日志
}
//心跳超时
if (lastRead != null && now - lastRead > heartbeatTimeout) {
//如果是客户端通道,尝试重连
if (channel instanceof Client) {
try {
//重连
((Client) channel).reconnect();
} catch (Exception e) {
//do nothing
}
} else {
//服务通道挂了,没得说,关闭
channel.close();
}
}
} catch (Throwable t) {
logger.warn("Exception when heartbeat to remote channel " + channel.getRemoteAddress(), t);
}
}
} catch (Throwable t) {
logger.warn("Unhandled exception when heartbeat, cause: " + t.getMessage(), t);
}
}
我们继续看到Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler)))
//HeaderExchangeHandler:在每次通道动作中都会进行记录时间,以便心跳能够进行时间判断
//DecodeHandler:解码处理,当接收消息的时候会对消息进行解码
//handler:这个是在DubboProtocol中定义的一个内部类,对于这个对象,我们等会会分析它的reply方法
Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler)))
public Server com.alibaba.dubbo.remoting.transport.netty4.NettyTransporter#bind(URL url, ChannelHandler listener) throws RemotingException {
return new NettyServer(url, listener);
}
|
V
public NettyServer(URL url, ChannelHandler handler) throws RemotingException {
//url:提供者URL, ExecutorUtil.setThreadName:设置线程池名字,
super(url, ChannelHandlers.wrap(handler, ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME)));
}
//其中ChannelHandlers.wrap最终调用了以下方法
protected ChannelHandler com.alibaba.dubbo.remoting.transport.dispatcher.ChannelHandlers#wrapInternal(ChannelHandler handler, URL url) {
//首先通过spi的方式创建了AllChannelHandler,这个是一个带有线程池的通道处理器,它由AllDispatcher分发器创建
//再次被HeartbeatHandler装饰,它的作用就是通道每个动作都会发生时间的更新,断连时清除时间
//最后被MultiMessageHandler装饰,它的作用就是用于处理一次性传递多个message的情况
return new MultiMessageHandler(new HeartbeatHandler(ExtensionLoader.getExtensionLoader(Dispatcher.class)
.getAdaptiveExtension().dispatch(handler, url)));
}
继续分析NettyServer的构造
public NettyServer(URL url, ChannelHandler handler) throws RemotingException {
//url:提供者URL, ExecutorUtil.setThreadName:设置线程池名字,
super(url, ChannelHandlers.wrap(handler, ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME)));
}
|
V
public AbstractServer(URL url, ChannelHandler handler) throws RemotingException {
super(url, handler);
//ip:port
localAddress = getUrl().toInetSocketAddress();
//获取需要绑定的主机地址
String bindIp = getUrl().getParameter(Constants.BIND_IP_KEY, getUrl().getHost());
//端口
int bindPort = getUrl().getParameter(Constants.BIND_PORT_KEY, getUrl().getPort());
if (url.getParameter(Constants.ANYHOST_KEY, false) || NetUtils.isInvalidLocalHost(bindIp)) {
bindIp = NetUtils.ANYHOST;
}
bindAddress = new InetSocketAddress(bindIp, bindPort);
//通道参数,接收队列最大个数
this.accepts = url.getParameter(Constants.ACCEPTS_KEY, Constants.DEFAULT_ACCEPTS);
//空闲超时还进
this.idleTimeout = url.getParameter(Constants.IDLE_TIMEOUT_KEY, Constants.DEFAULT_IDLE_TIMEOUT);
try {
//打开通道服务
doOpen();
if (logger.isInfoEnabled()) {
logger.info("Start " + getClass().getSimpleName() + " bind " + getBindAddress() + ", export " + getLocalAddress());
}
} catch (Throwable t) {
throw new RemotingException(url.toInetSocketAddress(), null, "Failed to bind " + getClass().getSimpleName()
+ " on " + getLocalAddress() + ", cause: " + t.getMessage(), t);
}
//fixme replace this with better method
//数据存储,获取默认的扩展,目前只有一个实现SimpleDataStore
//它使用ConcurrentMap<String, ConcurrentMap<String, Object>> data =
new ConcurrentHashMap<String, ConcurrentMap<String, Object>>()
//存储数据
DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();
//获取线程池对象
executor = (ExecutorService) dataStore.get(Constants.EXECUTOR_SERVICE_COMPONENT_KEY, Integer.toString(url.getPort()));
}
|
V
public AbstractEndpoint(URL url, ChannelHandler handler) {
super(url, handler);
this.codec = getChannelCodec(url);
this.timeout = url.getPositiveParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
this.connectTimeout = url.getPositiveParameter(Constants.CONNECT_TIMEOUT_KEY, Constants.DEFAULT_CONNECT_TIMEOUT);
}
|
V
public AbstractPeer(URL url, ChannelHandler handler) {
if (url == null) {
throw new IllegalArgumentException("url == null");
}
if (handler == null) {
throw new IllegalArgumentException("handler == null");
}
this.url = url;
this.handler = handler;
}
打开通道服务
protected void com.alibaba.dubbo.remoting.transport.netty4.NettyServer#doOpen() throws Throwable {
//netty的服务启动类ServerBootstrap
bootstrap = new ServerBootstrap();
//boss事件执行循环组
bossGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("NettyServerBoss", true));
//设置工作事件执行循环组
workerGroup = new NioEventLoopGroup(getUrl().getPositiveParameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS),
new DefaultThreadFactory("NettyServerWorker", true));
//netty的通道处理
final NettyServerHandler nettyServerHandler = new NettyServerHandler(getUrl(), this);
channels = nettyServerHandler.getChannels();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE)
.childOption(ChannelOption.SO_REUSEADDR, Boolean.TRUE)
.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
//初始化客户端通道时,注册到客户端ChannelPipeline中
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this);
ch.pipeline()//.addLast("logging",new LoggingHandler(LogLevel.INFO))//for debug
//添加dubbo的解码器
.addLast("decoder", adapter.getDecoder())
//添加编码器
.addLast("encoder", adapter.getEncoder())
//添加通道处理器
.addLast("handler", nettyServerHandler);
}
});
// bind
ChannelFuture channelFuture = bootstrap.bind(getBindAddress());
channelFuture.syncUninterruptibly();
channel = channelFuture.channel();
}
下一节我们开始服务的注册
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?