Dubbo 3.x源码(16)—Dubbo服务发布导出源码(5)

这篇具有很好参考价值的文章主要介绍了Dubbo 3.x源码(16)—Dubbo服务发布导出源码(5)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基于Dubbo 3.1,详细介绍了Dubbo服务的发布与引用的源码。

此前我们学习了Dubbo 3.x源码(15)—Dubbo服务发布导出源码(4),也就是Dubbo远程服务导出export方法的上半部分,也就是doLocalExport源码,将会得到一个Exporter。

现在我们继续学习,在导出远程服务得到Exporter之后,继续通过Registry将其注册到远程注册中心的源码。

  1. Dubbo 3.x源码(11)—Dubbo服务的发布与引用的入口
  2. Dubbo 3.x源码(12)—Dubbo服务发布导出源码(1)
  3. Dubbo 3.x源码(13)—Dubbo服务发布导出源码(2)
  4. Dubbo 3.x源码(14)—Dubbo服务发布导出源码(3)
  5. Dubbo 3.x源码(15)—Dubbo服务发布导出源码(4)
  6. Dubbo 3.x源码(16)—Dubbo服务发布导出源码(5)

1 register注册服务到注册中心

此前我们学习过,在远程服务导出协议(RegistryProtocol、InterfaceCompatibleRegistryProtocol)的export方法中,在本地导出服务得到Exporter之后,还需要将其注册到远程注册中心,这样consumer端才能从注册中心获取到服务的相关信息。

// url to registry
/*
 * 基于Dubbo SPI机制根据注册中心url加载具体的注册中心操作类,service-discovery-registry对应着ServiceDiscoveryRegistry
 */
final Registry registry = getRegistry(registryUrl);
//获取需要注册的服务url 内部包含服务的ip、port、pid、服务接口、版本、分组、接口内部的方法名等信息
//dubbo://192.168.31.84:20880/org.apache.dubbo.demo.GreetingService?anyhost=true&application=demo-provider&application.version=1&background=false&delay=5000&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&group=greeting&interface=org.apache.dubbo.demo.GreetingService&methods=hello&pid=10920&revision=1.0.0&service-name-mapping=true&side=provider&timeout=5000&timestamp=1666621305141&version=1.0.0
final URL registeredProviderUrl = getUrlToRegistry(providerUrl, registryUrl);

// decide if we need to delay publish (provider itself and registry should both need to register)
//决定我们是否需要延迟发布(提供者本身和注册中心都需要注册)
boolean register = providerUrl.getParameter(REGISTER_KEY, true) && registryUrl.getParameter(REGISTER_KEY, true);
/*
 * 2 向注册中心注册服务
 */
if (register) {
    register(registry, registeredProviderUrl);
}

2 getRegistry获取注册表

Registry是服务注册中心操作类,Registry同样是基于Dubbo SPI机制根据协议查找的,例如service-discovery-registry服务发现协议对应着ServiceDiscoveryRegistry,而registry服务发现协议由于getRegistryUrl方法中就被替换为了真实的协议地址,因此registryUrl可能对应着不同协议,因此Registry的返回也各不相同,例如nacos协议对应着NacosRegistry,zookeeper协议对应着ZookeeperRegistry。

/**
 * 根据调用者的地址获取注册表的实例
 *
 * @param registryUrl 注册中心url
 * @return 注册表
 */
protected Registry getRegistry(final URL registryUrl) {
    //获取RegistryFactory的自适应实现 RegistryFactory$Adaptive
    RegistryFactory registryFactory = ScopeModelUtil.getExtensionLoader(RegistryFactory.class, registryUrl.getScopeModel()).getAdaptiveExtension();
    //根据url的协议获取对应的RegistryFactory实现,然后调用RegistryFactory实现的getRegistry方法获取注册表
    return registryFactory.getRegistry(registryUrl);
}

2.1 AbstractRegistryFactory#getRegistry获取注册表

