Soul网关第9天:使用nacos同步数据到网关

1,019 阅读3分钟

一、准备工作

1、学习nacos

nacos 官网( nacos.io/ )上的描述是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。an easy-to-use dynamic service discovery, configuration and service management platform for building cloud native applications.

我们更具这句话可以猜测 nacos 功能上应该和 Eureka 类似,但是更强大,至少两个方面:支持接入的服务协议更多(起码写着有云原生);通过控制台。

列举一下官方介绍的三大特性:

  • 动态配置服务 动态配置服务让您能够以中心化、外部化和动态化的方式管理所有环境的配置。动态配置消除了配置变更时重新部署应用和服务的需要。配置中心化管理让实现无状态服务更简单,也让按需弹性扩展服务更容易。

  • 服务发现及管理 服务发现及管理 动态服务发现对以服务为中心的(例如微服务和云原生)应用架构方式非常关键。Nacos支持DNS-Based和RPC-Based(Dubbo、gRPC)模式的服务发现。Nacos也提供实时健康检查,以防止将请求发往不健康的主机或服务实例。借助Nacos,您可以更容易地为您的服务实现断路器。

  • 动态DNS服务 通过支持权重路由,动态DNS服务能让您轻松实现中间层负载均衡、更灵活的路由策略、流量控制以及简单数据中心内网的简单DNS解析服务。动态DNS服务还能让您更容易地实现以DNS协议为基础的服务发现,以消除耦合到厂商私有服务发现API上的风险。

总结关键词:中心化、微服务和云原生、实时健康检查

2、启动nacos

1) 下载 nacos,启动 sh startup.sh -m standalone

使用 lsof -i:8848jps -lvm ,发现 nacos 默认监听端口就是8848

2) 启动 soul-adminsoul-bootstrap

到今天数据同步的了解了很多,所以soul-bootstrap pom 文件里要加上 nacos 的 starter 配置

        <!--soul data sync start use nacos-->
        <dependency>
            <groupId>org.dromara</groupId>
            <artifactId>soul-spring-boot-starter-sync-data-nacos</artifactId>
            <version>${project.version}</version>
        </dependency>

二、使用nacos同步数据到网关

1、从 soul-bootstrap 依赖的 soul-spring-boot-starter-sync-data-nacos 看起

看看初始化了哪些 bean,bean 干了什么?

public class NacosSyncDataService extends NacosCacheHandler implements AutoCloseable, SyncDataService {

    /**
     * Instantiates a new Nacos sync data service.
     *
     * @param configService         the config service
     * @param pluginDataSubscriber the plugin data subscriber
     * @param metaDataSubscribers   the meta data subscribers
     * @param authDataSubscribers   the auth data subscribers
     */
    public NacosSyncDataService(final ConfigService configService, final PluginDataSubscriber pluginDataSubscriber,
                                final List<MetaDataSubscriber> metaDataSubscribers, final List<AuthDataSubscriber> authDataSubscribers) {

        super(configService, pluginDataSubscriber, metaDataSubscribers, authDataSubscribers);
        start();
    }

    /**
     * Start.
     */
    public void start() {
        watcherData(PLUGIN_DATA_ID, this::updatePluginMap);
        watcherData(SELECTOR_DATA_ID, this::updateSelectorMap);
        watcherData(RULE_DATA_ID, this::updateRuleMap);
        watcherData(META_DATA_ID, this::updateMetaDataMap);
        watcherData(AUTH_DATA_ID, this::updateAuthMap);
    }

    @Override
    public void close() {
        LISTENERS.forEach((dataId, lss) -> {
            lss.forEach(listener -> getConfigService().removeListener(dataId, GROUP, listener));
            lss.clear();
        });
        LISTENERS.clear();
    }
}

大体猜测就是启动的时候监听了这些常量配置,来了数据更新网关服务本地缓存。

2、从控制台事件监听方法看

这几天一直控制台数据同步一直靠这个事件监听类 DataChangedEventDispatcher 入手。

这是服务端 nacos 配置

    /**
     * The type Nacos listener.
     */
    @Configuration
    @ConditionalOnProperty(prefix = "soul.sync.nacos", name = "url")
    @Import(NacosConfiguration.class)
    static class NacosListener {

        /**
         * Data changed listener data changed listener.
         *
         * @param configService the config service
         * @return the data changed listener
         */
        @Bean
        @ConditionalOnMissingBean(NacosDataChangedListener.class)
        public DataChangedListener nacosDataChangedListener(final ConfigService configService) {
            return new NacosDataChangedListener(configService);
        }
    }

我们随便找一个权限更新事件,看一下 NacosDataChangedListener#onAppAuthChanged 方法

    @Override
    @SneakyThrows
    public void onAppAuthChanged(final List<AppAuthData> changed, final DataEventTypeEnum eventType) {
        updateAuthMap(getConfig(AUTH_DATA_ID));
        switch (eventType) {
            case DELETE:
                changed.forEach(appAuth -> AUTH_MAP.remove(appAuth.getAppKey()));
                break;
            case REFRESH:
            case MYSELF:
                Set<String> set = new HashSet<>(AUTH_MAP.keySet());
                changed.forEach(appAuth -> {
                    set.remove(appAuth.getAppKey());
                    AUTH_MAP.put(appAuth.getAppKey(), appAuth);
                });
                AUTH_MAP.keySet().removeAll(set);
                break;
            default:
                changed.forEach(appAuth -> AUTH_MAP.put(appAuth.getAppKey(), appAuth));
                break;
        }
        publishConfig(AUTH_DATA_ID, AUTH_MAP);
    }

看着没有数据库的参与,将事件数据存到Map,然后通过 nacas 发送给注册的网关服务。