Explorando Message Queue Server - Cómo funciona RabbitMQ Message Queue Server

Explorando Message Queue Server - Cómo funciona RabbitMQ Message Queue Server

 

1. Historia

RabbitMQ es una implementación de código abierto de AMQP (Advanced Message Queue) desarrollada por erlang. El surgimiento de AMQP es en realidad una respuesta a las necesidades del público en general. Aunque existen muchos estándares abiertos en el mundo de la comunicación de mensajes sincrónicos (como IIOP de COBAR o SOAP, etc.), no es el caso en el procesamiento de mensajes asincrónicos, solo las grandes empresas Existen algunas implementaciones comerciales (como MSMQ de Microsoft, Websphere MQ de IBM, etc.) Por lo tanto, en junio de 2006, Cisco, Redhat, iMatix, etc. formularon conjuntamente el estándar abierto para AMQP.

RabbitMQ es desarrollado por RabbitMQ Technologies Ltd y proporciona soporte comercial. La compañía fue adquirida por SpringSource (una división de VMWare) en abril de 2010. Se incorporó a Pivotal en mayo de 2013. De hecho, VMWare, Pivotal y EMC son esencialmente una compañía. La diferencia es que VMWare es una subsidiaria listada independiente, mientras que Pivotal integra ciertos recursos de EMC y actualmente no está listada.

El sitio web oficial de RabbitMQ es http://www.rabbitmq.com

2. Escenarios de aplicación.

Más cerca de casa. ¿Qué problema resuelve RabbitMQ o AMQP o cuál es su escenario de aplicación?

Para un sistema de software grande, tendrá muchos componentes o módulos o subsistemas o (subsistema o Componente o submódulo). Entonces, ¿cómo se comunican estos módulos? Esto es muy diferente del IPC tradicional. Muchos IPC tradicionales están en un solo sistema, y ​​los módulos están altamente acoplados y no son adecuados para la escalabilidad. Si se usan sockets, se pueden implementar diferentes módulos en diferentes máquinas, pero aún quedan muchos problemas por resolver. Por ejemplo:

1) ¿Cómo mantiene esta conexión el remitente y el receptor de la información? Si se interrumpe la conexión de una de las partes, ¿cómo se perderán los datos durante este período?

2) ¿Cómo reducir el acoplamiento entre el emisor y el receptor?

3) ¿Cómo dejar que el receptor con alta prioridad reciba los datos primero?

4) ¿Cómo lograr el equilibrio de carga? ¿Equilibrar efectivamente la carga del receptor?

5) ¿Cómo enviar efectivamente los datos a los destinatarios relevantes? En otras palabras, suscriba el receptor a diferentes datos, cómo hacer un filtro efectivo.

6) ¿Cómo se puede ampliar e incluso enviar este módulo de comunicación al clúster?

7) ¿Cómo asegurar que el receptor reciba datos completos y correctos?

El protocolo AMDQ resuelve los problemas anteriores y RabbitMQ implementa AMQP.

3. Arquitectura del sistema

Explorando Message Queue Server - Cómo funciona RabbitMQ Message Queue Server

 

imagen

Servidor RabbitMQ : también llamado servidor de intermediario, no es un camión que transporta alimentos, sino un servicio de transmisión. La palabra original es RabbitMQ, no es un camión de comida, es un servicio de entrega, su función es mantener una ruta del productor al consumidor para garantizar que los datos puedan transmitirse de la manera especificada. Pero esta garantía no es 100% garantizada, pero es suficiente para aplicaciones ordinarias. Por supuesto, para sistemas comerciales, puede hacer otra capa de protección de consistencia de datos, puede garantizar completamente la consistencia del sistema.

Cliente P : también llamado Productor, el remitente de los datos. crear mensajes y publicarlos (enviarlos) a un servidor de intermediario (RabbitMQ). Un mensaje tiene dos partes: carga útil (carga útil) y etiqueta (etiqueta). Como su nombre lo indica, la carga útil son los datos transmitidos. La etiqueta es el nombre del intercambio o una etiqueta, que describe la carga útil, y RabbitMQ también utiliza esta etiqueta para decidir a qué consumidor enviar este mensaje. AMQP solo describe la etiqueta, y RabbitMQ determina cómo usar la etiqueta.

