Dubbo是阿里巴巴开源的一个分布式服务框架,在阿里内部和其他公司都有广泛的应用,是目前比较成熟的一个服务框架。笔者将从源码层面对Dubbo进行分析,学习其中优秀的设计。
经过数年的沉淀,Dubbo整体的设计和抽象已非常完善,这里介绍的Provider启动就涉及到了多个抽象模型。本文使用的版本为2.5.3。
首先,当发布一个服务的Server时,我们需要编写一个Spring配置文件。
1
2
3
4
5
6
7
|
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<beans
xmlns
=
"..."
>
<dubbo:application
name
=
"hello-world-app"
/>
<dubbo:protocol
name
=
"dubbo"
port
=
"20880"
/>
<dubbo:service
interface
=
"net.beamlight.dubbo.service.DemoService"
ref
=
"demoService"
registry
=
"N/A"
/>
<bean
id
=
"demoService"
class
=
"net.beamlight.dubbo.provider.DemoServiceImpl"
/>
</beans>
|
其中关键的一行为<dubbo:service …>,这里使用了扩展的Spring Schema,相关定义在Dubbo jar包META-INF目录下的spring.handlers、spring.schemas、dubbo.xsd中。指定的配置解析器为com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler,所以它也就成了启动provider的“应用程序入口”
1
2
3
4
5
|
public
void
init
(
)
{
.
.
.
registerBeanDefinitionParser
(
"service"
,
new
DubboBeanDefinitionParser
(
ServiceBean
.
class
,
true
)
)
;
.
.
.
}
|
DubboNamespaceHandler的逻辑很简单,就是将xml文件中的配置信息转换成对应的bean,继续看关键的com.alibaba.dubbo.config.spring.ServiceBean
1
2
3
4
5
6
7
|
@SuppressWarnings
(
{
"unchecked"
,
"deprecation"
}
)
public
void
afterPropertiesSet
(
)
throws
Exception
{
.
.
.
if
(
!
isDelay
(
)
)
{
export
(
)
;
}
}
|
经过大段配置代码后来到父类ServiceConfig的export()方法,它将启动负责provider网络通信的Server并将服务地址发布出去。最终调用到doExportUrlsFor1Protocol()
1
2
3
4
5
6
7
8
9
|
private
static
final
Protocol
protocol
=
ExtensionLoader
.
getExtensionLoader
(
Protocol
.
class
)
.
getAdaptiveExtension
(
)
;
private
void
doExportUrlsFor1Protocol
(
ProtocolConfig
protocolConfig
,
List
<URL>
registryURLs
)
{
.
.
.
Invoker
<?
>
invoker
=
proxyFactory
.
getInvoker
(
ref
,
(
Class
)
interfaceClass
,
url
)
;
Exporter
<?
>
exporter
=
protocol
.
export
(
invoker
)
;
exporters
.
add
(
exporter
)
;
.
.
.
}
|
- Invoker – 执行具体的远程调用
- Protocol – 服务地址的发布和订阅
- Exporter – 暴露服务的引用,或取消暴露
Protocol的具体实现类由配置指定,默认创建一个DubboProtocol,其export()方法转到openServer()与createServer()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
private
ExchangeHandler
requestHandler
=
new
ExchangeHandlerAdapter
(
)
{
.
.
.
}
;
private
ExchangeServer
createServer
(
URL
url
)
{
.
.
.
ExchangeServer
server
;
try
{
server
=
Exchangers
.
bind
(
url
,
requestHandler
)
;
}
catch
(
RemotingException
e
)
{
throw
new
RpcException
(
"Fail to start server(url: "
+
url
+
") "
+
e
.
getMessage
(
)
,
e
)
;
}
.
.
.
return
server
;
}
|
requestHandler包含通信协议的主要处理逻辑,而server的创建来自Exchangers
1
2
3
4
|
public
static
ExchangeServer
bind
(
URL
url
,
ExchangeHandler
handler
)
throws
RemotingException
{
.
.
.
return
getExchanger
(
url
)
.
bind
(
url
,
handler
)
;
}
|
getExchanger()获取的实例也来源于配置,默认返回HeaderExchanger
1
2
3
4
5
6
7
8
9
10
|
public
class
HeaderExchanger
implements
Exchanger
{
public
ExchangeClient
connect
(
URL
url
,
ExchangeHandler
handler
)
throws
RemotingException
{
return
new
HeaderExchangeClient
(
Transporters
.
connect
(
url
,
new
DecodeHandler
(
new
HeaderExchangeHandler
(
handler
)
)
)
)
;
}
public
ExchangeServer
bind
(
URL
url
,
ExchangeHandler
handler
)
throws
RemotingException
{
return
new
HeaderExchangeServer
(
Transporters
.
bind
(
url
,
new
DecodeHandler
(
new
HeaderExchangeHandler
(
handler
)
)
)
)
;
}
}
|
可以看到Server与Client实例均是在这里创建的,HeaderExchangeServer需要一个Server类型的参数,来自Transporters.bind()
1
2
3
4
|
public
static
Server
bind
(
URL
url
,
ChannelHandler
.
.
.
handlers
)
throws
RemotingException
{
.
.
.
return
getTransporter
(
)
.
bind
(
url
,
handler
)
;
}
|
getTransporter()获取的实例来源于配置,默认返回一个NettyTransporter
1
2
3
4
5
6
7
8
9
10
|
public
class
NettyTransporter
implements
Transporter
{
public
Server
bind
(
URL
url
,
ChannelHandler
listener
)
throws
RemotingException
{
return
new
NettyServer
(
url
,
listener
)
;
}
public
Client
connect
(
URL
url
,
ChannelHandler
listener
)
throws
RemotingException
{
return
new
NettyClient
(
url
,
listener
)
;
}
}
|
最终来到了NettyServer,在它的doOpen()方法中看到了我们熟悉的Netty Bootstrap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
public
class
NettyServer
extends
AbstractServer
implements
Server
{
public
NettyServer
(
URL
url
,
ChannelHandler
handler
)
throws
RemotingException
{
super
(
url
,
ChannelHandlers
.
wrap
(
handler
,
ExecutorUtil
.
setThreadName
(
url
,
SERVER_THREAD_POOL_NAME
)
)
)
;
}
@Override
protected
void
doOpen
(
)
throws
Throwable
{
NettyHelper
.
setNettyLoggerFactory
(
)
;
ExecutorService
boss
=
Executors
.
newCachedThreadPool
(
new
NamedThreadFactory
(
"NettyServerBoss"
,
true
)
)
;
ExecutorService
worker
=
Executors
.
newCachedThreadPool
(
new
NamedThreadFactory
(
"NettyServerWorker"
,
true
)
)
;
ChannelFactory
channelFactory
=
new
NioServerSocketChannelFactory
(
boss
,
worker
,
getUrl
(
)
.
getPositiveParameter
(
Constants
.
IO_THREADS_KEY
,
Constants
.
DEFAULT_IO_THREADS
)
)
;
bootstrap
=
new
ServerBootstrap
(
channelFactory
)
;
final
NettyHandler
nettyHandler
=
new
NettyHandler
(
getUrl
(
)
,
this
)
;
channels
=
nettyHandler
.
getChannels
(
)
;
bootstrap
.
setPipelineFactory
(
new
ChannelPipelineFactory
(
)
{
public
ChannelPipeline
getPipeline
(
)
{
NettyCodecAdapter
adapter
=
new
NettyCodecAdapter
(
getCodec
(
)
,
getUrl
(
)
,
NettyServer
.
this
)
;
ChannelPipeline
pipeline
=
Channels
.
pipeline
(
)
;
pipeline
.
addLast
(
"decoder"
,
adapter
.
getDecoder
(
)
)
;
pipeline
.
addLast
(
"encoder"
,
adapter
.
getEncoder
(
)
)
;
pipeline
.
addLast
(
"handler"
,
nettyHandler
)
;
return
pipeline
;
}
}
)
;
// bind
channel
=
bootstrap
.
bind
(
getBindAddress
(
)
)
;
}
}
|
文中提到的核心类包括
- DubboNamespaceHandler
- ServiceBean
- ServiceConfig
- DubboProtocol
- Exchangers
- HeaderExchanger
- HeaderExchangeServer
- NettyTransporter
- NettyServer
至此,所有Provider启动的工作结束了,接下来就是接收请求并交给handler处理的过程,这些将在后面的文章予以介绍。