该方法是获取注册表的模版方法,属于AbstractRegistryFactory,该方法中,将会根据url获取注册表缓存key,例如service-discovery-registry://47.94.229.245:2181/org.apache.dubbo.registry.RegistryService,或者zookeeper://47.94.229.245:2181/org.apache.dubbo.registry.RegistryService,然后尝试从registries缓存中根据key获取注册表实例,如果找打就直接返回,否则调用createRegistry方法根据url创建一个注册中心,最后将创建的注册中心存入缓存并返回。

/**
 * AbstractRegistryFactory的方法
 * <p>
 * 获取注册表的模版方法
 *
 * @param url 注册中心url
 */
@Override
public Registry getRegistry(URL url) {
    if (registryManager == null) {
        throw new IllegalStateException("Unable to fetch RegistryManager from ApplicationModel BeanFactory. " +
            "Please check if `setApplicationModel` has been override.");
    }
    //应用销毁状态的判断
    Registry defaultNopRegistry = registryManager.getDefaultNopRegistryIfDestroyed();
    if (null != defaultNopRegistry) {
        return defaultNopRegistry;
    }
    //添加interface参数值为RegistryService全路径名、移除timestamp参数、移除export、refer属性
    url = URLBuilder.from(url)
        .setPath(RegistryService.class.getName())
        .addParameter(INTERFACE_KEY, RegistryService.class.getName())
        .removeParameter(TIMESTAMP_KEY)
        .removeAttribute(EXPORT_KEY)
        .removeAttribute(REFER_KEY)
        .build();
    //注册表缓存key,例如service-discovery-registry://47.94.229.245:2181/org.apache.dubbo.registry.RegistryService
    String key = createRegistryCacheKey(url);
    Registry registry = null;
    boolean check = url.getParameter(CHECK_KEY, true) && url.getPort() != 0;

    // Lock the registry access process to ensure a single instance of the registry  锁定注册表访问过程,以确保注册表的单个实例
    registryManager.getRegistryLock().lock();
    try {
        // double check
        // fix https://github.com/apache/dubbo/issues/7265.
        defaultNopRegistry = registryManager.getDefaultNopRegistryIfDestroyed();
        if (null != defaultNopRegistry) {
            return defaultNopRegistry;
        }
        //从registries缓存中根据key获取注册表实例
        registry = registryManager.getRegistry(key);
        //如果有就直接返回
        if (registry != null) {
            return registry;
        }

        // create registry by spi/ioc
        //基于url创建注册中心
        registry = createRegistry(url);
        if (check && registry == null) {
            throw new IllegalStateException("Can not create registry " + url);
        }
        //存入缓存
        if (registry != null) {
            registryManager.putRegistry(key, registry);
        }
    } catch (Exception e) {
        if (check) {
            throw new RuntimeException("Can not create registry " + url, e);
        } else {
            // 1-11 Failed to obtain or create registry (service) object.
            LOGGER.warn("1-11", "", "",
                "Failed to obtain or create registry ", e);
        }
    } finally {
        // Release the lock 解锁
        registryManager.getRegistryLock().unlock();
    }
    //返回注册表
    return registry;
}

2.1.1 createRegistry创建注册表

在应用级服务注册表ServiceDiscoveryRegistry的创建过程中,此时才会将service-discovery-registry服务发现协议替换为真实的注册中心协议,然后创建一个ServiceDiscoveryRegistry返回。

public class ServiceDiscoveryRegistryFactory extends AbstractRegistryFactory {

    @Override
    protected Registry createRegistry(URL url) {
        //初始的url:service-discovery-registry://xxx.xxx.xxx.xxx:2181/org.apache.dubbo.registry.RegistryService?REGISTRY_CLUSTER=registry1&application=demo-provider&application.version=1&dubbo=2.0.2&interface=org.apache.dubbo.registry.RegistryService&pid=42244&registry=zookeeper&timeout=20001
        if (UrlUtils.hasServiceDiscoveryRegistryProtocol(url)) {
            //获取url的registry参数值,默认dubbo
            String protocol = url.getParameter(REGISTRY_KEY, DEFAULT_REGISTRY);
            //将服务发现协议替换为真实的注册中心协议,并且删除url的registry参数
            url = url.setProtocol(protocol).removeParameter(REGISTRY_KEY);
        }
        //替换后的url zookeeper://xxx.xxx.xxx.xxx:2181/org.apache.dubbo.registry.RegistryService?REGISTRY_CLUSTER=registry1&application=demo-provider&application.version=1&dubbo=2.0.2&interface=org.apache.dubbo.registry.RegistryService&pid=41479&timeout=20001
        return new ServiceDiscoveryRegistry(url, applicationModel);
    }

}

