Enregistrement de service et découverte de services basés sur Zookeeper

avant-propos

Que vous utilisiez SOA ou une architecture de microservices, vous devez utiliser des composants d'enregistrement et de découverte de services. Lorsque je suis entré en contact avec Dubbo pour la première fois, j'étais toujours confus au sujet de l'enregistrement/découverte des services et du rôle de Zookeeper. Il semble maintenant que ma compréhension des systèmes distribués ne soit pas assez approfondie et que les principes de fonctionnement de Dubbo et de Zookeeper ne soient pas assez clairs. .

Cet article implémentera les fonctions d'enregistrement de service et de découverte de services basées sur Zookeeper. Si vous avez la même confusion que moi, j'espère que vous pourrez utiliser cet article pour comprendre comment d'autres composants utilisent Zookeeper comme centre d'enregistrement.

déclaration

Le code fourni dans l'article est uniquement à titre de référence et est destiné à aider les développeurs qui manquent de connaissances de base à mieux comprendre les concepts d'enregistrement et de découverte de services. Notez que ces codes ne sont pas destinés à être utilisés dans des applications réelles .

Pré-connaissance

Inscription et découverte du service

Dans une architecture SOA ou microservice, en raison de l'existence d'un grand nombre de services et d'éventuels appels mutuels, afin de gérer ces services plus efficacement, il est généralement nécessaire d'introduire un lieu unifié, à savoir le centre d'enregistrement, pour les gérer de manière centralisée, et le centre d'enregistrement est le plus basique. Sa fonction est l'enregistrement/découverte du service.

  • Enregistrement du service : enregistrez les métadonnées de l'instance de service (telles que l'adresse IP, le numéro de port, l'état de santé, etc.) auprès du centre d'enregistrement, afin que d'autres services ou clients puissent découvrir et utiliser le service.
  • Découverte de services : Lorsqu'un service doit appeler d'autres services, il n'est pas possible d'utiliser une configuration statique. À ce stade, vous pouvez accéder au registre pour obtenir les instances de service disponibles et les appeler.

Gardien de zoo

Zookeeper est un service de coordination distribué traditionnel. Il est davantage utilisé comme coordinateur, comme la coordination de la gestion des clusters Hadoop et la coordination de l'élection du leader de Kafka.

Pourquoi certains composants l’utilisent-ils comme registre ? Je pense qu'il y a plusieurs raisons :

  1. Zookeeper a une cohérence et une fiabilité plus fortes dans un système distribué, ce qui peut garantir la cohérence des informations d'enregistrement de chaque service.
  2. Zookeeper utilise la mémoire pour stocker les données et offre des performances de lecture et d'écriture élevées. Ceci est essentiel pour le registre, car il doit répondre rapidement aux demandes des clients.
  3. Le mécanisme Watcher de Zookeeper permet aux clients de surveiller les modifications dans les nœuds spécifiés. Lorsqu'un nœud (registre) change, Zookeeper peut avertir d'autres services pour obtenir des mises à jour en temps réel.

principe de fonctionnement

Prenez la figure suivante comme exemple pour voir comment Dubbo utilise Zookeeper pour réaliser l'enregistrement/la découverte de services.

insérer la description de l'image ici

  1. Le fournisseur de services /dubbo/com.foo.BarService/providersécrit sa propre adresse URL dans l'annuaire.
  2. Le consommateur du service s'abonne /dubbo/com.foo.BarService/providersà l'adresse URL du fournisseur sous l'annuaire. Et /dubbo/com.foo.BarService/consumersécrivez votre propre adresse URL dans le répertoire.

Le répertoire ici est la structure de données de Zookeeper. Le principe est très simple. Essentiellement, les fournisseurs de services et les consommateurs lisent et écrivent des données sur Zookeeper conformément à l'accord, et en même temps utilisent son mécanisme Watcher, ses nœuds temporaires et sa fiabilité pour efficacement mettre en œuvre les fonctions suivantes :

  • Lorsque le service du fournisseur subit un temps d'arrêt anormal tel qu'une panne de courant, le centre d'enregistrement peut automatiquement supprimer les informations du fournisseur.
  • Lorsque le centre d'inscription redémarre, il peut restaurer automatiquement les données d'inscription et les demandes d'abonnement.

Processus de mise en œuvre

centre d'inscription

Ensuite, implémentez un centre d'enregistrement qui inclut uniquement l'enregistrement/la découverte de services via l'API Java de Zookeeper. Le code est le suivant :

public class RegistrationCenter {
    
    

    // 连接信息
    private String connectString = "192.168.10.11:2181,192.168.10.11:2182,192.168.10.11:2183";

    // 超时时间
    private int sessionTimeOut = 30000;

    private final String ROOT_PATH = "/servers";

    private ZooKeeper client;

    public RegistrationCenter() {
    
    
        this(null);
    }