Cliente C : también llamado consumidor, el receptor de los datos. Los consumidores se conectan a un servidor de intermediario (RabbitMQ) y se suscriben a una cola. Compare la cola con un buzón con un nombre. Cuando un mensaje llega a un buzón, RabbitMQ lo envía a uno de sus suscriptores, el consumidor. Por supuesto, el mismo mensaje puede enviarse a muchos consumidores. En este mensaje, solo se han eliminado la carga útil y la etiqueta. Para el consumidor, no sabe quién envió esta información. Es que el protocolo en sí mismo no lo admite. Pero, por supuesto, es otra cuestión si la carga útil enviada por el Productor contiene la información del Productor.

Para la transmisión correcta de un dato del Productor al Consumidor, hay tres conceptos que deben aclararse: intercambios, colas y enlaces.

  • Los intercambios son donde los productores publican sus mensajes.
  • Las colas son donde los mensajes terminan y son recibidos por los consumidores.
  • Los enlaces son cómo se enrutan los mensajes del intercambio a colas particulares.

Hay varios conceptos que no están marcados en la figura anterior, es decir, Conexión (conexión), Canal (canal, canal).

  • Conexión: es una conexión TCP. Tanto el productor como el consumidor están conectados al servidor RabbitMQ a través de TCP. Más tarde podemos ver que el comienzo del programa es establecer esta conexión TCP.
  • Canales: conexión virtual. Se establece en la conexión TCP mencionada anteriormente. El flujo de datos se lleva a cabo en el canal. En otras palabras, la situación general es que el programa comienza a establecer una conexión TCP, y el segundo paso es establecer este canal.

Entonces, ¿por qué usar Channel en lugar de la conexión TCP directamente?

Para el sistema operativo, el establecimiento y cierre de conexiones TCP tiene un precio. El establecimiento y cierre frecuente de conexiones TCP tiene un gran impacto en el rendimiento del sistema, y ​​la cantidad de conexiones TCP también es limitada, lo que también limita la capacidad del sistema para manejar una alta concurrencia. Sin embargo, establecer un canal en una conexión TCP no tiene ese costo. Para Productor o Consumidor, se pueden usar múltiples canales para Publicar o Recibir simultáneamente. Los experimentos han demostrado que 1s de datos pueden publicar paquetes de 10K. Por supuesto, para diferentes entornos de hardware, estos datos deben ser diferentes para diferentes tamaños de paquetes, pero solo quiero explicar que para el consumidor o productor ordinario, esto es suficiente. Si no es suficiente, debe considerar cómo refinar su diseño.

  • Broker: En pocas palabras, es la entidad del servidor de la cola de mensajes.
  • Intercambio: Intercambio de mensajes, que especifica las reglas por las cuales los mensajes se enrutan a qué cola.
  • Cola: portador de la cola de mensajes, cada mensaje se colocará en una o más colas.
  • Enlace: Enlace, su función es vincular el intercambio y la cola de acuerdo con las reglas de enrutamiento.
  • Clave de enrutamiento: clave de enrutamiento, el intercambio entrega mensajes basados ​​en esta clave.
  • vhost: un host virtual. Se pueden configurar múltiples vhosts en un intermediario para separar los permisos de diferentes usuarios.
  • productor: Un productor de mensajes es un programa que entrega mensajes.
  • consumidor: un consumidor de mensajes es un programa que recibe mensajes.
  • canal: canal de mensajes En cada conexión del cliente, se pueden establecer múltiples canales y cada canal representa una tarea de sesión.

Exchange, Queue y RoutingKey determinan la única línea de Exchange a Queue.

4. Conceptos básicos

ConnectionFactory 、 Connection 、 Channel

ConnectionFactory, Connection y Channel son los objetos más básicos en la API proporcionada por RabbitMQ. Connection es el enlace de socket de RabbitMQ, que encapsula la lógica del protocolo de socket. ConnectionFactory es la fábrica de fabricación de Connection.

Channel es la interfaz más importante con la que tratamos RabbitMQ. La mayoría de nuestras operaciones comerciales se completan en la interfaz de Channel, incluida la definición de Queue, la definición de Exchange, la vinculación de cola e intercambio y la publicación de mensajes.

Cola

Queue (Queue) es un objeto interno de RabbitMQ, utilizado para almacenar mensajes, representado por la siguiente figura.

cola

Explorando Message Queue Server - Cómo funciona RabbitMQ Message Queue Server

 

imagen