对于zookeeper注册中心来说,则是直接创建一个ZookeeperRegistry返回,内部包含了一个zkClient客户端。

@Override
public Registry createRegistry(URL url) {
    return new ZookeeperRegistry(url, zookeeperTransporter);
}

常见注册表的关系如下:
Dubbo 3.x源码(16)—Dubbo服务发布导出源码(5),Dubbo 3.x 源码,dubbo,java,dubbo服务发布导出源码,dubbo源码

2.2 ServiceDiscoveryRegistry的构建

ServiceDiscoveryRegistry的构造器中:

  1. 首先会调用父类FailbackRegistry的构造器。
  2. 然后根据url中的注册中心协议构建一个ServiceDiscovery,例如ZookeeperServiceDiscovery,其包含服务发现的通用操作。
  3. 最后获取服务名映射 MetadataServiceNameMapping,可通过服务接口名查找到对应的服务应用的名字。
public ServiceDiscoveryRegistry(URL registryURL, ApplicationModel applicationModel) {
    //父类构造器
    super(registryURL);
    //根据url中的注册中心协议构建一个ServiceDiscovery,例如ZookeeperServiceDiscovery,其包含服务发现的通用操作
    this.serviceDiscovery = createServiceDiscovery(registryURL);
    //获取服务名映射 MetadataServiceNameMapping,可通过服务接口名查找到对应的服务应用的名字
    this.serviceNameMapping = (AbstractServiceNameMapping) ServiceNameMapping.getDefaultExtension(registryURL.getScopeModel());
    super.applicationModel = applicationModel;
}

FailbackRegistry的构造器如下:

  1. 首先会调用父类AbstractRegistry的构造器。
  2. 然后获取重试时间间隔,取url参数retry.period,默认5000ms。
  3. 最后创建一个用于失败重试的时间轮。因为重试任务不会非常多,一圈128个刻度就足够了。
public FailbackRegistry(URL url) {
    //调用父类AbstractRegistry构造器
    super(url);
    //重试时间间隔,取url参数retry.period,默认5000ms
    this.retryPeriod = url.getParameter(REGISTRY_RETRY_PERIOD_KEY, DEFAULT_REGISTRY_RETRY_PERIOD);

    // since the retry task will not be very much. 128 ticks is enough.
    //用于失败重试的时间轮。因为重试任务不会非常多,一圈128个刻度就足够了。
    retryTimer = new HashedWheelTimer(new NamedThreadFactory("DubboRegistryRetryTimer", true), retryPeriod, TimeUnit.MILLISECONDS, 128);
}

AbstractRegistry的构造器如下,主要是本地缓存文件的支持以及加载本地缓存。

