Comment le serveur du centre de configuration distribué perçoit-il que la configuration a été modifiée ?

introduction

J'ai écrit un article "Comment le centre de configuration distribué apollo perçoit-il la modification de la configuration en temps réel" , c'est-à-dire comment le client client sait-il que la configuration a été modifiée ? De nombreux lecteurs m'ont envoyé un message privé depuis que vous avez dit comment le côté client perçoit it. , comment le serveur sait-il que la configuration a été modifiée. Aujourd'hui, regardons comment Apollo modifie le fichier de configuration dans Portal et comment notifier configService. Qu'est-ce que portal et configService ? Il est recommandé de lire cet article "Comment le centre de configuration distribué apollo perçoit-il la modification de la configuration en temps réel" , qui contient une brève introduction à ces modules. Si vous ne voulez vraiment pas le lire, Je peux juste couper une image iciinsérez la description de l'image ici

Comment le serveur perçoit-il les mises à jour

Jetons un coup d'œil à une image fournie par le site officielinsérez la description de l'image ici

1. L'utilisateur exploite la version de configuration dans le portail

2. Le portail appelle l'opération d'interface du service d'administration pour publier 3. Une fois que le service d'administration a publié la configuration, il envoie un ReleaseMessage à chaque service de configuration 4. Une fois que le service de configuration a reçu le ReleaseMessage, il notifie le client correspondant

Le processus ci-dessus est le processus principal de Portal à ConfigService. Examinons les détails spécifiques. Pour connaître les détails, nous devons déboguer un code source par nous-mêmes. Nous pouvons exécuter le projet localement par nous-mêmes selon la documentation sur le site officiel. La documentation est toujours très détaillée, tant que vous suivez les étapes, vous pouvez l'exécuter. Nous créons simplement un nouveau projet et éditons la clé, puis ouvrons F12 du navigateur. Lorsque nous cliquons sur le bouton Soumettre, nous saurons quelles interfaces elle a appelées. Avec les interfaces, nous saurons que le reste de l'entrée est à casser. le point. débogué.

Comment obtenir AdminService

insérez la description de l'image iciSelon cette méthode, peut-on localiser le contrôleur du code back-end du module portail ? Trouvez le contrôleur correspondant et ouvrez-le pour voir qu'il n'y a pratiquement pas de logique métier, insérez la description de l'image icipuis portalappelez adminService-le. insérez la description de l'image iciSelon la façon dont nous pouvons trouver l'adminService correspondant, comment le portail trouve-t-il le service adminService correspondant, car adminService peut déployer plusieurs machines, ici nous devons utiliser l'enregistrement de service et découvrir que adminService ne peut être enregistré qu'après être arrivé au centre de service, le portail peut obtenir le service adminService correspondant via le centre d'enregistrement de service. ApolloPar défaut, eureka est utilisé pour l'enregistrement et la découverte de services. Il fournit également nacos et consul pour l'enregistrement et la découverte de services. Il fournit également une sorte de kubernetes qui n'utilise pas de tiers pour l'enregistrement et la découverte de services, et configure directement l'adresse de le service dans la base de données. . Si plusieurs adresses peuvent être séparées par des virgules dans la base de données.insérez la description de l'image iciIl fournit quatre façons d'obtenir la liste des services. Si le registre que nous utilisons est eureka, devons-nous obtenir la liste des services via l'API eureka ? Si notre découverte de service utilise nacos, devons-nous passer l'API nacos ? Pour obtenir un liste des prestations. . . Par conséquent, Apollo fournit une couche MetaService pour encapsuler les détails de la découverte de service. Pour le portail et le client, les informations de service du service d'administration et du service de configuration sont toujours obtenues via une interface Http, et il n'est pas nécessaire de se soucier de l'enregistrement réel du service et composants de découverte derrière elle. Tout comme nous déplaçons habituellement des briques, il n'y a pas de problème qui ne puisse être résolu en ajoutant une couche intermédiaire. Si l'une échoue, ajoutez-en une autre. MetaService fournit donc deux interfaces services/admin et services/config pour obtenir respectivement les informations de service du service d'administration et du service de configuration. Alors, comment Portal appelle-t-il l'interface services/admin ? Dans la classe com.ctrip.framework.apollo.portal.component#AdminServiceAddressLocator du projet apollo-portal,

  • Lorsque cette classe est chargée, elle obtient l'adresse de service d'adminService via l'interface services/admin fournie par MetaService pour la mise en cache.
  @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);
  }
复制代码

insérez la description de l'image iciCe qui précède consiste à demander l'adresse de MetaService, alors quelle est l'adresse de MetaService ? Comment obtenir ceci? com.ctrip.framework.apollo.portal.environment#DefaultPortalMetaServerProvider Cette classe.

Le module de portail est terminé, et nous y retournons adminService. En portalappelant l'adresse de l'interface d'adminService, on retrouve rapidement son entrée.La mise en place d'AdminService est également très 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;
  }
复制代码

Annotation PreAcquireNamespaceLock

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

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

发布配置

接下来我们要使上面新增的配置生效,并且推送给客户端。同样的我们点击发布按钮然后就能知道对应的后端方法入口 insérez la description de l'image ici 我们通过这个接口可以直接找到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是如何实时感知配置被修改》 insérez la description de l'image ici

总结

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

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

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

Le code source d'apollo est relativement simple par rapport à d'autres intergiciels, et il convient mieux aux étudiants qui souhaitent étudier le code source de l'intergiciel, mais ne savent pas par où commencer.

Finir

  • En raison de mon manque de connaissances et de connaissances, il est inévitable qu'il y ait des erreurs. Si vous trouvez un mauvais endroit, veuillez laisser un message et me le signaler, et je le corrigerai.
  • Si vous pensez que l'article n'est pas mauvais, vos transmissions, partages, appréciations, likes et commentaires sont pour moi le plus grand encouragement.
  • Merci d'avoir lu, vous êtes les bienvenus et appréciez votre attention.

Debout sur les épaules de géants www.apolloconfig.com/#/zh/design… www.iocoder.cn/Apollo/clie…

Je suppose que tu aimes

Origine juejin.im/post/7084067200620822536
conseillé
Classement