1. 程式人生 > >Dubbo服務再暴露

Dubbo服務再暴露

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import javax.annotation.Resource;

import org.I0Itec.zkclient.ZkClient;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.Version;
import com.alibaba.dubbo.common.bytecode.Wrapper;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
import com.alibaba.dubbo.common.utils.ConfigUtils;
import com.alibaba.dubbo.common.utils.NetUtils;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.config.AbstractServiceConfig;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ModuleConfig;
import com.alibaba.dubbo.config.MonitorConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.ProviderConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.support.Parameter;
import com.alibaba.dubbo.rpc.Exporter;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Protocol;
import com.alibaba.dubbo.rpc.ProxyFactory;
import com.alibaba.dubbo.rpc.cluster.ConfiguratorFactory;

/**
* 服務狀態節點恢復
* 描述: zookeeper分散式管理dubbo服務
* 1、服務正常啟動,因外界條件將其相關ip+port埠下的服務刪掉
* 2、針對已刪除的服務節點再次暴露供消費者呼叫
* 版權: Copyright (c) 2016
* 作者: [email protected]
* 版本: 1.0
* 建立日期: 2017年4月14日
* 建立時間: 上午10:26:36
*/
@Service(“serverRecoverService”)
public class ServerRecoverServiceImpl extends AbstractServiceConfig implements ServerRecoverService
{

/**
 * 
 */
private static final long serialVersionUID = 1L;

Logger logger = Logger.getLogger(ServerRecoverServiceImpl.class);

private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();

private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

@Resource
private ApplicationContext applicationContext;
protected List<ProtocolConfig> protocols;

@Autowired
private ZkClient zkClient;

@Autowired
private ProviderConfig providerConfig;

private final List<Exporter<?>> exporters = new ArrayList<Exporter<?>>();

private transient volatile boolean exported;

private transient volatile boolean unexported;

@Parameter(excluded = true)
public boolean isExported()
{
    return exported;
}

@Parameter(excluded = true)
public boolean isUnexported()
{
    return unexported;
}

public ProviderConfig getProviderConfigConfig()
{
    return providerConfig;
}

public void setProviderConfig(ProviderConfig providerConfig)
{
    this.providerConfig = providerConfig;
}

/**
 * @param jsonServerNodes 即將暴露的服務節點
 * eg:["com.***.scm.baseservice.sac.manager.test.CodeTempManager","com.***.scm.baseservice.sac.manager.PkManager","com.***.scm.baseservice.sac.service.CodeService","com.***.scm.baseservice.sac.manager.monitor.CodeMonitorManager","com.***.scm.baseservice.sac.manager.task.CommonTaskManager","com.***.scm.baseservice.sac.manager.CodeManager","com.***.scm.baseservice.sac.service.PkService","com.***.scm.baseservice.sac.manager.status.ServerRecoverService"]
 */
public void serverNodeRecover(String jsonServerNodes)
{
    init();
    //獲取dubbo服務暴露的協議
    protocols = getProtocols();
    List<URL> registryURLs = loadRegistries(true);
    Set<String> serviceNodeSet = JsonUtil.readValue(jsonServerNodes, Set.class);//相關的服務節點
    for (String node : serviceNodeSet)
    {
        for (ProtocolConfig protocolConfig : protocols)
        {
            exportNode(node, registryURLs, protocolConfig);
        }
    }
}

/**
 * 服務節點暴露
 * @param interfaceName 服務節點
 * @param registryURLs 註冊地址
 * @param protocolConfig 協議
 * 2017年4月18日 下午2:51:17
 */
@SuppressWarnings({ "unchecked", "rawtypes", "unused" })
public void exportNode(String interfaceName, List<URL> registryURLs, ProtocolConfig protocolConfig)
{
    Class<?> interfaceClass = null;
    // 介面實現類引用
    Object ref = null;
    String name = protocolConfig.getName();
    if (name == null || name.length() == 0)
    {
        name = "dubbo";
    }
    String host = protocolConfig.getHost();
    if (providerConfig != null && (host == null || host.length() == 0))
    {
        host = providerConfig.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 (providerConfig != null && (port == null || port == 0))
    {
        port = providerConfig.getPort();
    }
    Map<String, String> map = new HashMap<String, String>();
    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()));
    }
    //介面物件
    interfaceClass = getInterfaceClass(interfaceName);
    String revision = Version.getVersion(interfaceClass, getValidation());
    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)), ","));
    }
    try
    {
        //引用物件
        ref = applicationContext.getBean(interfaceClass);
    }
    catch (SecurityException e)
    {
        throw e;
    }
    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) && providerConfig != null)
    {
        contextPath = providerConfig.getContextpath();
    }
    URL url = new URL(name, host, port, (contextPath == null || contextPath.length() == 0 ? "" : contextPath + "/") + interfaceName, 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, ref, interfaceClass);
        }
        //如果配置不是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);
            }
        }
    }
}