protected AbstractRegistry(URL url) {
    //设置registryUrl属性
    setUrl(url);
    //获取注册表管理器
    registryManager = url.getOrDefaultApplicationModel().getBeanFactory().getBean(RegistryManager.class);
    //获取url参数file.cache,是否支持本地缓存,默认true
    localCacheEnabled = url.getParameter(REGISTRY_LOCAL_FILE_CACHE_ENABLED, true);
    //获取注册表缓存执行器sharedScheduledExecutor
    registryCacheExecutor = url.getOrDefaultFrameworkModel().getBeanFactory()
        .getBean(FrameworkExecutorRepository.class).getSharedScheduledExecutor();
    //如果支持本地缓存
    if (localCacheEnabled) {
        // Start file save timer
        //获取url参数save.file,是否同步存储,默认false
        syncSaveFile = url.getParameter(REGISTRY_FILESAVE_SYNC_KEY, false);
        //注册中心缓存文件名 /{user.home}/.dubbo/dubbo-registry-{dubbo.application.name}-{ip}-{post}.cache
        String defaultFilename = System.getProperty(USER_HOME) + DUBBO_REGISTRY + url.getApplication() +
            "-" + url.getAddress().replaceAll(":", "-") + CACHE;
        //获取url参数file,指定的文件名,默认defaultFilename
        String filename = url.getParameter(FILE_KEY, defaultFilename);
        File file = null;

        if (ConfigUtils.isNotEmpty(filename)) {
            //创建文件对象
            file = new File(filename);
            //不存在则创建
            if (!file.exists() && file.getParentFile() != null && !file.getParentFile().exists()) {
                if (!file.getParentFile().mkdirs()) {

                    IllegalArgumentException illegalArgumentException = new IllegalArgumentException(
                        "Invalid registry cache file " + file + ", cause: Failed to create directory " + file.getParentFile() + "!");

                    if (logger != null) {
                        // 1-9 failed to read / save registry cache file.

                        logger.error("1-9", "cache directory inaccessible",
                            "Try adjusting permission of the directory.",
                            "failed to create directory", illegalArgumentException);
                    }

                    throw illegalArgumentException;
                }
            }
        }

        this.file = file;

        // When starting the subscription center,
        // we need to read the local cache file for future Registry fault tolerance processing.
        //加载缓存文件内容到properties集合中,方便注册表容错管理
        loadProperties();
        //推送变更
        notify(url.getBackupUrls());
    }
}

3 register注册服务

该方法内部实际上是调用registry的register方法完成注册。参数url是注册的服务提供者url,内部包含服务提供者的协议、ip、port、pid、服务接口、版本、分组、接口内部的方法名等信息。

/**
 * RegistryProtocol的方法
 * <p>
 * 向注册中心注册服务
 *
 * @param registry              服务注册中心操作类,例如service-discovery-registry对应着ServiceDiscoveryRegistry
 * @param registeredProviderUrl 注册的服务提供者url, 内部包含服务的ip、port、pid、服务接口、版本、分组、接口内部的方法名等信息
 */
private void register(Registry registry, URL registeredProviderUrl) {
    //调用registry的register方法完成注册
    registry.register(registeredProviderUrl);
}

我们下面来看看接口级和应用级别的服务注册的源码,假设真实注册中心都是zookeeper,此时接口级服务注册使用的真实注册表ZookeeperRegistry,而应用级服务注册使用的是ServiceDiscoveryRegistry,但是url已经变成了真实zookeeper协议的url。

3.1 ServiceDiscoveryRegistry应用级服务注册

ServiceDiscoveryRegistry内部最终是调用ServiceDiscovery的register方法完成注册,我们前面就说过,serviceDiscovery中包含服务发现的通用操作。假设注册中心协议为zookeeper,那么serviceDiscovery就是ZookeeperServiceDiscovery。

@Override
public final void register(URL url) {
    //只注册提供者
    if (!shouldRegister(url)) { // Should Not Register
        return;
    }
    //执行注册
    doRegister(url);
}

@Override
public void doRegister(URL url) {
    // fixme, add registry-cluster is not necessary anymore
    url = addRegistryClusterKey(url);
    //调用serviceDiscovery的register方法完成注册
    serviceDiscovery.register(url);
}

ZookeeperServiceDiscovery的register方法实际上是AbstractServiceDiscovery的register方法实现,内部调用metadataInfo的addService方法。

addService方法会根据服务提供者url创建ServiceInfo并添加到services集合中,随后将url加入到exportedServiceURLs缓存中,最后将更新标识位updated改为true。

/**
 * AbstractServiceDiscovery的方法
 *
 * @param url  服务提供者url
 */
@Override
public void register(URL url) {
    //根据url添加MetadataInfo
    metadataInfo.addService(url);
}

/**
 * MetadataInfo的方法
 * @param url 服务提供者url
 */
