版權聲明:本文為博主原創文章,未經博主允許不得轉載。
如上圖所示的Dubbo的暴露服務的過程,不難看出它也和消費者端很像,也需要一個像reference的對象來維護service關聯的所有對象及其屬性,這里的reference就是provider。由於ServiceBean實現了
InitializingBean接口,所有在Spring實例化這個bean后會調用接口方法afterPropertiesSet:
- public void afterPropertiesSet() throws Exception {
- //如果沒有配置provider
- if (getProvider() == null) {
- //獲取IOC容器里的所有provider
- Map<String, ProviderConfig> providerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false);
- if (providerConfigMap != null && providerConfigMap.size() > 0) {
- Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
- if ((protocolConfigMap == null || protocolConfigMap.size() == 0)
- && providerConfigMap.size() > 1) { // 兼容舊版本
- List<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>();
- for (ProviderConfig config : providerConfigMap.values()) {
- if (config.isDefault() != null && config.isDefault().booleanValue()) {
- providerConfigs.add(config);
- }
- }
- //關聯所有providers
- if (providerConfigs.size() > 0) {
- setProviders(providerConfigs);
- }
- } else {
- ProviderConfig providerConfig = null;
- for (ProviderConfig config : providerConfigMap.values()) {
- if (config.isDefault() == null || config.isDefault().booleanValue()) {
- if (providerConfig != null) {
- throw new IllegalStateException("Duplicate provider configs: " + providerConfig + " and " + config);
- }
- providerConfig = config;
- }
- }
- if (providerConfig != null) {
- setProvider(providerConfig);
- }
- }
- }
- }
- //如果沒有配置application,且沒有配置provider
- if (getApplication() == null
- && (getProvider() == null || getProvider().getApplication() == null)) {
- //獲取所有applications
- Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false);
- if (applicationConfigMap != null && applicationConfigMap.size() > 0) {
- ApplicationConfig applicationConfig = null;
- for (ApplicationConfig config : applicationConfigMap.values()) {
- if (config.isDefault() == null || config.isDefault().booleanValue()) {
- if (applicationConfig != null) {
- throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config);
- }
- applicationConfig = config;
- }
- }
- //關聯application
- if (applicationConfig != null) {
- setApplication(applicationConfig);
- }
- }
- }
- //如果沒有配置module,且沒有配置provider
- if (getModule() == null
- && (getProvider() == null || getProvider().getModule() == null)) {
- Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false);
- if (moduleConfigMap != null && moduleConfigMap.size() > 0) {
- ModuleConfig moduleConfig = null;
- for (ModuleConfig config : moduleConfigMap.values()) {
- if (config.isDefault() == null || config.isDefault().booleanValue()) {
- if (moduleConfig != null) {
- throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config);
- }
- moduleConfig = config;
- }
- }
- //關聯module
- if (moduleConfig != null) {
- setModule(moduleConfig);
- }
- }
- }
- //如果沒有配置registries,且沒有配置provider
- if ((getRegistries() == null || getRegistries().size() == 0)
- && (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().size() == 0)
- && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) {
- Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
- if (registryConfigMap != null && registryConfigMap.size() > 0) {
- List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
- for (RegistryConfig config : registryConfigMap.values()) {
- if (config.isDefault() == null || config.isDefault().booleanValue()) {
- registryConfigs.add(config);
- }
- }
- //關聯registries
- if (registryConfigs != null && registryConfigs.size() > 0) {
- super.setRegistries(registryConfigs);
- }
- }
- }
- //如果沒有配置monitor,且沒有配置provider
- if (getMonitor() == null
- && (getProvider() == null || getProvider().getMonitor() == null)
- && (getApplication() == null || getApplication().getMonitor() == null)) {
- Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false);
- if (monitorConfigMap != null && monitorConfigMap.size() > 0) {
- MonitorConfig monitorConfig = null;
- for (MonitorConfig config : monitorConfigMap.values()) {
- if (config.isDefault() == null || config.isDefault().booleanValue()) {
- if (monitorConfig != null) {
- throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config);
- }
- monitorConfig = config;
- }
- }
- //關聯monitor
- if (monitorConfig != null) {
- setMonitor(monitorConfig);
- }
- }
- }
- //如果沒有配置protocol,且沒有配置provider
- if ((getProtocols() == null || getProtocols().size() == 0)
- && (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().size() == 0)) {
- Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
- if (protocolConfigMap != null && protocolConfigMap.size() > 0) {
- List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>();
- for (ProtocolConfig config : protocolConfigMap.values()) {
- if (config.isDefault() == null || config.isDefault().booleanValue()) {
- protocolConfigs.add(config);
- }
- }
- //關聯protocol
- if (protocolConfigs != null && protocolConfigs.size() > 0) {
- super.setProtocols(protocolConfigs);
- }
- }
- }
- //如果沒有配置path
- if (getPath() == null || getPath().length() == 0) {
- if (beanName != null && beanName.length() > 0
- && getInterface() != null && getInterface().length() > 0
- && beanName.startsWith(getInterface())) {
- setPath(beanName);
- }
- }
- //暴露provider
- if (! isDelay()) {
- export();
- }
- }
Dubbo在確認了所有相關對象都配置后調用export方法開始暴露過程:
- public synchronized void export() {
- //如果provider沒有配置
- if (provider != null) {
- //如果exporter沒有配置使用provider所關聯的exporter
- if (export == null) {
- export = provider.getExport();
- }
- //如果delay(延遲暴露)沒有配置,獲取provider的delay
- if (delay == null) {
- delay = provider.getDelay();
- }
- }
- //如果不需要暴露接口則直接返回
- if (export != null && ! export.booleanValue()) {
- return;
- }
- //如果延遲暴露的時間(毫秒級)是存在的,開啟線程並等待delay毫秒后開始暴露接口,否則直接執行暴露接口過程
- 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();
- }
- }
- protected synchronized void doExport() {
- //如果不需要暴露接口則拋出異常
- if (unexported) {
- throw new IllegalStateException("Already unexported!");
- }
- //如果已經暴露則不需要重復暴露
- if (exported) {
- return;
- }
- exported = true;
- //如果interfaceName沒配置(這樣dubbo就無法找到需要暴露的service對象)則拋出異常
- if (interfaceName == null || interfaceName.length() == 0) {
- throw new IllegalStateException("<dubbo:service interface=\"\" /> interface not allow null!");
- }
- checkDefault();
- //provider已經配置的情況下,如果application、module、registries、monitor、protocol中有未配置的均可以從provider獲取
- 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){
- //如果是本地服務在interfaceName屬性后面加上Local
- if(local=="true"){
- local=interfaceName+"Local";
- }
- Class<?> localClass;
- try {
- //加載service
- 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 {
- //加載service
- 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);
- }
- }
- //檢查application
- checkApplication();
- //檢查registries
- checkRegistry();
- //檢查protocol
- checkProtocol();
- //將所有這些對象的屬性關聯到provider
- appendProperties(this);
- checkStubAndMock(interfaceClass);
- if (path == null || path.length() == 0) {
- path = interfaceName;
- }
- //暴露地址
- doExportUrls();
- }
- private void doExportUrls() {
- //將注冊的所有url匹配上對應的協議在服務端暴露出來
- List<URL> registryURLs = loadRegistries(true);
- for (ProtocolConfig protocolConfig : protocols) {
- doExportUrlsFor1Protocol(protocolConfig, registryURLs);
- }
- }
- private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
- //如果沒配置protocol則默認使用dubbo協議
- 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 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);
- }
- //獲取application、module、provider、protocol、exporter、registries、monitor所有屬性
- 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 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)) {
- //暴露的地址是localhost所以遠端無法訪問
- 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<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));
- //根據協議將invoker暴露成exporter,具體過程是創建一個ExchangeServer,它會綁定一個ServerSocket到配置端口
- Exporter<?> exporter = protocol.export(invoker);
- //將創建的exporter放進鏈表便於管理
- exporters.add(exporter);
- }
- } else {
- Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
- Exporter<?> exporter = protocol.export(invoker);
- exporters.add(exporter);
- }
- }
- }
- this.urls.add(url);
- }
整個暴露服務的流程就是首先檢查配置是否完整然后獲取協議和端口信息,通知registries自己已經注冊可以提供服務最后創建Server綁定端口。這樣用戶就可以從配置的信息連接到Server並和Server通信遠程調用方法了。