¿Cómo percibe el servidor del centro de configuración distribuida que se ha modificado la configuración?

Introducción

Escribí un artículo "¿Cómo percibe el centro de configuración distribuida apollo la modificación de la configuración en tiempo real" , es decir, ¿cómo sabe el cliente cliente que la configuración ha sido modificada? Muchos lectores me envían mensajes privados ya que dijiste cómo percibe el lado del cliente it. , cómo sabe el servidor que la configuración ha sido modificada. Hoy, echemos un vistazo a cómo Apollo modifica el archivo de configuración en Portal y cómo notificar a configService. ¿Qué son portal y configService? Se recomienda leer este artículo "Cómo percibe el centro de configuración distribuida apollo la modificación de la configuración en tiempo real" , el cual tiene una breve introducción a estos módulos, si realmente no quieres leerlo, Puedo cortar una imagen aquíinserte la descripción de la imagen aquí

¿Cómo percibe el servidor las actualizaciones?

Echemos un vistazo a una imagen proporcionada por el sitio web oficial.inserte la descripción de la imagen aquí

1. El usuario opera la versión de configuración en el Portal

2. El portal llama a la operación de interfaz del servicio de administración para publicar 3. Después de que el servicio de administración publica la configuración, envía un mensaje de liberación a cada servicio de configuración 4. Después de que el servicio de configuración recibe el mensaje de liberación, notifica al cliente correspondiente

El proceso anterior es el proceso principal desde Portal hasta ConfigService. Echemos un vistazo a los detalles específicos. Para conocer los detalles, tenemos que depurar un código fuente nosotros mismos. Podemos ejecutar el proyecto localmente por nosotros mismos de acuerdo con la documentación en el sitio web oficial. La documentación aún es muy detallada, siempre que siga los pasos, puede ejecutarla. Simplemente creamos un nuevo proyecto y editamos la clave, luego abrimos F12 del navegador. Cuando hagamos clic en el botón Enviar, sabremos a qué interfaces ha llamado. Con las interfaces, sabremos que el resto de la entrada es romper el punto depurado.

Cómo obtener el servicio de administración

inserte la descripción de la imagen aquíDe acuerdo con este método, ¿podemos ubicar el controlador del código de fondo del módulo del portal? Encuentre el controlador correspondiente y ábralo para ver que básicamente no hay lógica comercial, inserte la descripción de la imagen aquíy luego portalllámelo adminService. inserte la descripción de la imagen aquíDe acuerdo con la forma en que podemos encontrar el servicio de administración correspondiente, ¿cómo encuentra el portal el servicio de servicio de administración correspondiente? Debido a que el servicio de administración puede implementar varias máquinas, aquí debemos usar el registro del servicio y descubrir que el servicio de administración solo se puede registrar después de llegar al centro de servicio. el portal puede obtener el servicio de adminService correspondiente a través del centro de registro de servicios. ApolloDe forma predeterminada, eureka se utiliza para el registro y descubrimiento de servicios. También proporciona nacos y consul para el registro y descubrimiento de servicios. También proporciona un tipo de kubernetes que no utiliza un tercero para el registro y descubrimiento de servicios, y configura directamente la dirección de el servicio en la base de datos. Si varias direcciones se pueden separar por comas en la base de datos.inserte la descripción de la imagen aquíProporciona cuatro formas de obtener la lista de servicios. Si el registro que usamos es eureka, ¿necesitamos obtener la lista de servicios a través de la API de eureka? Si nuestro descubrimiento de servicios usa nacos, ¿necesitamos pasar la API de nacos? para obtener una lista de servicios . . Por lo tanto, Apollo proporciona una capa de MetaService para encapsular los detalles del descubrimiento del servicio.Para el Portal y el Cliente, la información del servicio de Admin Service y Config Service siempre se obtiene a través de una interfaz Http, y no hay necesidad de preocuparse por el registro del servicio real y componentes de descubrimiento detrás de él. Al igual que solemos mover ladrillos, no hay problema que no se pueda solucionar añadiendo una capa intermedia, si falla una, entonces añadir otra. Entonces MetaService proporciona dos interfaces services/admin y services/config para obtener información de servicio de Admin Service y Config Service respectivamente. Entonces, ¿cómo llama Portal a la interfaz de servicios/administración? En la clase com.ctrip.framework.apollo.portal.component#AdminServiceAddressLocator del proyecto apollo-portal,

  • Cuando se carga esta clase, obtendrá la dirección de servicio de adminService a través de la interfaz de servicios/administración proporcionada por MetaService para el almacenamiento en caché.
  @PostConstruct
  public void init() {
    allEnvs = portalSettings.getAllEnvs();
    //init restTemplate
    restTemplate = restTemplateFactory.getObject();
    
    refreshServiceAddressService =
        Executors.newScheduledThreadPool(1, ApolloThreadFactory.create("ServiceLocator", true));
	// 创建延迟任务,1s后开始执行获取AdminService服务地址
    refreshServiceAddressService.schedule(new RefreshAdminServerAddressTask(), 1, TimeUnit.MILLISECONDS);
  }