public synchronized void addService(URL url) {
    // fixme, pass in application mode context during initialization of MetadataInfo.
    if (this.loader == null) {
        this.loader = url.getOrDefaultApplicationModel().getExtensionLoader(MetadataParamsFilter.class);
    }
    //元数据参数过滤器
    List<MetadataParamsFilter> filters = loader.getActivateExtension(url, "params-filter");
    // generate service level metadata
    //生成服务级别元数据
    ServiceInfo serviceInfo = new ServiceInfo(url, filters);
    //存入services缓存,mathKey例如:greeting/org.apache.dubbo.demo.GreetingService:1.0.0:dubbo  value是serviceInfo
    this.services.put(serviceInfo.getMatchKey(), serviceInfo);
    // extract common instance level params
    extractInstanceParams(url, filters);
    //初始化exportedServiceURLs
    if (exportedServiceURLs == null) {
        exportedServiceURLs = new ConcurrentSkipListMap<>();
    }
    //加入到exportedServiceURLs缓存,  key例如:greeting/org.apache.dubbo.demo.GreetingService:1.0.0  value是url的SortedSet<URL>集合
    addURL(exportedServiceURLs, url);
    //设置更新标志为true
    updated = true;
}

注意,上面的方法仅仅是将数据发布到内存中,还没有真正的注册到注册中心。那么,应用级服务注册信息什么时候真正的同步到注册中心的呢?

实际上在DefaultModuleDeployer#startSync方法中,在经过了exportServices服务导出和referServices服务引用之后的onModuleStarted方法中,此时才会进行应用级服务数据的真正注册。

我们这里直接来看看注册后在zookeeper上的数据,可以看到节点路径是应用级数据services/{applicationName}/{ip:port},每一个应用实例才会注册一个节点,节点类型是临时节点,节点内包括服务名称、id、地址、端口、端口、有效载荷(包含存储元数据)等信息。

Dubbo 3.x源码(16)—Dubbo服务发布导出源码(5),Dubbo 3.x 源码,dubbo,java,dubbo服务发布导出源码,dubbo源码

3.2 ZookeeperRegistry接口级服务注册

传统的接口级别服务注册使用注册中心协议本身对应的注册表来实现,例如zookeeper协议将会使用ZookeeperRegistry,而他的register方法实际上调用的父类FailbackRegistry实现的register方法。

FailbackRegistry#register方法首先将url加入到registered缓存中,然后从注册失败的缓存failedRegistered中和移除注册失败的缓存failedUnregistered中移除该url。核心方法是调用doRegister方法,向服务器端发送注册请求,该方法由具体的子类实现。

/**
 * FailbackRegistry的方法
 * 
 * 注册服务提供者url
 */
@Override
public void register(URL url) {
    if (!acceptable(url)) {
        logger.info("URL " + url + " will not be registered to Registry. Registry " + this.getUrl() + " does not accept service of this protocol type.");
        return;
    }
    //调用父类AbstractRegistry的register方法,将url加入到registered缓存中
    super.register(url);
    //从注册失败的缓存failedRegistered中移除该url
    removeFailedRegistered(url);
    //从移除注册失败的缓存failedUnregistered中移除该url
    removeFailedUnregistered(url);
    try {
        // Sending a registration request to the server side
        /*
         * 向服务器端发送注册请求,该方法由具体的子类实现
         */
        doRegister(url);
    } catch (Exception e) {
        Throwable t = e;

        // If the startup detection is opened, the Exception is thrown directly.
        boolean check = getUrl().getParameter(Constants.CHECK_KEY, true)
            && url.getParameter(Constants.CHECK_KEY, true)
            && (url.getPort() != 0);
        boolean skipFailback = t instanceof SkipFailbackWrapperException;
        if (check || skipFailback) {
            if (skipFailback) {
                t = t.getCause();
            }
            throw new IllegalStateException("Failed to register " + url + " to registry " + getUrl().getAddress() + ", cause: " + t.getMessage(), t);
        } else {
            logger.error("Failed to register " + url + ", waiting for retry, cause: " + t.getMessage(), t);
        }

        // Record a failed registration request to a failed list, retry regularly
        addFailedRegistered(url);
    }
}