Los mensajes en RabbitMQ solo se pueden almacenar en la Cola, el productor (P en la figura a continuación) produce el mensaje y finalmente lo entrega a la Cola, y el consumidor (C en la figura a continuación) puede obtener el mensaje de la Cola y consumirlo.

Explorando Message Queue Server - Cómo funciona RabbitMQ Message Queue Server

 

imagen

Múltiples consumidores pueden suscribirse a la misma Cola. En este momento, los mensajes en la Cola se distribuirán uniformemente a múltiples consumidores para su procesamiento, en lugar de que cada consumidor reciba todos los mensajes y el procesamiento.

Explorando Message Queue Server - Cómo funciona RabbitMQ Message Queue Server

 

imagen

Mensaje de acuse de recibo

En aplicaciones prácticas, puede suceder que el consumidor reciba el mensaje en la Cola, pero se cuelga (o tiene otros accidentes) antes de que se complete el procesamiento. En este caso, el mensaje puede perderse. Para evitar esta situación, podemos pedir a los consumidores que envíen un recibo a RabbitMQ después de consumir el mensaje. RabbitMQ eliminará el mensaje de la Cola después de recibir el acuse de recibo del mensaje; Al detectar que la conexión RabbitMQ del consumidor está desconectada, RabbitMQ enviará el mensaje a otros consumidores (si hay varios consumidores) para su procesamiento. No hay un concepto de tiempo de espera aquí. No importa cuánto tiempo procese un consumidor un mensaje, el mensaje no se enviará a otros consumidores a menos que se desconecte su conexión RabbitMQ.

Habrá otro problema aquí: si nuestros desarrolladores se olvidan de enviar el recibo a RabbitMQ después de procesar la lógica de negocios, esto generará errores graves: se acumularán más y más mensajes en la Cola; los consumidores se reiniciarán Consuma estos mensajes repetidamente y ejecute la lógica de negocios repetidamente.

Además, el mensaje de pub no tiene reconocimiento.

Durabilidad del mensaje

Si esperamos que, incluso si se reinicia el servicio RabbitMQ, el mensaje no se perderá, podemos configurar que Cola y Mensaje sean duraderos (duraderos), lo que puede garantizar que, en la mayoría de los casos, nuestros mensajes RabbitMQ no se pierdan . Pero aún no puede resolver la ocurrencia de un pequeño evento de pérdida de probabilidad (por ejemplo, el servidor RabbitMQ ha recibido el mensaje del productor, pero el servidor RabbitMQ se apagará antes de que tenga tiempo de persistir el mensaje), si necesitamos lidiar con este pequeño evento de probabilidad Gestión, entonces tenemos que usar las transacciones. Dado que esta es solo una breve introducción a RabbitMQ, no explicaremos aquí los asuntos relacionados con RabbitMQ.

Recuento de captación previa

Anteriormente dijimos que si hay varios consumidores que se suscriben a los mensajes en la misma Cola al mismo tiempo, los mensajes en la Cola se compartirán entre varios consumidores. En este momento, si el tiempo de procesamiento de cada mensaje es diferente, puede causar que algunos consumidores estén ocupados todo el tiempo, mientras que otros terminarán rápidamente el trabajo en cuestión y estarán inactivos. Podemos configurar prefetchCount para limitar el número de mensajes que la cola envía a cada consumidor a la vez. Por ejemplo, si establecemos prefetchCount = 1, la cola envía un mensaje a cada consumidor cada vez; después de que el consumidor procesa este mensaje, la cola Enviar otro mensaje al consumidor.

Explorando Message Queue Server - Cómo funciona RabbitMQ Message Queue Server

 

imagen

Intercambiar

En la sección anterior vimos que el productor publicó el mensaje en la Cola. De hecho, este tipo de cosas nunca sucede en RabbitMQ. La situación real es que el productor envía el mensaje a Exchange (Exchange, X en la figura a continuación), y Exchange enruta el mensaje a una o más Colas (o descartes).

Explorando Message Queue Server - Cómo funciona RabbitMQ Message Queue Server

 

imagen

¿Qué lógica usa Exchange para enrutar mensajes a la cola? Esto se introducirá en la sección de enlace.

Hay cuatro tipos de Exchange en RabbitMQ. Los diferentes tipos tienen diferentes estrategias de enrutamiento, que se introducirán en la sección Tipos de Exchange.

clave de enrutamiento