@SuppressWarnings({ "unchecked", "rawtypes" })
private void exportLocal(URL url, Object ref, Class interfaceClass)
{
    if (!Constants.LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol()))
    {
        URL local = URL.valueOf(url.toFullString()).setProtocol(Constants.LOCAL_PROTOCOL).setHost(NetUtils.LOCALHOST).setPort(0);
        Exporter<?> exporter = protocol.export(proxyFactory.getInvoker(ref, (Class) interfaceClass, local));
        exporters.add(exporter);
        logger.info("Export dubbo service " + interfaceClass.getName() + " to local registry");
    }
}

/**
 * 例項化物件
 * @param interfaceName
 * @return
 * 2017年4月18日 下午2:42:11
 */
public Class<?> getInterfaceClass(String interfaceName)
{
    Class<?> interfaceClass = null;
    try
    {
        if (interfaceName != null && interfaceName.length() > 0)
        {
            interfaceClass = Class.forName(interfaceName, true, Thread.currentThread().getContextClassLoader());
        }
    }
    catch (ClassNotFoundException t)
    {
        throw new IllegalStateException(t.getMessage(), t);
    }
    return interfaceClass;
}

public synchronized void unexport()
{
    if (!exported)
    {
        return;
    }
    if (unexported)
    {
        return;
    }
    if (exporters != null && exporters.size() > 0)
    {
        for (Exporter<?> exporter : exporters)
        {
            try
            {
                exporter.unexport();
            }
            catch (Throwable t)
            {
                logger.warn("unexpected err when unexport" + exporter, t);
            }
        }
        exporters.clear();
    }
    unexported = true;
}

/**
 * 再次初始化dubbo服務相關協議請求等資訊
 * 
 * 2017年4月18日 下午3:40:28
 */
public void init()
{
    if (getApplication() == null && (getProviderConfigConfig() == null || getProviderConfigConfig().getApplication() == null))
    {
        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;
                }
            }
            if (applicationConfig != null)
            {
                setApplication(applicationConfig);
            }
        }
    }

    if (getModule() == null && (getProviderConfigConfig() == null || getProviderConfigConfig().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;
                }
            }
            if (moduleConfig != null)
            {
                setModule(moduleConfig);
            }
        }
    }
    if ((getRegistries() == null || getRegistries().size() == 0)
            && (getProviderConfigConfig() == null || getProviderConfigConfig().getRegistries() == null || getProviderConfigConfig().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);
                }
            }
            if (registryConfigs != null && registryConfigs.size() > 0)
            {
                super.setRegistries(registryConfigs);
            }
        }
    }

    if (getMonitor() == null && (getProviderConfigConfig() == null || getProviderConfigConfig().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;
                }
            }
            if (monitorConfig != null)
            {
                setMonitor(monitorConfig);
            }
        }
    }
    // 獲取協議
    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);
            }
        }
        if (protocolConfigs != null && protocolConfigs.size() > 0)
        {
            super.setProtocols(protocolConfigs);
        }
    }
}

}

相關推薦

Dubbo服務暴露

import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; import j

dubbo服務原始暴露流程

dubbo採用的nio非同步的通訊,通訊協議預設為 netty,當然也可以選擇 mina,grizzy。在服務端(provider)在啟動時主要是開啟netty監聽,在zookeeper上註冊服務節點,處理消費者請求,返回處理後的訊息給消費者,消費者使用服務時主

dubbo源碼分析 之 服務本地暴露

ice oca IE exec 規則 PE nbsp dpa tzu dubbo 在服務暴露發生了哪些事,今天我們就來分析一下整個服務暴露中的本地暴露。本地暴露需要服務提供方與服務消費方在同一個 JVM。下面我們來寫一個本地暴露使用的例子: 1 DemoService.j

Dubbo服務合買平臺搭建出售釋出之服務暴露&心跳機制&服務註冊

Dubbo服務釋出 Dubbo合買平臺搭建出售 dsluntan.com Q:3393756370 VX:17061863513服務釋出影響流程的主要包括三個部分,依次是: 服務暴露 心跳 服務註冊 服務暴露是對外提供服務及暴露埠,以便消費端可以正常調通服務。心跳機制保證伺服器端及客戶

沉澱出發:dubbo服務治理和應用例項

沉澱再出發:dubbo服務治理和應用例項 一、前言     阿里開發的dubbo作為服務治理的工具,在分散式開發中有著重要的意義,這裡我們主要專注於dubbo的架構,基本原理以及在Windows下面開發出來的例項來解釋和介紹,從而使得dubbo不再神祕。 二、dubbo的架