我们来看看ZookeeperRegistry的doRegister方法实现,根据url构建节点路径,/dubbo/{servicePath}/providers/{urlString},例如: /dubbo/org.apache.dubbo.demo.TripleService/providers/tri%3A%2F%2F192.168.1.7%3A50051%2Forg.apache.dubbo.demo.TripleService%3Fanyhost%3Dtrue%26application%3Ddemo-provider%26application.version%3D1%26background%3Dfalse%26delay%3D5000%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26interface%3Dorg.apache.dubbo.demo.TripleService%26methods%3Dhello%26pid%3D2624%26revision%3D1.0.0%26service-name-mapping%3Dtrue%26side%3Dprovider%26timeout%3D5000%26timestamp%3D1666705770994%26version%3D1.0.0,节点的值是服务提供者的节点ip。

注意此节点是一个临时节点,当服务关闭时节点删除,值是服务提供者的节点ip。

/**
 * ZookeeperRegistry的方法
 *
 * 注册接口级别的服务提供者url到zookeeper
 * @param url 服务提供者url
 */
@Override
public void doRegister(URL url) {
    try {
        checkDestroyed();
        //根据url构建节点路径,/dubbo/{servicePath}/providers/{url}
        //例如: /dubbo/org.apache.dubbo.demo.TripleService/providers/tri%3A%2F%2F192.168.1.7%3A50051%2Forg.apache.dubbo.demo.TripleService%3Fanyhost%3Dtrue%26application%3Ddemo-provider%26application.version%3D1%26background%3Dfalse%26delay%3D5000%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26interface%3Dorg.apache.dubbo.demo.TripleService%26methods%3Dhello%26pid%3D2624%26revision%3D1.0.0%26service-name-mapping%3Dtrue%26side%3Dprovider%26timeout%3D5000%26timestamp%3D1666705770994%26version%3D1.0.0
        //注意此节点是一个临时节点
        zkClient.create(toUrlPath(url), url.getParameter(DYNAMIC_KEY, true));
    } catch (Throwable e) {
        throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
    }
}

对于接口级的服务注册,在zookeeper中的节点样式如下。

Dubbo 3.x源码(16)—Dubbo服务发布导出源码(5),Dubbo 3.x 源码,dubbo,java,dubbo服务发布导出源码,dubbo源码

每个服务的每个接口都有一个单独的url节点,这些url一般来说除了ip和端口不同,其他配置都是相同的,因此存在大量的数据冗余,增加了注册中心的压力,而dubbo3引入的应用级服务注册发现,其目的之一就是解决接口级的服务注册发现的数据冗余问题,后面会讲到。

4 总结

本次我们学习了在导出远程服务得到Exporter之后,继续通过Registry将其注册到远程注册中心的源码,大概逻辑:

  1. 基于Dubbo SPI机制根据注册中心url加载具体的注册中心操作类Registry,应用级服务导出协议service-discovery-registry对应着ServiceDiscoveryRegistry,接口级服务导出协议则会获取真实注册中心协议对应的Registry。
  2. 通过调用Registry#register方法向远程注册中心注册服务提供者url。对于接口级服务导出协议会直接注册到注册中心,而对于应用级服务导出协议则仅仅是存入到本地内存中,在后面才会将服务信息真正的注册。

到这里,我们的Dubbo服务导出过程中的Protocol#export方法的源码就基本学习完毕了(还差一个 exported方法),还记得之前学的内容吗?这个方法实际上是在ServiceConfig#doExportUrl方法中调用的哦!

之前的内容忘了也没关系,下一章我们将会学习最后的exported()方法,并且会对Dubbo服务导出的整体源码流程进行一个比较全面的总结。文章来源地址https://www.toymoban.com/news/detail-823519.html

