16. Dubbo服务暴露 - 容器启动
1. 开篇
本文主要介绍Dubbo服务暴露过程——根据URL来启动对应的容器。
2. 导出URL
doExportUrlsFor1Protocol
方法主要是为每一个协议导出对应的URL,由于该方法太长了,就只截取一部分吧。
该方法的主要工作如下:
- 获取协议名称,如果为空,设置为
dubbo
协议。 - 设置
side
为provider
。 - 设置运行时参数,dubbo版本、时间戳、协议版本等。
- 将监控、应用、模块、提供者、协议、服务本身、元数据、接口方法、方法参数等信息放入map中。
- 如果是泛化服务,设置泛化服务相关信息。
- 根据服务接口找到对应的
Wrapper
类,拿到Wrapper
类中所有的方法名字,放入map。 - 获取
token
配置,放入map,token
可以在一定程度上防止人为调用dubbo服务。 - 将map中的信息放入服务元数据的
attachments
中。 - 获取
host
、port
并构造URL
。 - 通过
DubboSPI
获取ConfiguratorFactory
的实现类,该步骤可以可以对URL的内容进行更改或做一些定制化操作。 - 根据
scope
来判断是本地注册还是注册到注册中心,如果是none
则不进行导出,如果是local
代表导出到本地,仅供本地JVM
调用,但是也是会走完整的dubbo
流程的。 - 将服务的元数据信息放、到元数据中心。
- 通过代理工厂生成
Invoker
,并进行服务导出。
来看下这一步生成URL的格式,协议头已经换成dubbo
,这个URL将被注册到注册中心上去,同样的,如果消费者拿到这个URL也可以直接调用的。
dubbo://172.17.0.157:20880/org.apache.dubbo.demo.DemoService?anyhost=true&application=dubbo-demo-annotation-provider&bind.ip=172.17.0.157&bind.port=20880&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.apache.dubbo.demo.DemoService&methods=sayHello,sayHelloAsync&pid=87628&release=&service.name=ServiceBean:/org.apache.dubbo.demo.DemoService&side=provider×tamp=1670995605316
3. 根据协议导出
Exporter<?> exporter = PROTOCOL.export(wrapperInvoker);
PROTOCOL
是一个自适应扩展对象,之前讲过自适应扩展类的方法需要有URL参数或者参数的类里有getURL
方法,那么wrapperInvoker
里面的URL长什么样呢?由于太长了,省略一部分:
registry://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?xxxx
这个URL的协议头为registry
,所以实际调用的方法为RegistryProtocol#export
。
该方法根据originInvoker
获取注册中心的URL(格式为registry://xxx?xx=xx®istry=zookeeper
)以及提供者的URL(格式为dubbo://172.17.0.157:20880/org.apache.dubbo.demo.DemoService?xxxx
)。
根据服务提供者URL生成一个overrideSubscribeUrl
,该URL协议为provider://
,在服务提供者URL的基础上增加参数category=configurators&check=false
。overrideSubscribeUrl
为老Dubbo版本的动态配置监听URL。
根据providerUrl
、registryUrl
对参数进行简化,因为有些参数是没用的,没有必要放到注册中心,比如:monitor
、bind.ip
、bind.port
等,简化后生成要注册的URL,并注册到注册中心。
4. 启动容器
调用doLocalExport
方法,根据协议来启动具体的容器。
protocol.export
会根据方法参数中getURL的返回值,根据协议来确定调用哪个类,这里最终会调用到DubboProtocol#export
方法,在这个方法中会启动Netty
或Tomcat
等具体容器。
该方法主要工作过程如下:
- 根据URL获取服务Key一般为接口类名。
- 构造一个
DubboExporter
,并放入缓存。 - 开启
Netty
服务。 - 根据
Invoker
中配置的optimizer
参数获取扩展的自定义序列化处理类。
4.1 开启服务openServer
该方法先获取服务地址(ip:port),判断是否创建过服务,创建过的话直接进行reset,没有的话,则创建服务容器。
4.2 创建服务createServer
- 根据传进来的URL生成服务URL,该URL比原来新增加了
channel.readonly.sent=TRUE
、heartbeat=60000
、codec=dubbo
参数。 - 从URL中获取协议的服务器端实现类型,例如:dubbo协议的mina、netty等,http协议的jetty、tomcat等,默认为netty协议。
- 把创建好的Server进行返回。
4.3 启动Netty
最终会调用到NettyServer
类中的doOpen
方法,设置Netty
相关参数进行绑定启动Netty。
5. 后记
本文主要介绍Dubbo服务暴露过程——根据URL来启动对应的容器,下一篇将进行介绍是如何把URL注册到注册中心里去的。