55-微服务技术栈(高级):微服务网关Soul(数据同步原理)

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: Soul 网关在启动时,会从从配置服务同步配置数据,并且支持推拉模式获取配置变更信息,并且更新本地缓存。而管理员在管理后台,变更用户、规则、插件、流量配置,通过推拉模式将变更信息同步给 Soul 网关,具体是 push 模式,还是 pull 模式取决于配置。关于配置同步模块,其实是一个简版的配置中心。

下图展示了 Soul 数据同步的流程,Soul 网关在启动时,会从从配置服务同步配置数据,并且支持推拉模式获取配置变更信息,并且更新本地缓存。而管理员在管理后台,变更用户、规则、插件、流量配置,通过推拉模式将变更信息同步给 Soul 网关,具体是 push 模式,还是 pull 模式取决于配置。关于配置同步模块,其实是一个简版的配置中心。

1.x 版本中,配置服务依赖 zookeeper 实现,管理后台将变更信息 push 给网关。而 2.x 版本支持 webosockethttpzookeeper,通过 soul.sync.strategy 指定对应的同步策略,默认使用 http 长轮询同步策略,可以做到秒级数据同步。但是,有一点需要注意的是,soul-websoul-admin 必须使用相同的同步机制。

如下图所示,soul-admin 在用户发生配置变更之后,会通过 EventPublisher 发出配置变更通知,由 EventDispatcher 处理该变更通知,然后根据配置的同步策略(http、weboscket、zookeeper),将配置发送给对应的事件处理器

  • 如果是 websocket 同步策略,则将变更后的数据主动推送给 soul-web,并且在网关层,会有对应的 WebsocketCacheHandler 处理器处理来处 admin 的数据推送
  • 如果是 zookeeper 同步策略,将变更数据更新到 zookeeper,而 ZookeeperSyncCache 会监听到 zookeeper 的数据变更,并予以处理
  • 如果是 http 同步策略,soul-web 主动发起长轮询请求,默认有 90s 超时时间,如果 soul-admin 没有数据变更,则会阻塞 http 请求,如果有数据发生变更则响应变更的数据信息,如果超过 60s 仍然没有数据变更则响应空数据,网关层接到响应后,继续发起 http 请求,反复同样的请求

zookeeper同步

基于 zookeeper 的同步原理很简单,主要是依赖 zookeeperwatch 机制,soul-web 会监听配置的节点,soul-admin 在启动的时候,会将数据全量写入 zookeeper,后续数据发生变更时,会增量更新 zookeeper 的节点,与此同时,soul-web 会监听配置信息的节点,一旦有信息变更时,会更新本地缓存。

soul 将配置信息写到zookeeper节点,是通过精细设计的。

websocket同步

websocketzookeeper 机制有点类似,将网关与 admin 建立好 websocket 连接时,admin 会推送一次全量数据,后续如果配置数据发生变更,则将增量数据通过 websocket 主动推送给 soul-web

使用websocket同步的时候,特别要注意断线重连,也叫保持心跳。soul使用java-websocket 这个第三方库来进行websocket连接。

public class WebsocketSyncCache extends WebsocketCacheHandler {

   /**

    * The Client.

    */

   private WebSocketClient client;

   public WebsocketSyncCache(final SoulConfig.WebsocketConfig websocketConfig) {

       ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1,

               SoulThreadFactory.create("websocket-connect", true));

        client = new WebSocketClient(new URI(websocketConfig.getUrl())) {

               @Override

               public void onOpen(final ServerHandshake serverHandshake) {

                 //....

               }

               @Override

               public void onMessage(final String result) {

                 //....

               }    

           };

       //进行连接

       client.connectBlocking();

       //使用调度线程池进行断线重连,30秒进行一次

       executor.scheduleAtFixedRate(() -> {

           if (client != null && client.isClosed()) {

                   client.reconnectBlocking();

           }

       }, 10, 30, TimeUnit.SECONDS);

   }

http长轮询

zookeeper、websocket 数据同步的机制比较简单,而 http 同步会相对复杂一些。Soul 借鉴了 ApolloNacos 的设计思想,取决精华,自己实现了 http 长轮询数据同步功能。注意,这里并非传统的 ajax 长轮询!

http 长轮询机制如上所示,soul-web 网关请求 admin 的配置服务,读取超时时间为 90s,意味着网关层请求配置服务最多会等待 90s,这样便于 admin 配置服务及时响应变更数据,从而实现准实时推送。

http 请求到达 sou-admin 之后,并非立马响应数据,而是利用 Servlet3.0 的异步机制,异步响应数据。首先,将长轮询请求任务 LongPollingClient 扔到 BlocingQueue 中,并且开启调度任务,60s 后执行,这样做的目的是 60s 后将该长轮询请求移除队列,即便是这段时间内没有发生配置数据变更。因为即便是没有配置变更,也得让网关知道,总不能让其干等吧,而且网关请求配置服务时,也有 90s 的超时时间。

