【想进大厂还不会阅读源码】ShenYu源码-接入注册中心发现服务

相信大家碰到源码时经常无从下手🙃,不知道从哪开始阅读,面对大量代码晕头转向,索性就读不下去了,又浪费了一次提升自己的机会😭。

我认为有一种方法 ,可以解决大家的困扰!那就是通过阅读某一次开源的【PR】、【ISSUE】,从这个入口出发去阅读源码!!

至此,我们发现自己开始从大量堆砌的源码中脱离开来😀。豁然开朗,柳暗花明又一村🍀。

ShenYu是一个异步的,高性能的,跨语言的,响应式的 API 网关。有关ShenYu的介绍可以戳这

一、前瞻

话不多说,奉上今天我们来阅读的PR提交

翻译过来就是,添加nacos、etcd、eureka发现服务。

我们先思考下我们的阅读线索

  1. 贡献者是怎么添加发现服务的
  2. 这些发现服务 是怎么和项目集成的,让ShenYu网关能从注册中心获取节点信息

二、探索

3个注册中心的添加流程大致是一致的,我们以Nacos为例子来进行本次pr的探索。

先整体看下pr的所有提交,代码的核心在NacosDiscoveryService 我们重点关注下。而ShenyuDiscoveryService作为底层接口来定义子类的行为动作,最后Admin模块就是来控制我们自定义的注册中心。

我们回顾上文我们整理的阅读线索2 :这些发现服务是怎么和项目集成的,让ShenYu网关能从注册中心获取节点信息。

先看下NacosDiscoveryService 是怎么获取节点信息的。可以看到,ShenYu网关通过配置和Nacos建立连接后,通过Nacos提供的NamingService.selectInstances来获取节点服务列表。

java 复制代码
    @Override
    public List<String> getRegisterData(final String key) {
        try {
            List<Instance> instances = namingService.selectInstances(key, groupName, true);
            List<String> registerData = new ArrayList<>();
            for (Instance instance : instances) {
                String data = buildInstanceInfoJson(instance);
                registerData.add(data);
            }
            return registerData;
        } catch (NacosException e) {
            LOGGER.error("Error getting Nacos service instances: {}", e.getMessage(), e);
            throw new ShenyuException(e);
        }
    }

NacosDiscoveryService类的其他方法又是什么作用。

我们看下watch方法 的入参DataChangedEventListener ,而watch方法内部又看到了listenerMap.put(key, nacosListener)。可以清楚的知道watch方法的作用就是让ShenYu网关可以在Nacos注册中心,监听到某个服务节点的动态变化。

而unwatch方法,顾名思义作用是反过来的。

java 复制代码
    @Override
    public void watch(final String key, final DataChangedEventListener listener) {
        try {
            if (!listenerMap.containsKey(key)) {
                List<Instance> initialInstances = namingService.selectInstances(key, groupName, true);
                instanceListMap.put(key, initialInstances);
                EventListener nacosListener = event -> {
                    if (event instanceof NamingEvent) {
                        try {
                            List<Instance> previousInstances = instanceListMap.get(key);
                            List<Instance> currentInstances = namingService.selectInstances(key, groupName, true);
                            compareInstances(previousInstances, currentInstances, listener);
                            instanceListMap.put(key, currentInstances);
                        } catch (NacosException e) {
                            throw new ShenyuException(e);
                        }
                    }
                };
                namingService.subscribe(key, groupName, nacosListener);
                listenerMap.put(key, nacosListener);
                LOGGER.info("Subscribed to Nacos updates for key: {}", key);
            }
        } catch (NacosException e) {
            LOGGER.error("nacosDiscoveryService error watching key: {}", key, e);
            throw new ShenyuException(e);
        }
    }

    @Override
    public void unwatch(final String key) {
        try {
            EventListener nacosListener = listenerMap.get(key);
            if (Objects.nonNull(nacosListener)) {
                namingService.unsubscribe(key, groupName, nacosListener);
                listenerMap.remove(key);
                LOGGER.info("Nacos Unwatch key: {}", key);
            }
        } catch (NacosException e) {
            LOGGER.error("Error removing Nacos service listener: {}", e.getMessage(), e);
            throw new ShenyuException(e);
        }
    }

我们看下register方法 ,ShenYu网关还提供通过该方法让我们可以注册某个节点到Nacos注册中心。同样是调用了Nacos提供的NamingService服务。

java 复制代码
    @Override
    public void register(final String key, final String value) {
        try {
            Instance instance = GsonUtils.getInstance().fromJson(value, Instance.class);
            namingService.registerInstance(key, groupName, instance);
            LOGGER.info("Registering service with key: {} and value: {}", key, value);
        } catch (NacosException e) {
            LOGGER.error("Error registering Nacos service instance: {}", e.getMessage(), e);
            throw new ShenyuException(e);
        }
    }

大家还没有忘记线索1 吧(贡献者是怎么添加发现服务的),连我都差点忘记了🤣

我们看下上文图2提到的ShenyuDiscoveryService 接口,其实贡献者就是按这个底层接口为方向,底层接口定义了新接入的注册中心,需要实现哪些行为、方法的入参是什么、规范是什么。

以底层接口为方向,添加新的注册中心发现服务其实就类似于SPI的接入

SPI与API区别

  • API是调用并用于实现目标的类、接口、方法等的描述;
  • SPI是扩展和实现以实现目标的类、接口、方法等的描述;

好了,今天的分享就到这了。大家能否感受通过PR、ISSUE这种方式来阅读源码的乐趣呢!

博主的GitHub也有一些读者感兴趣的知识可以学习😍,GitHub地址戳这

创作不易,不妨点赞、关注、收藏支持一下,各位的支持就是我创作的最大动力❤️

相关推荐
码农小野17 分钟前
基于SpringBoot的自习室预订系统
java·spring boot·后端
ac-er88881 小时前
如何在Flask中实现国际化和本地化
后端·python·flask
Adolf_19931 小时前
Flask-WTF的使用
后端·python·flask
mingzhi612 小时前
网安面试会问到的:http的长连接和短连接
http·面试·职场和发展
极客先躯3 小时前
高级java每日一道面试题-2024年9月16日-框架篇-Spring MVC和Struts的区别是什么?
java·spring·面试·mvc·struts2·框架篇·高级java
林太白5 小时前
❤Node09-用户信息token认证
数据库·后端·mysql·node.js
骆晨学长5 小时前
基于Springboot的助学金管理系统设计与实现
java·spring boot·后端
蒙娜丽宁6 小时前
深入理解Go语言中的接口定义与使用
开发语言·后端·golang·go
AskHarries6 小时前
java使用ByteBuffer进行多文件合并和拆分
java·后端
不染_是非6 小时前
Django学习实战篇六(适合略有基础的新手小白学习)(从0开发项目)
后端·python·学习·django