dubbo原始碼:dubbo服務暴露過程

dubbo標籤解析 spring通過在DubboNamespaceHandler註冊dubbo解析器DubboBeanDefinitionParser,在載入Bean的時候同時解析dubbo標籤並載入dubbo標籤解析後的Bean 暴露dubbo服務 d

dubbo服務暴露過程

所謂服務暴露最終做的事情:繫結網路埠,開啟serversokect服務以接收外部請求 服務暴露時序圖 本地暴露 遠端暴露   整體總結   dubbo服務提供者暴露服務的主過程:首先 ServiceConfig 類拿到對外提供服務的實際類 ref(如:Hell

Dubbo服務暴露原理

服務暴露原理 配置檔案 IOC容器啟動,載入配置檔案的時候 Dubbo標籤處理器,解析每一個標籤 封裝成對應的元件 service 解析service標籤 將service標籤資訊,封裝成ServiceBean Servic

Dubbo——服務暴露過程分析

    這篇文章來敘述對dubbo的服務暴露前的準備工作: 使用Spring配置檔案,通過main方法來啟動spring容器,來觀察dubbo服務的啟動過程。 dubbo配置檔案 <context:component-scan base-package="

dubbo 服務暴露 路徑問題

疑問 配置dubbo的時候看到了一個非常奇怪的配置: <dubbo:protocol name="webservice" port="${dubbo.webservice.port}" server="auto"/> <dubbo:protocol name

9、dubbo原始碼分析 之 服務遠端暴露(中)

在上一篇文章我們講解了一下 dubbo 遠端服務暴露過程中通過 Netty 進行 Socket 服務暴露。使得遠端客戶端可以訪問這個暴露的服務,這個只是解決了訪問之前點到點的服務呼叫。對於分步式環境當中,越來越多的服務我們如何管理並且治理這些服務是一個問題。因此 dubbo

7、dubbo原始碼分析 之 服務本地暴露

在上一篇文章我們分析了一下 dubbo 在服務暴露發生了哪些事,今天我們就來分析一下整個服務暴露中的本地暴露。(PS:其實我感覺本地暴露蠻雞肋的)。本地暴露需要服務提供方與服務消費方在同一個 JVM。下面我們來寫一個本地暴露使用的例子: 1) DemoS

Dubbo服務暴露與註冊

        前面的文章中,我們講解了Dubbo是如何進行配置的屬性的初始化的,並且講到,Dubbo最終會將所有的屬性引數都封裝

Dubbo服務暴露原始碼解析②

[TOC] ​ 先放一張官網的服務暴露時序圖,對我們梳理原始碼有很大的幫助。注:不論是暴露還是匯出或者是其他翻譯,都是描述export的,只是翻譯不同。 ![](https://img2020.cnblogs.com/blog/1383122/202012/1383122-2020122613493559

基於註解的Dubbo服務配置

log 開啟 不兼容 pack port import conf 多個 alibaba 基於註解的Dubbo服務配置可以大大減少dubbo xml配置文件中的Service配置量,主要步驟如下: 一、服務提供方 1. Dubbo配置文件中增加Dubbo註解掃描

Dubbo服務框架解析(二)

換行符 spi track .net int apt thread exce -i 本節介紹dubbo-common,dubbo-common是公共邏輯模塊,包含Util類、通用模型,是其他模塊的基礎。 擴展機制 SPI SPI是擴展點的註解。

Tomcat中部署web應用 ---- Dubbo服務消費者Web應用war包的部署

目錄 虛擬 iptables 設置 部署 inpu 端口 www 所有 樣例視頻:http://www.roncoo.com/course/view/f614343765bc4aac8597c6d8b38f06fd IP: 192.168.2.61 部署容器:apach

Dubbo服務接口的設計原則

將不 lin 實現 序列化 並且 校驗 劃分 err 分布式事務 1、接口粒度 1.1 服務接口盡可能大粒度,每個服務方法應代表一個功能,而不是某功能的一個步驟,否則將面臨分布式事務問題,Dubbo暫未提供分布式事務支持。同時可以減少系統間的網絡交互。 1.2 服務接口建議

zookeeper客戶端命令行查看dubbo服務的生產者和消費者

ide 切換 microsoft ons -s sof 生產 size zkcli 假設zookeeper安裝在192.168.5.130這臺服務器上,現在我們通過命令行查看dubbo在zookeeper註冊服務的生產者和消費者信息 首先通過命令切換到/usr/zookee

7.2 服務本地暴露

mage equals extends fail cas gis provide pack per 服務暴露的流程其實就是下邊這樣(圖片來自:http://www.iteye.com/topic/1123039) 簡單看一下服務暴露的偽代碼: 1 /** 2 *