cnzz 网站域名怎么填,安卓应用市场免费下载安装,WordPress仿虎嗅主题,网站变灰色 html一、服务导出
当我们在某个接口的实现类上加上DubboService后#xff0c;就表示定义了一个Dubbo服务#xff0c;应用启动时Dubbo只要扫描到了DubboService#xff0c;就会解析对应的类#xff0c;得到服务相关的配置信息#xff0c;比如#xff1a;
1. 服务的类型…一、服务导出
当我们在某个接口的实现类上加上DubboService后就表示定义了一个Dubbo服务应用启动时Dubbo只要扫描到了DubboService就会解析对应的类得到服务相关的配置信息比如
1. 服务的类型也就是接口接口名就是服务名 2. 服务的具体实现类也就是当前类 3. 服务的version、timeout等信息就是DubboService中所定义的各种配置 解析完服务的配置信息后就会把这些配置信息封装成为一个ServiceConfig对象并调用其export()方法进行服务导出此时一个ServiceConfig对象就表示一个Dubbo服务。而所谓的服务导出主要就是完成三件事情
1. 确定服务的最终参数配置 2. 按不同协议启动对应的Server服务暴露 3. 将服务注册到注册中心服务注册
二、确定服务参数
一个Dubbo服务除开服务的名字也就是接口名还会有很多其他的属性比如超时时间、版本 号、服务所属应用名、所支持的协议及绑定的端口等众多信息。但是通常这些信息并不会全部在DubboService中进行定义比如一个Dubbo服务肯定是属于某个应用的而一个应用下可以有多个Dubbo服务所以我们可以在应用级别定义一些通用的配置比如协议。
我们在application.properties中定义 表示当前应用下所有的Dubbo服务都支持通过tri协议进行访问并且访问端口为20880所以在进行某个服务的服务导出时就需要将应用中的这些配置信息合并到当前服务的配置信息中。另外除开可以通过DubboService来配置服务我们也可以在配置中心对服务进行配置比如在 配置中心中配置
dubbo.service.org.apache.dubbo.samples.api.DemoService.timeout5000
表示当前服务的超时时间为5s。所以在服务导出时也需要从配置中心获取当前服务的配置如果在DubboService中也定义了timeout那么就用配置中心的覆盖掉配置中心的配置优先级更高。最终确定出服务的各种参数。
三、服务暴漏
服务暴露就是根据不同的协议启动不同的Server比如dubbo协议启动的都是Netty我们也主要是讲解dubbo协议。
protected synchronized void doExport() {if (unexported) {throw new IllegalStateException(The service interfaceClass.getName() has already unexported!);}if (exported) {return;}if (StringUtils.isEmpty(path)) {path interfaceName;}doExportUrls();exported();}
继续进入到doExportUrls()方法里面for循环ProtocolConfig进行服务的暴漏
for (ProtocolConfig protocolConfig : protocols) {String pathKey URL.buildKey(getContextPath(protocolConfig).map(p - p / path).orElse(path), group, version);// In case user specified path, register service one more time to map it to path.repository.registerService(pathKey, interfaceClass);doExportUrlsFor1Protocol(protocolConfig, registryURLs);
}
例如暴漏的协议可以是dubbotrihttp等本节我们只讨论dubbo协议的暴漏也是生产上用的最多的。下图就是当ProtocolConfig为dubbo协议时的信息 在服务暴漏的方法中有一个比较关键的入参即url通过buildUrl(protocolConfig, map)方法创建其实就是提取一些配置信息得到那么在后续exportUrl暴漏的过程中会通过dubbo的SPI机制获取到url上面的信息从而获取到真正的实现类完成服务的暴漏注册等过程这种做法在dubbo中屡见不鲜。
private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, ListURL registryURLs) {MapString, String map buildAttributes(protocolConfig);// remove null key and null valuemap.keySet().removeIf(key - key null || map.get(key) null);// init serviceMetadata attachmentsserviceMetadata.getAttachments().putAll(map);URL url buildUrl(protocolConfig, map);//20881这里赋值exportUrl(url, registryURLs);
}
可以看下url具体长什么样 一、本地暴漏
继续执行方法exportUrl这里会进行exportLocal也就是本地暴漏这里又重新生成了一个injvm协议的url通过这种方式的暴漏允许在同一个 JVM 中进行直连调用而不需要通过网络。 举个栗子DemoService定义如下
Service
public class DemoServiceImpl implements DemoService {Overridepublic String sayHello(String name) {return Hello name;}
}
如果同一个jvm内部服务消费者希望调用这个方法服务消费者通过 protocol“injvm”配置引用本地的 InJvm 服务。
Reference(protocol injvm)
private DemoService demoService;
使用 InJvm 协议暴露服务在 Dubbo 中具有多种用途包括提高性能、简化测试、方便应用内部模块间调用等。通过 InJvm 协议可以在同一个 JVM 内快速高效地调用服务无需网络开销适用场景广泛且灵活。
二、远程暴漏
我们重点讲解下远程暴漏也就是依据dubbo协议在exportRemote方法中最终来到最最核心的方法这里的ref就是我们的原始service类可以看到这里是通过动态代理的方式将其最终包装了一个Invoker可想而知最终执行业务逻辑的还是refdubbo的一些强大的功能扩展就是在Invoker进行再次封装Invoker也非常的重要。
private void doExportUrl(URL url, boolean withMetaData) {Invoker? invoker proxyFactory.getInvoker(ref, (Class) interfaceClass, url);if (withMetaData) {invoker new DelegateProviderMetaDataInvoker(invoker, this);}Exporter? exporter protocolSPI.export(invoker);exporters.add(exporter);
} 这行代码中的protocolSPI通过名字可以看出来他会动态的读取invoker属性中的url获取具体的类执行export方法所以我们要时刻查看invoker中的url属性
Exporter? exporter protocolSPI.export(invoker);
当前也即表示目前是registry协议的暴漏意思就是要将服务在注册中心就是会将服务的url注册到zk上。 很明显下面判断UrlUtils.isRegistry(invoker.getUrl())会等于true,最终来到RegistryProtocol类的export方法中
public T ExporterT export(InvokerT invoker) throws RpcException {if (UrlUtils.isRegistry(invoker.getUrl())) {return protocol.export(invoker);}FilterChainBuilder builder getFilterChainBuilder(invoker.getUrl());return protocol.export(builder.buildInvokerChain(invoker, SERVICE_FILTER_KEY, CommonConstants.PROVIDER));
}
这个方法中代码比较多我们只看几个关键步骤 1、doLocalExport当执行到这个方法的时候注意到此时url上的协议已经是dubbo了也就是说接下来会根据providerUrl上面的协议去进行服务暴露了。 2、Registry registry getRegistry(registryUrl)获取到注册中心实现类
3、register(registry, registeredProviderUrl)最终将url写到注册中心供服务消费者订阅使用
关于服务注册部分下面会进行详细解释我们继续看dubbo协议的服务暴漏那么就会来到DubboProtocol类中的export方法这里将invoker传递给了DubboExporter然后返回服务暴露的返回对象就是这个exporter。
下面还有一行openServer这里就是去启动netty因为要供消费者进行网络调用所以netty启动后作为服务端能够接受消费端的传过来的信息最终这些信息会传递到exporter中的invoker方法由invoker方法中的ref完成业务逻辑最终再通过netty发送给消费端。
public T ExporterT export(InvokerT invoker) throws RpcException {checkDestroyed();URL url invoker.getUrl();// export service.String key serviceKey(url);DubboExporterT exporter new DubboExporterT(invoker, key, exporterMap);openServer(url);optimizeSerialization(url);return exporter;
}
最终operServer会执行到下面的doOpen()方法可以看到这里是标准的netty启动流程
protected void doOpen() throws Throwable {bootstrap new ServerBootstrap();bossGroup NettyEventLoopFactory.eventLoopGroup(1, EVENT_LOOP_BOSS_POOL_NAME);workerGroup NettyEventLoopFactory.eventLoopGroup(getUrl().getPositiveParameter(IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS),EVENT_LOOP_WORKER_POOL_NAME);final NettyServerHandler nettyServerHandler new NettyServerHandler(getUrl(), this);channels nettyServerHandler.getChannels();boolean keepalive getUrl().getParameter(KEEP_ALIVE_KEY, Boolean.FALSE);bootstrap.group(bossGroup, workerGroup).channel(NettyEventLoopFactory.serverSocketChannelClass()).option(ChannelOption.SO_REUSEADDR, Boolean.TRUE).childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE).childOption(ChannelOption.SO_KEEPALIVE, keepalive).childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT).childHandler(new ChannelInitializerSocketChannel() {Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelFuture channelFuture bootstrap.bind(getBindAddress());channelFuture.syncUninterruptibly();channel channelFuture.channel();}
至此服务暴漏过程结束。
四、服务注册下个章节继续解析服务注册