到了这里,关于Dubbo 3.x源码(16)—Dubbo服务发布导出源码(5)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • dubbo源码阅读之-java spi, dubbo spi 和 Spring spi 到底有啥区别

    SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。

    2024年02月08日
    浏览(41)
  • 从源码全面解析 dubbo 消费端服务调用的来龙去脉

    👏作者简介:大家好,我是爱敲代码的小黄,独角兽企业的Java开发工程师,CSDN博客专家,阿里云专家博主 📕系列专栏:Java设计模式、Spring源码系列、Netty源码系列、Kafka源码系列、JUC源码系列、duubo源码系列 🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦

    2024年02月09日
    浏览(35)
  • 2.16日学习打卡----初学Dubbo(一)

    可以看我的这篇文章–2.14日学习打卡----初学Zookeeper(一) RPC(Remote Procedure Call)远程过程调用,它是一种通过网络从远程计算机程序上请求服务。 大白话理解就是:RPC让你用别人家的东西就像自己家的一样。 RPC两个作用: 屏蔽远程调用跟本地调用的区别,让我们感觉就是调用项

    2024年02月19日
    浏览(37)
  • 精进云原生 - Dubbo 3.2 正式发布

    我们非常高兴地宣布,Dubbo 3.2 已经正式发布了!这个版本带来了许多新功能和改进,这也是 Dubbo 在面对云原生化的当下的一次重要的尝试。 Apache Dubbo 是一款 RPC 服务开发框架,用于解决微服务架构下的服务治理与通信问题,官方提供了 Java、Golang 等多语言 SDK 实现。使用

    2024年03月08日
    浏览(32)
  • Java 【dubbo rpc改feign调用】解决调用服务提供方无法传递完整参数问题

    【框架改造问题点记录,dubbo改为spring cloud alibaba】 【第二篇】feign接口异常解决 【描述】多参数情况下,调用服务提供方无法传递完整参数、改@SpringQueryMap原因是会将实体自动拆分为拼接参数。目前只遇到多参数:实体和单参数情况,持续更新… 汇总: 1.多个普通参数,

    2024年02月16日
    浏览(56)
  • Dubbo源码浅析(一)—RPC框架与Dubbo

    RPC,Remote Procedure Call 即远程过程调用,与之相对的是本地服务调用,即LPC(Local Procedure Call)。本地服务调用比较常用,像我们应用内部程序 (注意此处是程序而不是方法,程序包含方法) 互相调用即为本地过程调用,而远程过程调用是指在本地调取远程过程进行使用。 而 RPC框

    2024年02月08日
    浏览(41)
  • Dubbo 指定调用固定ip+port dubbo调用指定服务 dubbo调用不随机 dubbo自定义调用服务 dubbo点对点通信 dubbo指定ip

    1. 在写分布式im时nami-im: 分布式im, 集群 zookeeper netty kafka nacos rpc主要为gate(长连接服务) logic (业务) lsb (负载均衡)store(存储) - Gitee.com,需要指定某一长连接服务调用,其他博客得都调不通,写的有问题。要不就是通过xml进行配置,本文主要是以代码形式,调用前 配

    2024年02月15日
    浏览(43)
  • 【Dubbo核心 详解三】Dubbo服务接口的详解

    ✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: Dubbo专栏 本文将介绍 Dubbo 服务接口的基本概念和特点,实现方式和应用场景,以及注册与发现、调用、属性和参数、异常处理、日志和监控、高级特性、微

    2023年04月24日
    浏览(80)
  • Apache Dubbo 首个 Node.js 3.0-alpha 版本正式发布

    Apache Dubbo 是一款易用、高性能的 WEB 和 RPC 框架,同时为构建企业级微服务提供服务发现、流量治理、可观测、认证鉴权等能力、工具与最佳实践。经过近几年发展,Dubbo3 已在阿里巴巴集团各条业务线实现全面推广,成功取代运行多年的 HSF 框架,同时 Dubbo3 的多语言体系也有

    2024年02月08日
    浏览(51)
  • Dubbo之ExtensionLoader源码解析

    ExtensionLoader包含了扩展机制的逻辑,类似ClassLoader的功能用途。ExtensionLoader主要功能是加载约定路径下的SPI文件,获取扩展类的类名,并做Class类、实例的缓存。里面还包含自动包装、自动加载、自适应、自动激活等功能的实现逻辑。 2.1.1)主要成员变量分析 2.1.2)主要成员方

    2024年02月12日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包