复制代码

inserte la descripción de la imagen aquíLo anterior es para solicitar la dirección de MetaService, entonces, ¿cuál es la dirección de MetaService? ¿Cómo conseguir esto? com.ctrip.framework.apollo.portal.environment#DefaultPortalMetaServerProvider Esta clase.

El módulo del portal está terminado y volvemos a adminServiceél. Al portalllamar a la dirección de interfaz de adminService, podemos encontrar rápidamente su entrada.La implementación de AdminService también es muy simple


  @PreAcquireNamespaceLock
@PostMapping("/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items")
  public ItemDTO create(@PathVariable("appId") String appId,
                        @PathVariable("clusterName") String clusterName,
                        @PathVariable("namespaceName") String namespaceName, @RequestBody ItemDTO dto) {
    Item entity = BeanUtils.transform(Item.class, dto);

    ConfigChangeContentBuilder builder = new ConfigChangeContentBuilder();
    Item managedEntity = itemService.findOne(appId, clusterName, namespaceName, entity.getKey());
    if (managedEntity != null) {
      throw new BadRequestException("item already exists");
    }
    entity = itemService.save(entity);
    builder.createItem(entity);
    dto = BeanUtils.transform(ItemDTO.class, entity);

    Commit commit = new Commit();
    commit.setAppId(appId);
    commit.setClusterName(clusterName);
    commit.setNamespaceName(namespaceName);
    commit.setChangeSets(builder.build());
    commit.setDataChangeCreatedBy(dto.getDataChangeLastModifiedBy());
    commit.setDataChangeLastModifiedBy(dto.getDataChangeLastModifiedBy());
    commitService.save(commit);

    return dto;
  }
复制代码

PreAcquireNamespaceLock anotación

首先方法上有个@PreAcquireNamespaceLock 这个注解,这个根据名字都应该能够去猜一个大概就是去获取NameSpace的分布式锁,现在分布式锁比较常见的方式是采用redis和zookeeper。但是在这里apollo是采用数据库来实现的,具体怎么细节大家可以去看看源码应该都看的懂,无非就是加锁往DB里面插入一条数据,释放锁然后把这个数据进行删除。稍微有点不一样的就是如果获取锁失败,就直接返回失败了,不会在继续自旋或者休眠重新去获取锁。 因为获取锁失败说明已经有其他人在你之前修改了配置,只有这个人新增的配置被发布或者删除之后,其他人才能继续新增配置,这样的话就会导致一个NameSpace只能同时被一个人修改。这个限制是默认关闭的需要我们在数据库里面去配置(ApolloConfigDb的ServiceConfig表)inserte la descripción de la imagen aquí 一般我们应用的配置修改应该是比较低频的,多人同时去修改的话情况会比较少,再说有些公司是开发提交配置,测试去发布配置,提交和修改不能是同一个人,这样的话新增配置冲突就更少了,应该没有必要去配置namespace.lock.switch=true一个namespace只能一个人去修改。

接下来的代码就非常简单明了,就是一个简单的参数判断然后执行入库操作了,把数据插入到Item表里面。这是我们新增的配置数据就已经保存了。效果如下 inserte la descripción de la imagen aquí 这时候新增的配置是不起作用的,不会推送给客户端的。只是单纯一个类似于草稿的状态。

