Red de conocimiento informático - Material del sitio web - Introducción e instalación de la biblioteca de red de código abierto de alto rendimiento basada en eventos libevent

Introducción e instalación de la biblioteca de red de código abierto de alto rendimiento basada en eventos libevent

Libevent es una biblioteca de red de código abierto, liviana, de alto rendimiento y basada en eventos que admite múltiples plataformas y encapsula la tecnología de reutilización de E / S para múltiples plataformas. Cuando compilamos el código de la biblioteca, el script de compilación correspondiente. El código se compilará de acuerdo con el mecanismo de manejo de eventos admitido por el sistema operativo para mantener la coherencia de la interfaz libevent.

En el servidor actual, el problema principal es si puede manejar la gran cantidad de conexiones. A través de la biblioteca de red libevent, podemos llamar a su API para resolver este problema. Primero, revisemos las soluciones tradicionales a este problema.

Problema: Cómo manejar múltiples conexiones de clientes

Solución 1: Tecnología de multiplexación de E/S

Estas son E/S sincrónicas, es decir, cuando la lectura y los eventos de escritura están listos, deben ser responsables de leer y escribir ellos mismos, y este proceso de lectura y escritura está bloqueado. Sin embargo, la E/S asincrónica no necesita ser responsable de la lectura y escritura por sí misma. el programa responsable del proceso de lectura y escritura.

Solución 2: subprocesos múltiples o multiprocesamiento

La tecnología de subprocesos y multiprocesamiento también puede manejar conexiones de datos altamente concurrentes porque se puede generar una gran cantidad de procesos y subprocesos en el servidor y manejar nuestras conexiones que necesitan ser monitoreadas. Sin embargo, estos dos métodos también tienen grandes limitaciones. Por ejemplo, el modelo multiproceso no es adecuado para una gran cantidad de conexiones cortas, porque la creación y el cierre de procesos consumen mucho rendimiento del sistema. comunicación del proceso, que depende del rendimiento de la CPU. No aplicable cuando es insuficiente. La tecnología de subprocesos múltiples tampoco es adecuada para manejar conexiones largas, porque cuando creamos un proceso, Linux consumirá 8G de espacio de pila. Si cada una de nuestras conexiones no se puede abrir, una gran cantidad de conexiones serán seguidas por conexiones largas. lo que resulta en una gran cantidad de conexiones. El resultado es un gran consumo de memoria.

Solución 3: los dos métodos compuestos de uso común anteriores

Los dos métodos anteriores tienen sus propias ventajas y desventajas, por lo que podemos combinar los métodos anteriores, que también es la solución actual cuando lidiar con alta concurrencia. Utilice más métodos. Multiproceso + multiplexación de E/S o multiproceso + multiplexación de E/S. En implementación específica, se puede dividir de muchas maneras. Por ejemplo, en la tecnología de multiplexación de E/S + subprocesos múltiples, utilizamos un subproceso principal que es responsable de escuchar un puerto y aceptar si ocurre un evento de lectura o escritura en el descriptor. Si es así, el evento se asigna a Otro trabajo. Se completan los procesos, que también es la idea del grupo de procesos.

Habiendo introducido formas de lidiar con la alta concurrencia, ahora es el momento de presentar una de las características principales de libevent.

De manera similar, libevent también utiliza los métodos select, poll y epoll proporcionados por el sistema para realizar la multiplexación de E/S, pero para diferentes implementaciones de multiplexación de E/S en múltiples plataformas, libevent se ha reempaquetado para proporcionar una API unificada. .

Lo mismo ocurre con Libevent. Registrará eventos y funciones de devolución de llamada con el marco de Libevent; cuando ocurran estos eventos, Libevent llamará a estas funciones de devolución de llamada para manejar los eventos correspondientes.

lbevent admite tres tipos de eventos: E/S de red, temporizadores y señales. La estructura de datos del temporizador utiliza Min Heap para mayor eficiencia. La estructura de datos para señales y E/S de red utiliza una lista doblemente enlazada (TAILQ).

Más material de texto tutorial en vídeo sobre el kernel de Linux con acceso gratuito a mensajes privados en segundo plano del kernel.

La instalación de libevent es muy simple. Cloné el código fuente directamente desde github, luego lo compilé e instalé.

El comando específico es el siguiente (suponiendo que haya instalado git):

La versión actualmente disponible de libevent es libevent2, que agrega soporte para subprocesos múltiples y realiza algunos cambios menores en el Funciones API.

Si desea obtener más información sobre el uso de la API, haga clic aquí.

A continuación, escriba un servidor de sala de chat basado en libevent2.

Idea: primero crear un socket, luego crear un evento para escuchar este puerto, poner en cola a los usuarios solicitantes y escuchar todos los eventos del usuario, cuando un usuario habla y generar un evento de lectura, enviando el discurso del usuario a otros usuarios en la cola.

Análisis del programa

Encabezado de la función Libevent para incluir:

Cree una estructura de cliente que acepte conexiones y luego almacene datos:

Primero, Eche un vistazo al proceso de procesamiento de la función principal:

Primero, esta función inicializa una cola de usuario tailq, luego crea un socket y envía el socket a otros usuarios en la cola. Luego cree un socket y configúrelo en modo sin bloqueo. Luego registre un evento para la colección global de eventos de evbase, el origen del evento es listening_fd, la función de devolución de llamada es on_accept, el evento ocurre en forma de EV_READ, el indicador EV_PESIST indica que el evento siempre existe y luego el ciclo de escaneo de eventos event_base _dispatch (evbase) está abierto.

Luego verifique la implementación de la función de devolución de llamada on_accpet:

La función de esta función de devolución de llamada es obvia: aceptar la solicitud de un cliente, solicitar la información del cliente y completar Ingrese el contenido requerido, es importante tener en cuenta que debe registrar un cliente de eventos bufferevent->buf_ev en la biblioteca de eventos del grupo de eventos anterior y registrar las funciones de devolución de llamada buffered_on_read y buffered_on_error. Estas tres funciones son para lectura o. errores cuando se acepta la conexión. Función ejecutada después del evento. A continuación, la estructura del cliente del usuario se coloca en la cola de usuarios tailq.

La función de ejecución después del búfer del usuario es legible:

La función de la función de ejecución es obvia: leer los datos del búfer del administrador libevent, almacenarlos en la matriz de datos local, y luego recuperar los clientes en la cola. Si no es el cliente el que envía los datos, los datos se escribirán en el búfer del cliente y se enviarán al usuario. Tenga en cuenta que debe leer los datos en el búfer repetidamente para evitar una lectura sin una lectura limpia, hasta que los datos no se puedan leer.

La función de manejo de errores del búfer es casi la misma que la función anterior. Esta función finaliza guardando la estructura del cliente cuando ocurre un error.

Recuerde cambiar la ubicación de la carpeta Libevent en el Makefile al compilar

Idea de diseño: el llamado servidor echo es enviar los datos del cliente nuevamente, que se refiere principalmente a Se implementa la IO pura de libevent. La implementación es similar a la anterior, o incluso más sencilla.

El programa es similar al servidor de chat anterior, excepto que en la función de evento legible en el búfer, los datos del usuario no se envían a otros usuarios, sino directamente al propio usuario.

Idea: El método anterior utiliza una función libevent simple para implementar el servicio, pero aquí, suponiendo que estamos tratando con un número menor de clientes, podemos implementar el servicio al usuario asignando un hilo para cada conexión. Servicios prestados. Se trata de un servicio individualizado, sencillo y eficaz, incluso si la lógica empresarial está bloqueada.

Análisis del programa

Primero defina algunas estructuras de datos. La estructura de datos del Trabajador define un Trabajador, que contiene un hilo de Trabajador y un indicador de finalización. Es necesario obtener la cola de trabajo y establecer un puntero de lista vinculada. La estructura de datos del trabajo define los métodos y objetos de operación de un trabajo, que se devuelven al programa y en realidad hacen referencia a eventos. La estructura de datos de la cola de trabajo se refiere al trabajador actual en la cola de trabajo, así como a los trabajos pendientes en la cola de trabajo, así como a los mutex y las variables de condición (porque varios procesos de trabajo necesitan acceder a estos recursos).

El proceso específico consiste en utilizar el hilo principal para escuchar un socket y aceptar la conexión aceptada por el socket, luego crear una estructura de datos del cliente para guardar la información de la conexión y registrar un búfer en esta estructura del cliente. evento, regístrelo en el cliente->evbase (se llama a evbase después de que el cliente registra un evento que aún no se ha ciclado en el conjunto de eventos).

Luego, cuando el hilo principal escucha el evento de almacenamiento en búfer del cliente, el hilo principal envolverá la estructura del cliente y el método de trabajo que se ejecutará en una estructura de trabajo, luego arrojará el trabajo a la cola de trabajo y notificará. el trabajador. Después de eso, se activa el hilo abierto de cada trabajador y estos toman frenéticamente el trabajo a realizar de la cola de trabajo. Una vez que un trabajador obtiene el trabajo, puede desmontarlo y operar de acuerdo con la descripción del trabajo (función_trabajo). Objeto de trabajo (cliente). Aquí, hay un bucle cliente->evbase en la descripción del trabajo, por lo que este hilo siempre monitoreará el estado de la conexión. Si hay datos, se llamará a esta función de devolución de llamada para su procesamiento. Al mismo tiempo, el hilo está bloqueado aquí y es responsable de esta conexión.

Las estructuras y funciones necesarias para construir la cola de trabajos son:

La función on_accept del hilo principal es:

El asistente de trabajos en el trabajo es:

Idea de diseño: suponiendo que tenemos una gran cantidad de usuarios, alta concurrencia y conexiones largas, usemos multiplexación de E/S y grupos de subprocesos para implementarlo, y usemos un subproceso de control. La multiplexación de E/S es responsable de escuchar y distribuir eventos, y un conjunto de grupos de subprocesos es responsable de procesar eventos, de modo que la lógica de control y la lógica empresarial se puedan separar de manera flexible. Consulte la explicación a continuación.

Análisis del programa

El proceso específico es similar al anterior. Utilice el hilo principal para escuchar el socket, aceptar la conexión recibida por el socket y crear una estructura de datos del cliente. guarde la información de conexión y registre un evento buffervent en esta estructura de cliente, pero aquí el evento se registra en Accept_evbase y el hilo principal todavía se usa para escuchar.

Cuando ocurre un evento después de escuchar, el cliente y el método para operar el cliente se empaquetarán en un trabajo y se colocarán en la cola de trabajos mencionada anteriormente para que el proceso de trabajo los complete. La diferencia entre este y el método anterior es que el método anterior registra el evento de almacenamiento en búfer en evbase en el cliente y escucha a través del hilo de trabajo, mientras que este método escucha a través del hilo principal y el hilo de trabajo es responsable de procesar los eventos generados por la escucha.

La diferencia radica en las dos funciones de la función on_accept:

En buffered_on_read, se envía el trabajo.

En la guía de trabajo server_job_function puedes hacer lo que quieras en tu trabajo en función del procesamiento de la información enviada a la base de datos, devoluciones http, etc.