public void doLongPolling(final HttpServletRequest request, final HttpServletResponse response) {

   // 因为soul-web可能未收到某个配置变更的通知,因此MD5值可能不一致,则立即响应

   List<ConfigGroupEnum> changedGroup = compareMD5(request);

   String clientIp = getRemoteIp(request);

   if (CollectionUtils.isNotEmpty(changedGroup)) {

       this.generateResponse(response, changedGroup);

       return;

   }

   // Servlet3.0异步响应http请求

   final AsyncContext asyncContext = request.startAsync();

   asyncContext.setTimeout(0L);

   scheduler.execute(new LongPollingClient(asyncContext, clientIp, 60));

}

   

class LongPollingClient implements Runnable {

   LongPollingClient(final AsyncContext ac, final String ip, final long timeoutTime) {

       // 省略......

   }

   @Override

   public void run() {

       // 加入定时任务,如果60s之内没有配置变更,则60s后执行,响应http请求

       this.asyncTimeoutFuture = scheduler.schedule(() -> {

           // clients是阻塞队列,保存了来处soul-web的请求信息

           clients.remove(LongPollingClient.this);

           List<ConfigGroupEnum> changedGroups = HttpLongPollingDataChangedListener.compareMD5((HttpServletRequest) asyncContext.getRequest());

           sendResponse(changedGroups);

       }, timeoutTime, TimeUnit.MILLISECONDS);

       //

       clients.add(this);

   }

}

如果这段时间内,管理员变更了配置数据,此时,会挨个移除队列中的长轮询请求,并响应数据,告知是哪个 Group 的数据发生了变更(我们将插件、规则、流量配置、用户配置数据分成不同的组)。网关收到响应信息之后,只知道是哪个 Group 发生了配置变更,还需要再次请求该 Group 的配置数据。有人会问,为什么不是直接将变更的数据写出?我们在开发的时候,也深入讨论过该问题,因为 http 长轮询机制只能保证准实时,如果在网关层处理不及时,或者管理员频繁更新配置,很有可能便错过了某个配置变更的推送,安全起见,我们只告知某个 Group 信息发生了变更。

// soul-admin发生了配置变更,挨个将队列中的请求移除,并予以响应

class DataChangeTask implements Runnable {

   DataChangeTask(final ConfigGroupEnum groupKey) {

       this.groupKey = groupKey;

   }

   @Override

   public void run() {

       try {

           for (Iterator<LongPollingClient> iter = clients.iterator(); iter.hasNext(); ) {

               LongPollingClient client = iter.next();

               iter.remove();

               client.sendResponse(Collections.singletonList(groupKey));

           }

       } catch (Throwable e) {

           LOGGER.error("data change error.", e);

       }

   }

}

soul-web 网关层接收到 http 响应信息之后,拉取变更信息(如果有变更的话),然后再次请求 soul-admin 的配置服务,如此反复循环。

总结

总体继承关系图,如下图所示,核心借助于DataChangedEventDispatcher下面的五个监听器,根据不同的数据同步策略,触发不同的listener。

每个具体实现,都包含下面五个实现方法,用于数据同步。

其中,Http长轮询,借鉴了 `Apollo``Nacos` 的设计思想,取决精华,自己实现了 `http` 长轮询数据同步功能。注意,这里并非传统的 ajax 长轮询!

soul内置依赖 `spring-webflux` 而其底层是使用的netty。这一块只要是使用的netty线程模型

@Bean

public NettyReactiveWebServerFactory nettyReactiveWebServerFactory() {

   NettyReactiveWebServerFactory webServerFactory = new NettyReactiveWebServerFactory();

   webServerFactory.addServerCustomizers(new EventLoopNettyCustomizer());

   return webServerFactory;

}


private static class EventLoopNettyCustomizer implements NettyServerCustomizer {


   @Override

