Registro de servicios y descubrimiento de servicios basados en Zookeeper

prefacio

Ya sea que utilice SOA o arquitectura de microservicio, debe utilizar componentes de registro y descubrimiento de servicios. Cuando entré en contacto por primera vez con Dubbo, siempre estaba confundido acerca del registro/descubrimiento de servicios y el papel de Zookeeper. Ahora parece que mi comprensión de los sistemas distribuidos no es lo suficientemente profunda y los principios de funcionamiento de Dubbo y Zookeeper no son lo suficientemente claros. .

Este artículo implementará funciones de registro y descubrimiento de servicios basadas en Zookeeper. Si tiene la misma confusión que yo, espero que pueda usar este artículo para comprender cómo otros componentes usan Zookeeper como centro de registro.

declaración

El código proporcionado en el artículo es solo de referencia y está destinado a ayudar a los desarrolladores que carecen de conocimientos básicos a comprender mejor los conceptos de registro y descubrimiento de servicios. Tenga en cuenta que estos códigos no están pensados ​​para su uso en aplicaciones reales .

Conocimiento previo

Registro y descubrimiento de servicios

En SOA o arquitectura de microservicios, debido a la existencia de una gran cantidad de servicios y posibles llamadas mutuas, para administrar estos servicios de manera más efectiva, generalmente necesitamos introducir un lugar unificado, es decir, el centro de registro, para administrarlos de manera centralizada, y el centro de registro es el más básico. Su función es el registro/descubrimiento de servicios.

  • Registro de servicio : registre los metadatos de la instancia de servicio (como la dirección IP, el número de puerto, el estado de salud, etc.) en el centro de registro, para que otros servicios o clientes puedan descubrir y utilizar el servicio.
  • Descubrimiento de servicios : cuando un servicio necesita llamar a otros servicios, no es factible utilizar la configuración estática. En este momento, puede ir al registro para obtener las instancias de servicio disponibles y llamarlas.

cuidador del zoológico

Zookeeper es un servicio de coordinación distribuida tradicional, que se utiliza más como coordinador, como coordinar la gestión de clústeres de Hadoop y coordinar la elección del líder de Kafka.

¿Por qué algunos componentes lo utilizan como registro? Creo que hay varias razones:

  1. Zookeeper tiene mayor consistencia y confiabilidad en un sistema distribuido, lo que puede garantizar que la información de registro de cada servicio sea consistente.
  2. Zookeeper utiliza memoria para almacenar datos y tiene un alto rendimiento de lectura y escritura. Esto es fundamental para el registro, ya que debe responder rápidamente a las solicitudes de los clientes.
  3. El mecanismo Watcher de Zookeeper permite a los clientes monitorear cambios en nodos específicos. Cuando cambia un nodo (registro), Zookeeper puede notificar a otros servicios para lograr actualizaciones en tiempo real.

principio de funcionamiento

Tome la siguiente figura como ejemplo para ver cómo Dubbo usa Zookeeper para realizar el registro/descubrimiento de servicios.

inserte la descripción de la imagen aquí

  1. El proveedor de servicios /dubbo/com.foo.BarService/providersescribe su propia dirección URL en el directorio.
  2. El consumidor del servicio se suscribe /dubbo/com.foo.BarService/providersa la dirección URL del proveedor en el directorio. Y /dubbo/com.foo.BarService/consumersescriba su propia dirección URL en el directorio.

El directorio aquí es la estructura de datos de Zookeeper. El principio es muy simple: en esencia, los proveedores de servicios y los consumidores leen y escriben datos en Zookeeper de acuerdo con el acuerdo y, al mismo tiempo, utilizan su mecanismo Watcher, nodos temporales y confiabilidad para hacerlo de manera eficiente. implementar las siguientes funciones:

  • Cuando el servicio del proveedor experimenta un tiempo de inactividad anormal, como un corte de energía, el centro de registro puede eliminar automáticamente la información del proveedor.
  • Cuando el centro de registro se reinicia, puede restaurar automáticamente los datos de registro y las solicitudes de suscripción.

Proceso de implementación

centro de registro

A continuación, implemente un centro de registro que solo incluya registro/descubrimiento de servicios a través de la API Java de Zookeeper, el código es el siguiente:

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 + '}';
        }
    }
}

Hay dos métodos principales en esta clase: doRegister()registro subServers()de servicio y suscripción.

  • doRegister()Es principalmente para crear datos de nodo temporal en Zookeeper. La ventaja del nodo temporal es que el nodo se eliminará automáticamente cuando el servicio se cierre de forma anormal, como por ejemplo un corte de energía.
  • subServers()Va a Zookeeper para leer la información de todos los proveedores de servicios y monitorea el estado de los nodos. Cuando ocurren eventos como la creación, eliminación y actualización de nodos, se vuelve a adquirir la información de los proveedores de servicios para que los datos puedan actualizarse en tiempo real.

Hasta ahora, se ha completado un centro de registro simple. Por supuesto, si se va a implementar un centro de registro maduro, también se deben considerar funciones como equilibrio de carga, alta disponibilidad y tolerancia a fallas, gobernanza de servicios y control de enrutamiento, que no ampliarse aquí.

registro de servicio

Cuando hay un centro de registro, el proveedor de servicios puede llamar doRegister() para registrarse, el código es el siguiente:

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);
    }
}

descubrimiento de servicios

De manera similar, los consumidores de servicios pueden llamar para subServers()descubrir proveedores de servicios y se les notificará cuando los proveedores de servicios cambien. El código se muestra a continuación:

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);
    }
}

Resumir

Las funciones de registro de servicios y descubrimiento de servicios están diseñadas para resolver problemas de comunicación y gestión de servicios en sistemas distribuidos. Después del desarrollo y mejora continuos de funciones como equilibrio de carga, monitoreo de estado, gobernanza de servicios y control de enrutamiento, se convierten en un centro de registro. El registro de servicios y el descubrimiento de servicios ayudan a lograr la elasticidad y escalabilidad del sistema, porque se pueden agregar dinámicamente nuevas instancias de servicios al sistema sin configuración manual ni modificación del código existente.

Supongo que te gusta

Origin blog.csdn.net/qq_28314431/article/details/132581610
Recomendado
Clasificación