    public RegistrationCenter(Consumer<List<String>> consumer) {
    
    
        try {
    
    
            getConnection(null == consumer ? null : watchedEvent -> {
    
    
                //监听服务器地址的上下线
                if (watchedEvent.getType() == Watcher.Event.EventType.NodeChildrenChanged) {
    
    
                    try {
    
    
                        consumer.accept(subServers());
                    } catch (Exception e) {
    
    
                        e.printStackTrace();
                    }
                }
            });
            Stat stat = client.exists(ROOT_PATH, false);
            if (stat == null) {
    
    
                //创建根节点
                client.create(ROOT_PATH, ROOT_PATH.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

    /**
     * @param serverName 将服务器注册到zk集群时,所需的服务名称
     * @param metadata   服务元数据
     * @throws Exception
     */
    public void doRegister(String serverName, Metadata metadata) throws Exception {
    
    


        /**
         * ZooDefs.Ids.OPEN_ACL_UNSAFE: 此权限表示允许所有人访问该节点(服务器)
         * CreateMode.EPHEMERAL_SEQUENTIAL: 由于服务器是动态上下线的,上线后存在,下线后不存在,所以是临时节点
         * 而服务器一般都是有序号的,所以是临时、有序的节点.
         */
        String node = client.create(ROOT_PATH + "/" + serverName, metadata.toString().getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);

        System.out.println(serverName + " 已经上线");
    }


    /**
     * 发现/订阅服务
     */
    public List<String> subServers() throws InterruptedException, KeeperException {
    
    
        List<String> zkChildren = client.getChildren(ROOT_PATH, true);
        List<String> servers = new ArrayList<>();
        zkChildren.forEach(node -> {
    
    
            //拼接服务完整信息
            try {
    
    
                byte[] data = client.getData(ROOT_PATH + "/" + node, false, null);
                servers.add(new String(data));
            } catch (Exception e) {
    
    
                e.printStackTrace();
            }
        });
        return servers;
    }

    private void getConnection(Watcher watcher) throws IOException {
    
    
        this.client = new ZooKeeper(connectString, sessionTimeOut, watcher);
    }

    /**
     * 服务元数据
     */
    public static class Metadata {
    
    
        public Metadata() {
    
    
        }

        public Metadata(String ip, int port) {
    
    
            this.ip = ip;
            this.port = port;
        }

        private String ip;

        private int port;

        public String getIp() {
    
    
            return ip;
        }

        public void setIp(String ip) {
    
    
            this.ip = ip;
        }

        public int getPort() {
    
    
            return port;
        }

        public void setPort(int port) {
    
    
            this.port = port;
        }

        @Override
        public String toString() {
    
    
            return "{" + "ip='" + ip + '\'' + ", port=" + port + '}';
        }
    }
}

Il existe deux méthodes principales dans cette classe :doRegister() , subServers()l'enregistrement du service et l'abonnement.

  • doRegister()Il s'agit principalement de créer un nœud de données temporaire dans Zookeeper. L'avantage du nœud temporaire est que le nœud sera automatiquement supprimé lorsque le service est arrêté anormalement, comme une panne de courant.
  • subServers()Il va à Zookeeper pour lire les informations de tous les fournisseurs de services et surveille l'état des nœuds. Lorsque des événements tels que la création, la suppression et la mise à jour de nœuds se produisent, les informations des fournisseurs de services sont réacquises, afin que les données puissent être mises à jour dans temps réel.

Jusqu'à présent, un simple centre d'enregistrement a été réalisé. Bien entendu, si un centre d'enregistrement mature doit être mis en œuvre, des fonctions telles que l'équilibrage de charge, la haute disponibilité et la tolérance aux pannes, la gouvernance des services et le contrôle du routage doivent également être prises en compte, ce qui ne sera pas le cas. être développé ici.

enregistrement des services

Lorsqu'il existe un centre d'inscription, le prestataire peut appeler doRegister() pour s'inscrire, le code est le suivant :

public class ProviderServer {
    
    
    public static void main(String[] args) throws Exception {
    
    
        RegistrationCenter registrationCenter = new RegistrationCenter();
        registrationCenter.doRegister("provider", new RegistrationCenter.Metadata("127.0.0.1", 8080));
        Thread.sleep(Long.MAX_VALUE);
    }
}

découverte de services

De même, les consommateurs de services peuvent appeler pour subServers()découvrir les fournisseurs de services, et les consommateurs seront informés en cas de changement de fournisseur de services. le code s'affiche comme ci-dessous :

public class ConsumerServer {
    
    
    public static void main(String[] args) throws Exception {
    
    
        RegistrationCenter registrationCenter = new RegistrationCenter(newServers -> {
    
    
            System.out.println("服务更新了..."+newServers);
        });
        List<String> servers = registrationCenter.subServers();
        System.out.println(servers);
        Thread.sleep(Long.MAX_VALUE);
    }
}

Résumer

Les fonctions d'enregistrement de services et de découverte de services sont conçues pour résoudre les problèmes de gestion des services et de communication dans les systèmes distribués. Après un développement et une amélioration continus de fonctions telles que l'équilibrage de charge, la surveillance de l'état, la gouvernance des services et le contrôle du routage, ils deviennent un centre d'enregistrement. Le registre de services et la découverte de services contribuent à assurer l'élasticité et l'évolutivité du système, car de nouvelles instances de service peuvent être ajoutées dynamiquement au système sans configuration manuelle ni modification du code existant.

Je suppose que tu aimes

Origine blog.csdn.net/qq_28314431/article/details/132581610
conseillé
Classement