   public HttpServer apply(final HttpServer httpServer) {

       return httpServer

           .tcpConfiguration(tcpServer -> tcpServer

                             .runOn(LoopResources.create("soul-netty", 1, DEFAULT_IO_WORKER_COUNT, true), false)

                             .selectorOption(ChannelOption.SO_REUSEADDR, true)

                             .selectorOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)

                             .option(ChannelOption.TCP_NODELAY, true)

                             .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT));

   }

}

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
相关文章
|
7天前
|
微服务 应用服务中间件
微服务跨域(通过网关配置进行跨域)
在单体架构中,我们通常通过SpringMVC配置类实现CORS跨域支持,设置允许的来源、请求头、方法及凭证等。然而,在微服务架构下,因浏览器首先访问网关再进行服务路由,需在网关配置跨域。对于无SpringMVC环境的网关(如使用Gateway组件),我们可在YAML文件中配置`spring.cloud.gateway.globalcors`属性,以实现全局跨域支持。
26 0
|
3天前
|
运维 Cloud Native 应用服务中间件
阿里云微服务引擎 MSE 及 API 网关 2024 年 07 月产品动态
阿里云微服务引擎 MSE 面向业界主流开源微服务项目, 提供注册配置中心和分布式协调(原生支持 Nacos/ZooKeeper/Eureka )、云原生网关(原生支持Higress/Nginx/Envoy,遵循Ingress标准)、微服务治理(原生支持 Spring Cloud/Dubbo/Sentinel,遵循 OpenSergo 服务治理规范)能力。API 网关 (API Gateway),提供 APl 托管服务,覆盖设计、开发、测试、发布、售卖、运维监测、安全管控、下线等 API 生命周期阶段。帮助您快速构建以 API 为核心的系统架构.满足新技术引入、系统集成、业务中台等诸多场景需要。
|
6天前
|
API
阿里云微服务引擎及 API 网关 2024 年 7 月产品动态
阿里云微服务引擎及 API 网关 2024 年 7 月产品动态。
|
9天前
|
设计模式 监控 API
探索微服务架构中的API网关模式
在微服务的宇宙里,API网关是连接星辰的桥梁。它不仅管理着服务间的通信流量,还肩负着保护、增强和监控微服务集群的重任。本文将带你走进API网关的世界,了解其如何成为微服务架构中不可或缺的一环,以及它在实际应用中扮演的角色和面临的挑战。
|
12天前
|
安全 前端开发 Java
微服务网关及其配置
微服务网关及其配置
50 4
|
12天前
|
缓存 监控 API
【微服务战场上的神秘守门人】:揭秘API网关的超能力 —— 探索微服务架构中的终极守护者与它的神奇魔法!
【8月更文挑战第7天】随着微服务架构的流行,企业应用被拆分为围绕特定业务功能构建的小型服务。API网关作为微服务间的通信管理核心,对请求进行路由、认证、限流等处理,简化客户端集成并提升用户体验。以电商应用为例,通过Kong部署API网关,配置产品目录等服务的API及JWT认证插件,确保安全高效的数据交互。这种方式不仅增强了系统的可维护性和扩展性,还提供了额外的安全保障。
30 2
|
15天前
|
负载均衡 监控 API
探索微服务架构中的API网关模式
在微服务架构的海洋中,API网关扮演着枢纽的角色。它不仅是客户端请求的接收者,也是各个微服务间通信的协调者。本文将深入探讨API网关的设计原则、实现策略以及它在微服务生态中的重要性。我们将通过实际案例分析,了解API网关如何优化系统性能、提高安全性和简化客户端与服务的交互。
31 4
|
15天前
|
运维 监控 负载均衡
探索微服务架构中的API网关设计
在微服务架构的复杂性中,API网关作为客户端和后端服务间的桥梁,扮演着至关重要的角色。本文将深入探讨如何设计一个高效、可扩展且安全的API网关,包括处理请求转发、负载均衡、身份验证、监控与日志记录等核心功能,并讨论如何在保障性能的同时确保系统的高可用性和安全性。通过具体案例,我们将了解API网关在实际生产环境中的实现方式及其对整个微服务生态系统的影响。
38 3
|
1天前
|
canal 关系型数据库 MySQL
"揭秘阿里数据同步黑科技Canal:从原理到实战,手把手教你玩转MySQL数据秒级同步,让你的数据处理能力瞬间飙升,成为技术界的新晋网红!"
【8月更文挑战第18天】Canal是一款由阿里巴巴开源的高性能数据同步系统,它通过解析MySQL的增量日志(Binlog),提供低延迟、可靠的数据订阅和消费功能。Canal模拟MySQL Slave与Master间的交互协议来接收并解析Binary Log,支持数据的增量同步。配置简单直观,包括Server和Instance两层配置。在实战中,Canal可用于数据库镜像、实时备份等多种场景,通过集成Canal Client可实现数据的消费和处理,如更新缓存或写入消息队列。
8 0
|
12天前
|
监控 供应链 安全
构建高效微服务架构:API网关与服务熔断策略
【7月更文挑战第38天】随着现代应用程序向微服务架构的转型,系统的稳定性和效率成为了开发团队关注的焦点。本文将探讨在微服务环境中实现系统可靠性的关键组件——API网关,以及如何在服务间通讯时采用熔断机制来防止故障蔓延。通过分析API网关的核心功能和设计原则,并结合熔断策略的最佳实践,我们旨在提供一套提高分布式系统弹性的策略。

热门文章

最新文章