Cuando un productor envía un mensaje a Exchange, generalmente especifica una clave de enrutamiento para especificar las reglas de enrutamiento del mensaje. Esta clave de enrutamiento debe usarse junto con el Tipo de intercambio y la clave de enlace para que finalmente surtan efecto.

En el caso en que el Tipo de intercambio y la clave de enlace son fijos (generalmente estos contenidos son fijos y configurados en uso normal), nuestro productor puede especificar la clave de enrutamiento para determinar dónde fluye el mensaje al enviar un mensaje a Exchange.

El límite de longitud establecido por RabbitMQ para la clave de enrutamiento es de 255 bytes.

Unión

En RabbitMQ, Exchange está asociado con la cola a través del enlace, por lo que RabbitMQ sabe cómo enrutar correctamente los mensajes a la cola especificada.

Explorando Message Queue Server - Cómo funciona RabbitMQ Message Queue Server

 

imagen

Clave de enlace

Cuando se vincula (vincula) Exchange y Queue, generalmente se especifica una clave de vinculación; cuando un consumidor envía un mensaje a Exchange, generalmente se especifica una clave de enrutamiento; cuando la clave de vinculación coincide con la clave de enrutamiento, el mensaje se enrutará A la cola correspondiente. Esto se ilustrará con ejemplos prácticos en el capítulo Tipos de intercambio.

Al vincular múltiples colas al mismo intercambio, estos enlaces permiten utilizar la misma clave de enlace.

La clave de enlace no tiene efecto en todos los casos. Depende del tipo de intercambio. Por ejemplo, el intercambio del tipo de despliegue ignorará la clave de enlace, pero enrutará el mensaje a todas las colas vinculadas al intercambio.

Tipos de intercambio

Hay cuatro tipos de tipos de intercambio comúnmente utilizados en RabbitMQ: fanout, directo, tema y encabezados (la especificación AMQP también menciona dos tipos de intercambio, que son sistema y personalizado, que no se describen aquí), que se presentan a continuación.

fanout

La regla de enrutamiento de Exchange del tipo fanout es muy simple: enrutará todos los mensajes enviados al Exchange a todas las Colas vinculadas a él.

Explorando Message Queue Server - Cómo funciona RabbitMQ Message Queue Server

 

imagen

En la figura anterior, todos los mensajes enviados por el productor (P) a Exchange (X) se enrutarán a las dos Colas en la figura, y eventualmente serán consumidos por los dos consumidores (C1 y C2).

directo

La regla de enrutamiento directo de Exchange también es muy simple, enrutará el mensaje a la cola cuya clave de enlace coincide exactamente con la clave de enrutamiento.

Explorando Message Queue Server - Cómo funciona RabbitMQ Message Queue Server

 

imagen

Tomando la configuración de la figura anterior como ejemplo, si enviamos un mensaje a Exchange con routingKey = "error", el mensaje se enrutará a Queue1 (amqp.gen-S9b ..., que es el nombre de cola generado automáticamente por RabbitMQ) y Queue2 (amqp.gen- Agl ...); si enviamos el mensaje con routingKey = "info" o routingKey = "warning", el mensaje solo se enrutará a Queue2. Si enviamos un mensaje con otra clave de enrutamiento, el mensaje no se enrutará a estas dos colas.

tema

Como se mencionó anteriormente, la regla de enrutamiento de Exchange del tipo directo coincide completamente con la clave de enlace y la clave de enrutamiento, pero este método de coincidencia estricto no puede cumplir con los requisitos comerciales reales en muchos casos. El tipo de tema Intercambio se extiende en reglas coincidentes. Es similar al tipo directo Intercambio. También enruta mensajes a la Cola que coincide con la clave de enlace y la clave de enrutamiento. Sin embargo, las reglas coincidentes aquí son algo diferentes. Concuerda:

La clave de enrutamiento es una cadena separada por un punto "." (Llamaremos a cada cadena independiente separada por un punto "." Una palabra), como "stock.usd.nyse" y "nyse". "vmw", "quick.orange.rabbit" la clave de enlace y la clave de enrutamiento también son cadenas de caracteres separadas por punto "."

Puede haber dos caracteres especiales "" y "#" en la clave de enlace, utilizados para la coincidencia difusa, donde "" se utiliza para hacer coincidir una palabra, "#" se usa para hacer coincidir varias palabras (puede ser cero)