发布配置

接下来我们要使上面新增的配置生效,并且推送给客户端。同样的我们点击发布按钮然后就能知道对应的后端方法入口 inserte la descripción de la imagen aquí 我们通过这个接口可以直接找到adminService的方法入口

 public ReleaseDTO publish(@PathVariable("appId") String appId,
                            @PathVariable("clusterName") String clusterName,
                            @PathVariable("namespaceName") String namespaceName,
                            @RequestParam("name") String releaseName,
                            @RequestParam(name = "comment", required = false) String releaseComment,
                            @RequestParam("operator") String operator,
                            @RequestParam(name = "isEmergencyPublish", defaultValue = "false") boolean isEmergencyPublish) {
    Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName);
    if (namespace == null) {
      throw new NotFoundException(String.format("Could not find namespace for %s %s %s", appId,
                                                clusterName, namespaceName));
    }
    Release release = releaseService.publish(namespace, releaseName, releaseComment, operator, isEmergencyPublish);

    //send release message
    Namespace parentNamespace = namespaceService.findParentNamespace(namespace);
    String messageCluster;
    if (parentNamespace != null) {
      messageCluster = parentNamespace.getClusterName();
    } else {
      messageCluster = clusterName;
    }
    messageSender.sendMessage(ReleaseMessageKeyGenerator.generate(appId, messageCluster, namespaceName),
                              Topics.APOLLO_RELEASE_TOPIC);
    return BeanUtils.transform(ReleaseDTO.class, release);
  }
复制代码
  • 上述代码就不仔细展开分析了,感兴趣的可以自己断点调试下我们重点看下releaseService.publish 这个方法,里面有一些灰度发布相关的逻辑,不过这个不是本文的重点,这个方法主要是往release表插入数据。
  • 接下来就是messageSender.sendMessage这个方法了,这个方法主要是往ReleaseMessage表里面插入一条记录。保存完ReleaseMessage这个表会得到相应的主键ID,然后把这个ID放入到一个队列里面。然后在加载DatabaseMessageSender的时候会默认起一个定时任务去获取上面队列里面放入的消息ID,然后找出比这这些ID小的消息删除掉。

发布流程就完了,这里也没有说到服务端是怎么感知有配置修改了的。

Config Service 通知配置变化

apolloConfigService 在服务启动的时候ReleaseMessageScanner 会启动一个定时任务 每隔1s去去查询ReleaseMessage里面有没有最新的消息,如果有就会通知到所有的消息监听器比如NotificationControllerV2ConfigFileController等,这个消息监听器注册是在ConfigServiceAutoConfiguration里面注册的。 NotificationControllerV2 得到配置发布的 AppId+Cluster+Namespace 后,会通知对应的客户端,这样就从portal到configService 到 client 整个消息通知变化就串起来了。服务端通知客户端的具体细节可以看看《分布式配置中心apollo是如何实时感知配置被修改》 inserte la descripción de la imagen aquí

总结

这样服务端配置如何更新的流程就完了。

1.用户在Portal操作配置发布

2.Portal调用Admin Service的接口操作发布 3.Admin Service发布配置后,发送ReleaseMessage给各个Config Service 4.Config Service收到ReleaseMessage后,通知对应的客户端

El código fuente de apollo es relativamente simple en comparación con otros middleware, y es más adecuado para estudiantes que desean estudiar el código fuente del middleware, pero no saben cómo comenzar.

Terminar

  • Debido a mi falta de conocimiento y conocimiento, es inevitable que haya errores. Si encuentra un lugar incorrecto, deje un mensaje y me lo indique, y lo corregiré.
  • Si cree que el artículo no es malo, su reenvío, intercambio, aprecio, me gusta y comentarios son el mayor estímulo para mí.
  • Gracias por leer, eres muy bienvenido y agradezco tu atención.

De pie sobre los hombros de gigantes www.apolloconfig.com/#/zh/design… www.iocoder.cn/Apollo/clie…

Supongo que te gusta

Origin juejin.im/post/7084067200620822536
Recomendado
Clasificación