1,Dubbo服务提供者-Provider,提供RPC具体服务。一个典型的Dubbo提供者配置如下:
<dubbo
:application name
=
"sync-data-consumer-1"
/>
<dubbo
:registry protocol
=
"zookeeper" address
=
"zoo4.superboss.cc:30002,zoo5.superboss.cc:30002,zoo6.superboss.cc:30002"
/>
<dubbo
:protocol name
=
"dubbo" port
=
"2288" host
=
"10.132.171.146"
></dubbo
:protocol
>
<dubbo
:service id
=
"serviceDubbo"
interface
=
"IInterface" ref
=
"detailService" version
=
"${dubbo.version}" timeout
=
"60000"
></dubbo
:service
>
2,之前提到过,Dubbo定义了自己的Schemal并自己解析。我们查看ServiceBean,该类用来解析对应的Dubbo命名空间的文档。
public
class ServiceBean
<T
>
extends ServiceConfig
<T
> implements InitializingBean
, DisposableBean
, ApplicationContextAware
, ApplicationListener
, BeanNameAware
该类实现了一系列Spring初始化Bean的方法,并继承了SerivceConfig。在Bean初始化时候,会调用一些Bean的初始化方法。
public void onApplicationEvent
(ApplicationEvent event
)
{
if
(ContextRefreshedEvent
.
class
.getName
(
)
.equals
(event
.getClass
(
)
.getName
(
)
)
)
{
if
(isDelay
(
)
&&
! isExported
(
)
&&
! isUnexported
(
)
)
{
if
(logger
.isInfoEnabled
(
)
)
{
logger
.info
(
"The service ready on spring started. service: "
+ getInterface
(
)
)
;
}
export
(
)
;
}
}
}
在onApplicationEvent事件中,调用了export方法。
public synchronized void export
(
)
{
if
(provider
!=
null
)
{
if
(export
==
null
)
{
export
= provider
.getExport
(
)
;
}
if
(delay
==
null
)
{
delay
= provider
.getDelay
(
)
;
}
}
if
(export
!=
null
&&
! export
.booleanValue
(
)
)
{
return
;
}
if
(delay
!=
null
&& delay
>
0
)
{
Thread thread
=
new Thread
(
new Runnable
(
)
{
public void run
(
)
{
try
{
Thread
.
sleep
(delay
)
;
} catch
(Throwable e
)
{
}
doExport
(
)
;
}
}
)
;
thread
.setDaemon
(
true
)
;
thread
.setName
(
"DelayExportServiceThread"
)
;
thread
.start
(
)
;
}
else
{
doExport
(
)
;
}
}
继续查看doExport方法。
protected synchronized void doExport() {
if (unexported) {
throw new IllegalStateException("Already unexported!");
}
if (exported) {
return;
}
exported = true;
if (interfaceName == null || interfaceName.length() == 0) {
throw new IllegalStateException("<dubbo:service interface=\"\" /> interface not allow null!");
}
checkDefault();
if (provider != null) {
if (application == null) {
application = provider.getApplication();
}
if (module == null) {
module = provider.getModule();
}
if (registries == null) {
registries = provider.getRegistries();
}
if (monitor == null) {
monitor = provider.getMonitor();
}
if (protocols == null) {
protocols = provider.getProtocols();
}
}
if (module != null) {
if (registries == null) {
registries = module.getRegistries();
}
if (monitor == null) {
monitor = module.getMonitor();
}
}
if (application != null) {
if (registries == null) {
registries = application.getRegistries();
}
if (monitor == null) {
monitor = application.getMonitor();
}
}
if (ref instanceof GenericService) {
interfaceClass = GenericService.class;
if (StringUtils.isEmpty(generic)) {
generic = Boolean.TRUE.toString();
}
} else {
try {
interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
.getContextClassLoader());
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e.getMessage(), e);
}
checkInterfaceAndMethods(interfaceClass, methods);
checkRef();
generic = Boolean.FALSE.toString();
}
if(local !=null){
if(local=="true"){
local=interfaceName+"Local";
}
Class
<?
> localClass
;
try
{
localClass
= ClassHelper
.forNameWithThreadContextClassLoader
(local
)
;
} catch
(ClassNotFoundException e
)
{
throw
new IllegalStateException
(e
.getMessage
(
)
, e
)
;
}
if
(
!interfaceClass
.isAssignableFrom
(localClass
)
)
{
throw
new IllegalStateException
(
"The local implemention class "
+ localClass
.getName
(
)
+
" not implement interface "
+ interfaceName
)
;
}
}
if
(stub
!=
null
)
{
if
(stub
==
"true"
)
{
stub
=interfaceName
+
"Stub"
;
}
Class
<?
> stubClass;
try {
stubClass = ClassHelper.forNameWithThreadContextClassLoader(stub);
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e.getMessage(), e);
}
if(!interfaceClass.isAssignableFrom(stubClass)){
throw new IllegalStateException("The stub implemention class " + stubClass.getName() + " not implement interface " + interfaceName);
}
}
checkApplication();
checkRegistry();
checkProtocol();
appendProperties(this);
checkStubAndMock(interfaceClass);
if (path == null || path.length() == 0) {
path = interfaceName;
}
doExportUrls();
}
最后到最终的方法暴漏:
private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
String name = protocolConfig.getName();
if (name == null || name.length() == 0) {
name = "dubbo";
}
String host = protocolConfig.getHost();
if (provider != null && (host == null || host.length() == 0)) {
host = provider.getHost();
}
boolean anyhost = false;
if (NetUtils.isInvalidLocalHost(host)) {
anyhost = true;
try {
host = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
logger.warn(e.getMessage(), e);
}
if (NetUtils.isInvalidLocalHost(host)) {
if (registryURLs != null && registryURLs.size() > 0) {
for (URL registryURL : registryURLs) {
try {
Socket socket = new Socket();
try {
SocketAddress addr = new InetSocketAddress(registryURL.getHost(), registryURL.getPort());
socket.connect(addr, 1000);
host = socket.getLocalAddress().getHostAddress();
break;
} finally {
try {
socket.close();
} catch (Throwable e) {}
}
} catch (Exception e) {
logger.warn(e.getMessage(), e);
}
}
}
if (NetUtils.isInvalidLocalHost(host)) {
host = NetUtils.getLocalHost();
}
}
}
Integer port = protocolConfig.getPort();
if (provider != null && (port == null || port == 0)) {
port = provider.getPort();
}
final int defaultPort = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(name).getDefaultPort();
if (port == null || port == 0) {
port = defaultPort;
}
if (port == null || port <= 0) {
port = getRandomPort(name);
if (port == null || port < 0) {
port = NetUtils.getAvailablePort(defaultPort);
putRandomPort(name, port);
}
logger.warn("Use random available port(" + port + ") for protocol " + name);
}
Map<String, String> map = new HashMap<String, String>();
if (anyhost) {
map.put(Constants.ANYHOST_KEY, "true");
}
map.put(Constants.SIDE_KEY, Constants.PROVIDER_SIDE);
map.put(Constants.DUBBO_VERSION_KEY, Version.getVersion());
map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis()));
if (ConfigUtils.getPid() > 0) {
map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));
}
appendParameters(map, application);
appendParameters(map, module);
appendParameters(map, provider, Constants.DEFAULT_KEY);
appendParameters(map, protocolConfig);
appendParameters(map, this);
if (methods != null && methods.size() > 0) {
for (MethodConfig method : methods) {
appendParameters(map, method, method.getName());
String retryKey = method.getName() + ".retry";
if (map.containsKey(retryKey)) {
String retryValue = map.remove(retryKey);
if ("false".equals(retryValue)) {
map.put(method.getName() + ".retries", "0");
}
}
List<ArgumentConfig> arguments = method.getArguments();
if (arguments != null && arguments.size() > 0) {
for (ArgumentConfig argument : arguments) {
//类型自动转换.
if(argument.getType() != null && argument.getType().length() >0){
Method[] methods = interfaceClass.getMethods();
//遍历所有方法
if(methods != null && methods.length > 0){
for (int i = 0; i < methods.length; i++) {
String methodName = methods[i].getName();
//匹配方法名称,获取方法签名.
if(methodName.equals(method.getName())){
Class
<?
>
[
] argtypes
= methods
[i
]
.getParameterTypes
(
)
;
//一个方法中单个callback
if
(argument
.getIndex
(
)
!=
-
1
)
{
if
(argtypes
[argument
.getIndex
(
)
]
.getName
(
)
.equals
(argument
.
getType
(
)
)
)
{
appendParameters
(map
, argument
, method
.getName
(
)
+
"."
+ argument
.getIndex
(
)
)
;
}
else
{
throw
new IllegalArgumentException
(
"argument config error : the index attribute and type attirbute not match :index :"
+argument
.getIndex
(
)
+
", type:"
+ argument
.
getType
(
)
)
;
}
}
else
{
//一个方法中多个callback
for
(int j
=
0
;j
<argtypes
.length
;j
++
)
{
Class
<?
> argclazz = argtypes[j];
if (argclazz.getName().equals(argument.getType())){
appendParameters(map, argument, method.getName() + "." + j);
if (argument.getIndex() != -1 && argument.getIndex() != j){
throw new IllegalArgumentException("argument config error : the index attribute and type attirbute not match :index :"+argument.getIndex() + ", type:" + argument.getType());
}
}
}
}
}
}
}
}else if(argument.getIndex() != -1){
appendParameters(map, argument, method.getName() + "." + argument.getIndex());
}else {
throw new IllegalArgumentException("argument config must set index or type attribute.eg: <dubbo:argument index='0' .../> or <dubbo:argument type=xxx .../>");
}
}
}
} // end of methods for
}
if (ProtocolUtils.isGeneric(generic)) {
map.put("generic", generic);
map.put("methods", Constants.ANY_VALUE);
} else {
String revision = Version.getVersion(interfaceClass, version);
if (revision != null && revision.length() > 0) {
map.put("revision", revision);
}
String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
if(methods.length == 0) {
logger.warn("NO method found in service interface " + interfaceClass.getName());
map.put("methods", Constants.ANY_VALUE);
}
else {
map.put("methods", StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ","));
}
}
if (! ConfigUtils.isEmpty(token)) {
if (ConfigUtils.isDefault(token)) {
map.put("token", UUID.randomUUID().toString());
} else {
map.put("token", token);
}
}
if ("injvm".equals(protocolConfig.getName())) {
protocolConfig.setRegister(false);
map.put("notify", "false");
}
// 导出服务
String contextPath = protocolConfig.getContextpath();
if ((contextPath == null || contextPath.length() == 0) && provider != null) {
contextPath = provider.getContextpath();
}
URL url = new URL(name, host, port, (contextPath == null || contextPath.length() == 0 ? "" : contextPath + "/") + path, map);
if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
.hasExtension(url.getProtocol())) {
url = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
.getExtension(url.getProtocol()).getConfigurator(url).configure(url);
}
String scope = url.getParameter(Constants.SCOPE_KEY);
//配置为none不暴露
if (! Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) {
//配置不是remote的情况下做本地暴露 (配置为remote,则表示只暴露远程服务)
if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) {
exportLocal(url);
}
//如果配置不是local则暴露为远程服务.(配置为local,则表示只暴露远程服务)
if (! Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope) ){
if (logger.isInfoEnabled()) {
logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
}
if (registryURLs != null && registryURLs.size() > 0
&& url.getParameter("register", true)) {
for (URL registryURL : registryURLs) {
url = url.addParameterIfAbsent("dynamic", registryURL.getParameter("dynamic"));
URL monitorUrl = loadMonitor(registryURL);
if (monitorUrl != null) {
url = url.addParameterAndEncoded(Constants.MONITOR_KEY, monitorUrl.toFullString());
}
if (logger.isInfoEnabled()) {
logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);
}
Invoker
<?
> invoker
= proxyFactory
.getInvoker
(ref
,
(
Class
) interfaceClass
, registryURL
.addParameterAndEncoded
(Constants
.EXPORT_KEY
, url
.toFullString
(
)
)
)
;
Exporter
<?
> exporter = protocol.export(invoker);
exporters.add(exporter);
}
} else {
Invoker
<?
> invoker
= proxyFactory
.getInvoker
(ref
,
(
Class
) interfaceClass
, url
)
;
Exporter
<?
> exporter = protocol.export(invoker);
exporters.add(exporter);
}
}
}
this.urls.add(url);
}
这个是比较主要的一条线,我们可以较为简单的分析一些实现。