Explorando Message Queue Server - Cómo funciona RabbitMQ Message Queue Server

 

imagen

Tomando la configuración de la figura anterior como ejemplo, el mensaje de routingKey = "quick.orange.rabbit" se enrutará a Q1 y Q2 al mismo tiempo, el mensaje de routingKey = "lazy.orange.fox" se enrutará a Q1, routingKey = "lazy.brown. El mensaje "zorro" se enrutará a Q2, el mensaje routingKey = "lazy.pink.rabbit" se enrutará a Q2 (solo se entrega a Q2 una vez, aunque este routeringKey coincide con las dos teclas de enlace de Q2); routingKey = "rápido. Los mensajes Brown.fox ", routingKey =" orange ", routingKey =" quick.orange.male.rabbit "se descartarán porque no coinciden con ningún enlaceKey.

encabezados

El tipo de intercambio de encabezados no depende de las reglas coincidentes de la clave de enrutamiento y la clave de enlace para enrutar el mensaje, pero coincide de acuerdo con el atributo de encabezado en el contenido del mensaje enviado.

Especifique un conjunto de pares clave-valor al vincular Cola e Intercambio; cuando se envía un mensaje a Exchange, RabbitMQ obtendrá los encabezados del mensaje (también en forma de un par clave-valor) y comparará si los pares clave-valor coinciden exactamente con la Cola y el Intercambio. Los pares clave-valor especificados durante el enlace de Exchange; si coinciden exactamente, el mensaje se enrutará a la Cola, de lo contrario no se enrutará a la Cola.

Este tipo de intercambio no se ha utilizado (pero también debería ser muy útil), por lo que no lo presentaré.

RPC

MQ se basa en el procesamiento de mensajes asíncronos. En el ejemplo anterior, todos los productores (P) envían mensajes a RabbitMQ sin saber si el procesamiento del consumidor (C) fue exitoso o fallido (incluso si hay un consumidor que procese este mensaje) No se)

Sin embargo, en el escenario real de la aplicación, probablemente necesitemos un procesamiento de sincronización. Debemos esperar a que el servidor termine de procesar mi mensaje antes de continuar con el siguiente procesamiento. Esto es equivalente a RPC (llamada a procedimiento remoto, llamada a procedimiento remoto).

RPC también es compatible con RabbitMQ.

Explorando Message Queue Server - Cómo funciona RabbitMQ Message Queue Server

 

imagen

El mecanismo para implementar RPC en RabbitMQ es:

  • Cuando el cliente envía una solicitud (mensaje), establezca dos valores en las propiedades del mensaje (MessageProperties, definido en las propiedades del protocolo AMQP 14, estas propiedades se enviarán junto con el mensaje) replyTo (un nombre de cola, utilizado para indicar al servidor Después de que se complete el procesamiento, el mensaje que me informa será enviado a esta Cola) y correlationId (el número de identificación de esta solicitud, el servidor debe devolver este atributo después de que se complete el procesamiento, y el cliente sabrá qué solicitud se ejecutó o ejecutó con éxito en función de esta identificación Fallido)
  • El servidor recibe el mensaje y lo procesa.
  • Después de procesar el mensaje, el servidor generará un mensaje de respuesta a la Cola especificada por replyTo y traerá el atributo correlationId
  • El cliente se ha suscrito a la cola especificada por replyTo. Después de recibir el mensaje de respuesta del servidor, analiza qué solicitud se ejecutó de acuerdo con el atributo correlationId y realiza el procesamiento comercial posterior en función del resultado de la ejecución.

5. Detalles

Use ack para confirmar la entrega correcta del Mensaje

De forma predeterminada, si un mensaje ha sido recibido correctamente por un consumidor, el mensaje se eliminará de la cola. Por supuesto, también puede enviar el mismo mensaje a muchos consumidores.

Si ningún consumidor suscribe una cola, entonces si los datos llegan para esta cola, los datos se almacenarán en caché y no se descartarán. Cuando hay un Consumidor, estos datos se enviarán a este Consumidor de inmediato, y cuando el Consumidor reciba correctamente estos datos, se eliminarán de la cola.

Entonces, ¿qué se recibe correctamente? A través de ack. Cada mensaje debe ser reconocido (reconocido, ack). Podemos mostrar el reconocimiento en el programa o reconocer automáticamente. Si hay datos que no han sido atacados, RabbitMQ Server enviará esta información al próximo consumidor.

Si la aplicación tiene errores y olvida el error, RabbitMQ Server no le enviará datos nuevamente, porque el Servidor cree que este Consumidor tiene un poder de procesamiento limitado.

Y el mecanismo de reconocimiento puede desempeñar el papel de limitar la corriente (Benefitto estrangulamiento): enviar reconocimiento después de que el Consumidor termine de procesar los datos, e incluso enviar reconocimiento después de un retraso adicional, equilibrará efectivamente la carga del Consumidor.

Por supuesto, para ejemplos prácticos, por ejemplo, podemos fusionar algunos datos, como los datos en fusionar 4s, y luego obtener los datos después de dormir 4s. Especialmente al monitorear el estado del sistema, no queremos que todo el estado se transfiera en tiempo real, pero queremos un cierto retraso. Esto puede reducir algo de IO, y el usuario final no lo sentirá.

Rechazar un mensaje

Hay dos formas, el primer Rechazo permite que RabbitMQ Server envíe el mensaje al siguiente Consumidor. El segundo es eliminar el mensaje inmediatamente de la cola.

Crear una cola

Tanto Consumer como Procuder pueden crear colas a través de queue.declare. Para un canal, el consumidor no puede declarar una cola, sino suscribirse a otras colas. Por supuesto, también puede crear una cola privada. Solo la aplicación en sí puede usar esta cola. La cola también se puede eliminar automáticamente. La cola marcada como eliminación automática se eliminará automáticamente después de la última suscripción del consumidor. Entonces, ¿qué pasa si está creando una cola existente? Entonces no habrá impacto. Cabe señalar que no hay ningún efecto, es decir, si el parámetro es diferente de la primera vez en la segunda creación, aunque la operación es exitosa, las propiedades de la cola no se modificarán.

Entonces, ¿quién debería ser responsable de crear esta cola? ¿Es consumidor o productor?

Si la cola no existe, por supuesto, el consumidor no recibirá ningún mensaje. Pero si la cola no existe, el mensaje de publicación del productor se descartará. Por lo tanto, para no perder datos, ¡tanto el consumidor como el productor intentan crear la cola! De todos modos, no habrá problemas con esta interfaz.

El manejo de la cola del equilibrio de carga es perfecto. Para múltiples consumidores, RabbitMQ utiliza un método de turnos para enviarlos a diferentes consumidores de manera equilibrada.

Intercambios

Como se puede ver en el diagrama de arquitectura, el mensaje de Procuder Publish ingresó a Exchange. Luego, a través de "claves de enrutamiento", RabbitMQ encontrará la cola en la que se debe colocar este mensaje. La cola también está vinculada por las claves de enrutamiento.

Hay tres tipos de intercambios: directo, fanout, tema. Cada uno implementa un algoritmo de enrutamiento diferente.

  • Intercambio directo: si la clave de enrutamiento coincide, el mensaje se entregará a la cola correspondiente. De hecho, cuando se crea la cola, usará automáticamente el nombre de la cola como la clave de enrutamiento para vincular el intercambio.
  • Intercambio de fanout: se transmitirá a la cola de respuesta.
  • Intercambio de temas: la coincidencia de patrones en las teclas, como ab, se puede pasar a todas las colas ab.

Anfitriones virtuales

Cada host virtual es esencialmente un servidor RabbitMQ, con su propia cola, regla de excagne y bings, etc. Esto asegura que puede usar RabbitMQ en múltiples aplicaciones diferentes.

La última documentación sobre productos secos de la tecnología Java: [acabado de los puntos de conocimiento básicos de Java] que cubre 29 tecnologías principales de Java, JVM, Redis, Nginx, Spring Boot, Spring Cloud, Kafka, programación concurrente, Tomcat, MyBatis, preguntas de la entrevista BAT, Java Video de elaboración técnica, etc. Reenviar + seguir, responder a "productos secos" por mensaje privado para obtener un método de recolección gratuito.

Después de dominar estos puntos de conocimiento, puede obtener mucha atención entre los candidatos durante la entrevista, alcanzar los 9999 puntos. Las oportunidades están reservadas para aquellos que están preparados, solo con una preparación suficiente se puede destacar entre los candidatos.

70 artículos originales publicados · Me gusta 1612 · Visita 380,000+

Supongo que te gusta

Origin blog.csdn.net/yelvgou9995/article/details/105599781
Recomendado
Clasificación