Comparta una experiencia de entrevista abierta de prueba muy desagradable

Compensar la entrevista anterior, debería ser a fines del mes pasado, puro KPI, es la peor experiencia de entrevista en reclutamiento social.

No recuerdo si el departamento comercial debería ser un dron o un vehículo no tripulado, debería ser un dron.

Debido a que fue detectado, primero pregunté si sabía sobre la prueba y si sabía sobre la prueba, y luego comencé oficialmente.

La entrevistadora era una señora mayor con el pelo despeinado, ojos que no se podían abrir y una mirada de amargura y desdén.

Relacionado con el proyecto, algunos temas específicos en profundidad

MySQL cuatro niveles de aislamiento

MySQL proporciona cuatro niveles de aislamiento, a saber:

  1. READ UNCOMMITTED (lectura no confirmada): este es el nivel de aislamiento más bajo que permite que una transacción lea datos que aún no han sido confirmados por otra transacción. Esto puede generar lecturas sucias (lecturas de datos no confirmados) y lecturas no repetibles (lecturas de los mismos datos pero valores diferentes). En MySQL, este nivel no se usa comúnmente.

  2. READ COMMITTED (lectura confirmada): este es el nivel de aislamiento predeterminado de MySQL. Permite que una transacción lea datos que otra transacción ha confirmado. Esto evita lecturas sucias, pero puede dar lugar a lecturas no repetibles (lecturas de los mismos datos pero valores diferentes) y lecturas fantasma (lecturas de nuevos datos insertados por otra transacción).

  3. LECTURA REPETIBLE (repetible read): este nivel de aislamiento garantiza que cuando los mismos datos se leen varias veces dentro de la misma transacción, el resultado es siempre el mismo. Evita las lecturas sucias y las lecturas no repetibles, pero puede generar lecturas fantasma (lectura de nuevos datos insertados por otra transacción). En MySQL, este nivel es el más utilizado.

  4. SERIALIZABLE (serializable): este es el nivel de aislamiento más alto, que evita lecturas sucias, lecturas no repetibles y lecturas fantasma al obligar a que las transacciones se ejecuten en serie. Esto significa que solo una transacción puede acceder a los datos mientras que otras tienen que esperar. Este nivel puede garantizar la integridad de los datos, pero tiene un gran impacto en el rendimiento y no se usa comúnmente en MySQL.

Di algo sobre MVCC

MVCC, es decir, control de concurrencia de múltiples versiones, es una tecnología utilizada para implementar el control de concurrencia de bases de datos.Se utiliza principalmente para resolver algunos problemas que pueden ocurrir durante las operaciones concurrentes de bases de datos, como modificación perdida, lectura no repetible, lectura fantasma, etc.

En MVCC, cada vez que se modifica la base de datos, se generará una nueva versión en lugar de sobrescribir directamente los datos originales. Cuando cada transacción lee datos, solo verá los datos de la versión anterior a la hora de inicio de la transacción y no verá las modificaciones posteriores. De esta forma, se puede lograr el aislamiento entre transacciones concurrentes, para garantizar que cada transacción pueda ver datos consistentes cuando se ejecuta.

El método de implementación de MVCC es agregar un número de versión o una marca de tiempo a cada fila de registros y un marcador de eliminación para marcar si el registro se ha eliminado. Cuando comienza una transacción, se crea una instantánea para registrar todas las versiones de datos y eliminar marcadores en la base de datos actual. Durante la ejecución de la transacción, si otras transacciones modifican o eliminan algunos datos, los datos se marcarán como "eliminados", pero el registro de la fila no se eliminará directamente. De esta forma, la transacción actual puede leer la versión anterior del registro de fila.

MVCC puede mejorar el rendimiento de simultaneidad de la base de datos, ya que varias transacciones pueden leer datos en la base de datos al mismo tiempo sin bloquearse entre sí. Sin embargo, al usar MVCC, también es necesario prestar atención, si hay demasiadas transacciones, habrá una gran cantidad de datos de versión en la base de datos, lo que aumentará el espacio de almacenamiento y el tiempo de consulta de la base de datos. Por lo tanto, es necesario seleccionar un nivel de aislamiento apropiado y un método de control de concurrencia de acuerdo con la situación real.

¿Utiliza excesivas subtablas de base de datos?¿Bajo qué circunstancias?

Por lo general, cuando la cantidad de datos en una aplicación alcanza una cierta escala, para hacer frente al acceso a datos con alta simultaneidad y gran volumen de datos, se utilizará la tecnología de subbase de datos y subtabla.

La subtabla de la subbase de datos es para dividir una base de datos grande en varias bases de datos pequeñas (subbases de datos), y cada base de datos pequeña divide la tabla de datos en varias tablas de datos pequeñas (subtablas), para realizar el almacenamiento y la consulta descentralizados. de datos

Las principales situaciones de uso de subbases de datos y subtablas incluyen:

  1. Cuello de botella en el rendimiento de la base de datos: cuando la carga de una sola base de datos alcanza el cuello de botella, para mejorar la capacidad de procesamiento simultáneo de la base de datos, los datos se pueden dividir en varias bases de datos.

  2. Limitación de la capacidad de la base de datos: cuando una sola base de datos no puede almacenar todos los datos, los datos se pueden dividir en varias bases de datos para aumentar la capacidad de almacenamiento.

  3. Zonas activas de acceso a datos: cuando una tabla de datos tiene una gran cantidad de acceso a datos, para reducir la carga en la tabla de datos, los datos de la tabla se pueden distribuir a varias tablas de datos, lo que mejora el rendimiento de las consultas.

  4. Requisitos comerciales: cuando los requisitos comerciales requieren que se completen varias bases de datos juntas, por ejemplo, los datos de usuario en varias regiones deben almacenarse en diferentes bases de datos, lo que se puede lograr mediante el uso de subbases de datos y subtablas.

Cabe señalar que, aunque la subbase de datos y la subtabla pueden mejorar el rendimiento y la escalabilidad de la base de datos, también presentan algunos desafíos, como transacciones distribuidas, consistencia de datos, migración de datos, copia de seguridad y recuperación y otros problemas. Por lo tanto, cuando se utilizan subbases de datos y subtablas, es necesario considerar cuidadosamente su impacto en el sistema y elegir estrategias y herramientas de fragmentación apropiadas para lograrlo.

Optimización MySQL

La optimización de MySQL incluye los siguientes aspectos:

  1. Optimización de la configuración de hardware: incluida la configuración y optimización de los recursos de hardware, como la CPU, la memoria y el disco, como el aumento de los núcleos de la CPU, la expansión de la memoria y el uso de discos duros de estado sólido.

  2. Optimización de la configuración de la base de datos: incluida la optimización de los parámetros de configuración de MySQL, como el tamaño de la memoria caché, el número de conexiones simultáneas, el tamaño del grupo de subprocesos, etc.

  3. Optimización de índices: los índices son un medio importante para optimizar el rendimiento de la base de datos. Puede utilizar los índices apropiados para mejorar la velocidad de consulta y reducir los tiempos de E/S del disco de consulta.

  4. Optimización de declaraciones SQL: la declaración SQL es un medio importante para operar la base de datos Al optimizar la estructura y la sintaxis de las declaraciones SQL, la cantidad de datos de consulta se puede reducir y la lógica de consulta se puede optimizar para mejorar el rendimiento de la consulta.

  5. Optimización de la tabla de particiones: la tabla de particiones es una estructura de tabla especial compatible con MySQL, que puede dividir una tabla grande en varias tablas pequeñas, lo que mejora el rendimiento de la consulta y actualización de datos.

  6. Optimización de la arquitectura de la base de datos: el diseño y la optimización de la arquitectura de la base de datos también son medios importantes para mejorar el rendimiento de la base de datos. Puede mejorar el rendimiento de las consultas y reducir la redundancia de datos optimizando el diseño de la base de datos y ajustando los modelos de datos.

Cabe señalar que los diferentes métodos de optimización se enfocan en diferentes problemas y escenarios aplicables, y deben seleccionarse y adoptarse en combinación con requisitos comerciales específicos y cuellos de botella en el rendimiento de la base de datos. Al mismo tiempo, la optimización no se realiza de una sola vez y requiere una observación y un ajuste continuos para adaptarse a las cambiantes necesidades comerciales y la escala de datos.

Penetración de caché de Redis

La penetración de caché de Redis significa que no hay datos que deban consultarse en el caché, lo que hace que todas las solicitudes se envíen a la base de datos, lo que aumenta la presión sobre la base de datos.

La penetración de caché generalmente ocurre en las siguientes situaciones:

  1. Consultar datos que no existen, como consultar datos con un ID negativo.

  2. Ataques maliciosos o accesos ilegales, como el uso de algoritmos explosivos para intentar consultar todos los ID posibles, con el fin de agotar los recursos del sistema.

Para evitar la penetración de caché, se pueden utilizar los siguientes métodos:

  1. Filtro Bloom: un filtro Bloom es una estructura de datos aleatorios eficiente en el espacio que se puede utilizar para determinar si un elemento existe en un conjunto. Las posibles claves de consulta se pueden almacenar en el filtro Bloom de antemano. Cuando llega una solicitud de consulta, primero se juzga si la clave está en el filtro Bloom. De lo contrario, se devuelve un resultado vacío directamente, de lo contrario, se consulta el caché o la base de datos. .

  2. Valor de caché vacío: puede almacenar pares clave-valor inexistentes en el caché, el tiempo de caché es corto y caducará automáticamente después de un período de tiempo. De esta forma, la próxima vez que consultes por una clave que no existe, obtendrás el valor nulo de la memoria caché, evitando consultar directamente la base de datos.

  3. Precalentamiento de datos: cuando se inicia el sistema, cargue datos de uso común en la memoria caché para reducir la presión sobre la base de datos durante la primera consulta.

  4. Limite la frecuencia de acceso: limitar la frecuencia de acceso puede prevenir eficazmente ataques maliciosos y acceso ilegal.

Cabe señalar que los métodos anteriores son solo algunos medios comunes para evitar la penetración de caché, pero no son soluciones absolutas. En aplicaciones prácticas, es necesario elegir un método apropiado según la situación específica para garantizar la seguridad y estabilidad del sistema.

avalancha de caché

La avalancha de caché significa que una gran cantidad de datos almacenados en la caché caduca en el mismo período de tiempo, lo que provoca que una gran cantidad de solicitudes caigan directamente en la base de datos back-end, lo que provoca problemas de rendimiento de la base de datos.

Las avalanchas de caché suelen ocurrir en las siguientes situaciones:

  1. El servidor de caché está inactivo o reiniciado.

  2. La configuración del tiempo de caducidad de los datos de caché no es razonable, lo que provoca que una gran cantidad de datos de caché caduquen y se vuelvan inválidos al mismo tiempo.

  3. Los datos almacenados en la memoria caché se concentran en una determinada tecla de acceso rápido. Cuando la tecla de acceso rápido caduca, una gran cantidad de solicitudes caen directamente en la base de datos de back-end.

Para evitar la avalancha de caché, se pueden utilizar varios métodos:

  1. Establezca un valor aleatorio para el tiempo de caducidad: puede agregar un valor aleatorio al tiempo de caducidad de los datos almacenados en caché, de modo que el tiempo de caducidad de los datos almacenados en caché se pueda extender, evitando que una gran cantidad de datos caduquen al mismo tiempo. .

  2. Cree un clúster: construya un servidor de caché en un clúster, comparta solicitudes a través de varios servidores de caché y reduzca el riesgo de fallas en un solo punto.

  3. Los datos del punto de acceso nunca caducan: configurar el tiempo de vencimiento de los datos del punto de acceso para que nunca caduque puede garantizar que los datos del punto de acceso sean siempre válidos y evitar problemas de avalancha de caché causados ​​por el vencimiento de los datos del punto de acceso.

  4. Limitación y reducción de corriente: para solicitudes que excedan la capacidad del sistema, se puede utilizar la limitación o reducción de corriente para proteger la estabilidad del sistema.

Cabe señalar que los métodos anteriores son solo algunos medios comunes para evitar la avalancha de caché, pero no son soluciones absolutas. En aplicaciones prácticas, es necesario elegir un método apropiado según la situación específica para garantizar la seguridad y estabilidad del sistema.

mecanismo de persistencia redis

Redis proporciona dos mecanismos de persistencia, RDB y AOF.

RDB

RDB es un método de persistencia de instantáneas de Redis, que puede guardar datos de Redis en un momento determinado en un archivo. La ventaja de la persistencia de RDB es que tiene menos impacto en Redis, porque los datos en la memoria de Redis se escriben en el disco, por lo que no tendrá un gran impacto en el rendimiento de Redis. Al mismo tiempo, el archivo RDB también es muy compacto, porque solo contiene los datos en la base de datos de Redis en un momento determinado.

Hay dos métodos de activación para la persistencia de RDB: manual y automático. La activación manual puede usar  SAVE comandos para forzar que la base de datos de Redis se escriba en el disco duro. El disparo automático se puede realizar mediante  save o  bgsave configuración. Lo primero significa que cuando se cumplen ciertas condiciones (por ejemplo, la cantidad de claves en la base de datos actual de Redis excede el número especificado, o la cantidad de claves modificadas excede el número especificado), Redis realizará la persistencia de RDB; la persistencia de RDB se realiza de forma asíncrona en segundo plano, para que no se bloquee el hilo principal de Redis.

AOF

AOF es otro método de persistencia de Redis, y su nombre completo es Append Only File, que es un archivo adjunto. A diferencia de RDB, el método de persistencia de AOF consiste en guardar el registro de operaciones de Redis en un archivo. Este archivo se puede usar para restaurar el estado de la base de datos de Redis a través de la operación de reproducción. El método de persistencia AOF tiene las siguientes ventajas:

  • Los registros operativos son más detallados, lo que reduce la posibilidad de pérdida de datos.

  • Puede garantizar que la base de datos de Redis no se dañe tanto como sea posible cuando falla inesperadamente.

En comparación con RDB, AOF consume más recursos porque necesita escribir todas las operaciones de Redis en el disco. Al mismo tiempo, el archivo AOF es relativamente grande porque contiene todos los registros de operaciones de la base de datos de Redis.

Al igual que RDB, AOF también admite dos métodos de activación: manual y automático. La activación manual puede usar  BGREWRITEAOF comandos para obligar a Redis a reescribir el archivo AOF; la activación automática se puede lograr a través de  auto-aof-rewrite-percentage una  auto-aof-rewrite-min-size configuración. Lo primero significa que cuando el tamaño del archivo AOF supera un determinado porcentaje del tamaño del archivo actual (el valor predeterminado es 100 %), Redis realizará la reescritura de AOF; lo segundo significa que cuando el tamaño del archivo AOF supere el tamaño especificado, Redis realizará la reescritura de AOF reescribiendo

Mecanismo de trabajo centinela

Sentinel es una de las soluciones de alta disponibilidad proporcionadas por Redis. Se ejecuta como un proceso independiente para monitorear el estado de salud del nodo maestro de Redis y actualiza automáticamente uno de los nodos esclavos a nodo maestro para garantizar la disponibilidad del sistema.

Centinela funciona de la siguiente manera:

  1. Los centinelas envían periódicamente comandos PING al nodo maestro para verificar el estado del nodo maestro.

  2. Si el centinela no recibe la respuesta PONG del nodo maestro varias veces consecutivas, se considera que el nodo maestro ha estado caído.

  3. Después de que el nodo maestro se cae, Sentinel seleccionará uno de todos los nodos esclavos como el nuevo nodo maestro y lo actualizará a nodo maestro.

  4. Sentinel publicará una notificación a todos los clientes de la nueva dirección del nodo principal y el número de puerto.

  5. Sentinel enviará un comando de configuración al nuevo nodo maestro, le permitirá configurar todos los nodos esclavos como sus propios nodos esclavos y actualizar la dirección del nodo maestro y el número de puerto de todos los nodos esclavos.

  6. Cuando el nodo maestro original se reinicia, se convertirá en un nuevo nodo esclavo y replicará los datos de forma síncrona de acuerdo con el nuevo nodo maestro.

Cabe señalar que Sentinel también puede fallar, por lo que en aplicaciones prácticas, Sentinel debe implementarse en diferentes servidores para mejorar la disponibilidad del sistema. Además, Sentry también admite el monitoreo mutuo entre múltiples Sentinels para mejorar la tolerancia a fallas del sistema.

partición de memoria JVM

La memoria JVM se divide en las siguientes áreas:

1. Contador de programa

El contador del programa es una pequeña área de la memoria que puede considerarse como un indicador del número de línea del código de bytes que ejecuta el subproceso actual. En una máquina virtual, cada subproceso tiene su propio contador de programa independiente para garantizar que pueda volver a la posición de ejecución correcta después del cambio de subproceso. El contador del programa es privado para subprocesos, por lo que no hay problemas de seguridad de subprocesos.

2. Pila de máquinas virtuales Java

La pila de la máquina virtual de Java, también conocida como pila de métodos de Java, se utiliza para almacenar información como la tabla de variables locales, la pila de operandos, el enlace dinámico y la salida del método de cada método durante la ejecución. Al igual que el contador del programa, la pila de la máquina virtual también es privada para subprocesos y cada subproceso tiene su propia pila de máquina virtual independiente.

3. Pila de métodos nativos

La pila de métodos nativos es similar a la pila de máquinas virtuales, excepto que la pila de métodos nativos se usa para almacenar la información del método JNI (es decir, el método implementado en lenguaje C u otros lenguajes nativos). La especificación de la máquina virtual no especifica la implementación específica de la pila de métodos nativos, pero, en términos generales, es similar a la pila de la máquina virtual.

4. Montón de Java

El montón de Java es el área de memoria más grande de la máquina virtual de Java y se utiliza para almacenar matrices e instancias de objetos. Todos los subprocesos comparten el montón de Java, lo que crea problemas de seguridad de subprocesos.

5. Área de método

El área de método, también conocida como generación permanente, se utiliza para almacenar datos como información de clases, conjuntos de constantes, variables estáticas y código compilado por el compilador justo a tiempo. En JDK8 y versiones posteriores, el área de métodos se elimina y se reemplaza por Metaspace.

6. Conjunto de constantes de tiempo de ejecución

El conjunto de constantes de tiempo de ejecución se utiliza para almacenar varios literales y referencias de símbolos generados durante la compilación, y forma parte del área de métodos. Al igual que el montón de Java, los subprocesos también comparten el conjunto de constantes de tiempo de ejecución.

mecanismo de recogida de basura

El mecanismo de recolección de elementos no utilizados de Java es una de las características importantes del lenguaje Java, que mejora la confiabilidad y la mantenibilidad de los programas mediante la administración automática de la memoria. El mecanismo de recolección de basura de Java incluye principalmente los siguientes aspectos:

  1. Creación de objetos: los programas de Java crearán continuamente nuevos objetos durante el tiempo de ejecución, y estos objetos se asignan en la memoria de almacenamiento dinámico de la máquina virtual de Java.

  2. Recuento de referencias: la máquina virtual de Java utiliza el recuento de referencias para rastrear las referencias de los objetos. Cuando se hace referencia a un objeto, su recuento de referencias aumenta en uno, y cuando ya no se hace referencia a un objeto, su recuento de referencias disminuye en uno.

  3. Recolector de basura: la máquina virtual Java tiene una variedad de recolectores de basura incorporados, que se utilizan para reciclar periódicamente objetos a los que ya no se hace referencia y liberar la memoria ocupada.

  4. Algoritmo de eliminación de marcas: la máquina virtual Java utiliza el algoritmo de eliminación de marcas para recuperar la basura. Este algoritmo divide la memoria del montón en dos áreas, una para almacenar objetos activos y otra para almacenar objetos basura. Cuando se inicia el recolector de basura, primero marcará Todo objetos vivos, luego borre todos los objetos no marcados.

  5. Algoritmo de recopilación generacional: la máquina virtual Java también utiliza un algoritmo de recopilación generacional para dividir la memoria del montón en dos partes: la nueva generación y la generación anterior. La nueva generación se usa para almacenar objetos recién creados y la generación anterior se usa para almacenar objetos que han sobrevivido durante mucho tiempo. El recolector de basura asignará objetos a diferentes generaciones según su edad para mejorar la eficiencia de la recolección de basura.

  6. Activación de la recolección de elementos no utilizados: la máquina virtual Java activa la recolección de elementos no utilizados de acuerdo con el uso de la memoria del montón. Cuando el uso de la memoria del montón supera un cierto umbral, el recolector de elementos no utilizados se iniciará para reciclar los objetos a los que ya no se hace referencia.

Cabe señalar que aunque el mecanismo de recolección de basura facilita el trabajo de desarrollo de los programadores de Java, demasiada recolección de basura tendrá un cierto impacto en el rendimiento del programa. Ajuste la estrategia y los parámetros de la recolección de basura para mejorar el rendimiento y la velocidad de respuesta de el programa.

OM

OOM es la abreviatura de OutOfMemoryError, que significa error de falta de memoria. Se genera un error OOM cuando la máquina virtual Java ya no puede asignar memoria. Esta condición generalmente es causada por:

  1. Fuga de memoria: hay una gran cantidad de objetos en el programa que no se liberan a tiempo, lo que genera un uso elevado de la memoria.

  2. Desbordamiento de memoria (Memory Overflow): El programa utiliza demasiado espacio de memoria, superando el límite máximo de memoria establecido por la JVM.

  3. Creación excesiva de objetos grandes: en una aplicación, los objetos grandes se crean con frecuencia, lo que hace que se agote la velocidad de la memoria.

  4. Demasiados subprocesos simultáneos: hay demasiados subprocesos habilitados en la aplicación, lo que provoca que la pila de subprocesos internos de la JVM ocupe demasiada memoria.

Cuando ocurre un error OOM, podemos resolver el problema a través de los siguientes pasos:

  1. Encuentre fugas de memoria: use herramientas de análisis de memoria para verificar qué objetos en el programa no se han liberado y realice los ajustes correspondientes.

  2. Aumente el límite de memoria de JVM: si la aplicación realmente necesita mucho espacio de memoria, puede aumentar el límite de memoria de JVM modificando los parámetros de inicio de JVM.

  3. Optimice el programa: evite crear objetos grandes con frecuencia tanto como sea posible, y cuando escriba código, preste atención al uso de la memoria. El número de subprocesos simultáneos también debe controlarse adecuadamente.

  4. Optimice el código: cuando use clases de colección, preste atención para eliminar elementos inútiles a tiempo, evite usar variables estáticas tanto como sea posible y reduzca la sobrecarga de memoria.

En resumen, en el desarrollo de aplicaciones, evitar errores OOM requiere que tengamos algunos conocimientos básicos de gestión de memoria y que adoptemos las soluciones correspondientes para diferentes situaciones.

Delegación de padres, ¿hay algún ejemplo de ruptura del mecanismo de delegación de padres?

En el lenguaje Java, el mecanismo de delegación principal es un mecanismo de carga de clases que requiere que cada cargador de clases tenga un cargador de clases principal, excepto el cargador de clases de inicio de nivel superior. Cuando un cargador de clases necesita cargar una clase, primero delega esta tarea a su cargador de clases principal. Si el cargador de clases principal no puede completar esta tarea (es decir, no puede encontrar la clase correspondiente dentro de su ámbito de búsqueda), el cargador de clases intentará cargar la clase por sí mismo. Este mecanismo puede evitar la carga repetida de clases y garantizar la seguridad y la estabilidad de la biblioteca central de Java.

Pero también hay algunos casos especiales que necesitan romper el mecanismo de delegación de padres, como el marco OSGi, la aplicación web y otros escenarios. En el marco OSGi, cada componente (Paquete) tiene su propio cargador de clases, y la carga de clases entre ellos es independiente entre sí, y el mecanismo de delegación de padres debe romperse; en las aplicaciones web, se deben compartir diferentes aplicaciones web. misma clase, pero sus cargadores de clase respectivos son diferentes, lo que también necesita romper el mecanismo de delegación de los padres.

Por lo tanto, en estos casos especiales, es necesario romper el mecanismo de delegación de padres escribiendo un cargador de clases personalizado o utilizando un cargador de clases especial para satisfacer necesidades específicas.

decir tres apretones de manos

TCP es un protocolo orientado a la conexión que utiliza un protocolo de enlace de tres vías para establecer una conexión y cuatro protocolos de enlace para desconectarse. El siguiente es el proceso de negociación de tres vías:

  1. El cliente envía un segmento de mensaje SYN al servidor, en el que el indicador SYN se establece en 1, lo que indica que el cliente solicita establecer una conexión.

  2. Después de recibir el segmento de mensaje SYN, si el servidor acepta establecer una conexión, enviará un segmento de mensaje SYN-ACK al cliente, en el que los indicadores SYN y ACK se establecen en 1, lo que indica que el servidor acepta establecer una conexión y notificar al cliente El siguiente paso es enviar datos al servidor.

  3. Después de recibir el segmento de mensaje SYN-ACK del servidor, el cliente envía un segmento de mensaje ACK al servidor, en el que el indicador ACK se establece en 1, lo que indica que el cliente confirma que se ha establecido la conexión. En este punto, la conexión entre el cliente y el servidor se establece con éxito y se puede realizar la transmisión de datos.

El propósito del protocolo de enlace de tres vías es garantizar que el cliente y el servidor puedan comunicarse entre sí y evitar conexiones no válidas. Específicamente, el primer apretón de manos es cuando el cliente envía una solicitud al servidor, el segundo apretón de manos es cuando el servidor responde a la solicitud del cliente y acepta establecer una conexión, y el tercer apretón de manos es cuando el cliente confirma la respuesta del servidor y notifica al servidor al mismo tiempo El cliente está listo para enviar datos. De esta forma, se puede garantizar una conexión fiable entre el cliente y el servidor y se puede realizar una transmisión de datos normal.

TCP y UDP

TCP y UDP son dos protocolos de transporte de Internet. TCP (Protocolo de control de transmisión) es un protocolo orientado a la conexión y de alta confiabilidad.Establece una conexión, transmite datos y se desconecta a través de un protocolo de enlace de tres vías. UDP (Protocolo de datagramas de usuario) es un protocolo simple y sin conexión, que no garantiza la confiabilidad de la transmisión de datos, pero la velocidad de transmisión es rápida.

TCP se usa ampliamente en Internet, como la navegación web, el envío de correo y otras aplicaciones, todas usan el protocolo TCP. Debido a que TCP puede garantizar la transmisión confiable de datos y garantizar que los datos no se pierdan, dañen o dupliquen, puede cumplir con los requisitos de estas aplicaciones para la transmisión de datos. Además, TCP también tiene un mecanismo de control de congestión, que puede evitar la congestión de la red causada por la acumulación excesiva de paquetes de datos.

UDP es adecuado para aplicaciones con altos requisitos en tiempo real, como juegos en línea, transmisión de medios de transmisión, etc. Dado que UDP no garantiza la transmisión confiable de datos, pueden ocurrir problemas como pérdida de paquetes de datos y desorden durante el proceso de transmisión, pero su velocidad de transmisión es rápida, lo que puede satisfacer las necesidades de aplicaciones con altos requisitos de tiempo real.

¿Por qué la transmisión TCP es confiable?

La razón por la cual el protocolo TCP puede garantizar una transmisión confiable es principalmente porque tiene los siguientes mecanismos:

  1. Establecer una conexión: antes de la transmisión de datos, TCP debe realizar un "apretón de manos de tres vías" para establecer una conexión para confirmar que la comunicación entre los dos extremos es normal y garantizar que ambas partes puedan recibir y enviar datos.

  2. Respuesta de confirmación: cuando TCP envía datos, esperará la respuesta de confirmación del receptor para asegurarse de que los datos han llegado correctamente. Si no se recibe confirmación, TCP intentará retransmitir los datos.

  3. Ventana deslizante: TCP utiliza una ventana deslizante para controlar el flujo de datos. El remitente y el receptor deben coordinar dinámicamente la tasa de envío de datos para evitar la congestión de la red y la pérdida de paquetes. El remitente controla la tasa de envío de datos ajustando la ventana deslizante, y el receptor controla la tasa de recepción de datos confirmando la respuesta.

  4. Tiempo de espera de retransmisión: durante la transmisión de la red, los paquetes de datos pueden perderse o dañarse. Para garantizar la transmisión confiable de datos, TCP establecerá un temporizador de tiempo de espera. Si no se recibe una respuesta de confirmación dentro del tiempo especificado, los datos se retransmitirán.

  5. Control de congestión: cuando la red está congestionada, TCP realizará el control de congestión a través de mecanismos como el inicio lento, la evitación de congestión y la recuperación rápida para garantizar la confiabilidad y estabilidad de la red.

En resumen, la razón por la cual TCP puede lograr una transmisión confiable es porque tiene múltiples mecanismos, como el establecimiento de conexión, la respuesta de confirmación, la ventana deslizante, la retransmisión de tiempo de espera y el control de congestión, que pueden evitar de manera efectiva la pérdida, el daño o la duplicación de datos y garantizar que los datos sean correctos. transmisión.

¿Puedes presentar el segmento TCP?

El segmento TCP es la unidad de transmisión de datos en el protocolo TCP, que se controla y transmite en la capa de transporte. Un segmento TCP consta de encabezado y datos.La estructura específica es la siguiente:

  1. Encabezado: ocupa 20 bytes y contiene información de control, como puerto de origen, puerto de destino, número de serie, número de confirmación, bits de bandera, etc.

  2. Datos (Data): Puede contener cero o más bytes de contenido de datos según se requiera, siendo el más largo 65.535 bytes.

Las principales funciones del segmento TCP son:

  1. Confirmar datos recibidos: decirle al compañero qué datos se han recibido a través del campo de número de confirmación.

  2. Segmentación y reensamblaje: cuando la cantidad de datos es demasiado grande, TCP los divide en varios segmentos para la transmisión y los vuelve a ensamblar en el extremo receptor.

  3. Control de flujo: a través del campo de la ventana, informe al extremo del par cuántos datos puede recibir, para controlar la cantidad de datos en el extremo del remitente.

  4. Control de congestión: a través del campo de la ventana de congestión, ajuste su propia tasa de envío para evitar la congestión de la red.

  5. Fiabilidad de garantía de datos: a través del mecanismo de retransmisión, el mecanismo de retransmisión de tiempo de espera, el mecanismo de confirmación acumulativa, etc., se garantiza la transmisión fiable de datos.

En comparación con los paquetes UDP, los paquetes TCP no tienen límite de longitud, pero el encabezado del paquete es más largo, por lo que ocupará más recursos de red. Al mismo tiempo, los segmentos TCP tienen las ventajas de confiabilidad, control de flujo y control de congestión, y son más adecuados para escenarios de aplicaciones que requieren transmisión y control confiables de la carga de la red.

Hay varias formas de lograr subprocesos múltiples, permítanme hablar sobre las ventajas y desventajas

El subprocesamiento múltiple se puede implementar de las siguientes maneras:

  1. Heredar la clase Thread: crea un nuevo hilo heredando la clase Thread y reescribiendo el método run(). Este método es simple y fácil de usar, pero dado que Java no admite la herencia múltiple, las subclases no pueden heredar otras clases.

  2. Implemente la interfaz Runnable: cree un nuevo hilo implementando la interfaz Runnable y pasándolo como parámetro al constructor de la clase Thread. Este método es más flexible y puede evitar la restricción de herencia única provocada por la herencia de clases.

  3. Implemente la interfaz Callable: similar a la implementación de la interfaz Runnable, la diferencia es que la interfaz Callable admite la devolución de valores y el lanzamiento de excepciones, y debe usar la clase FutureTask para obtener el valor devuelto.

  4. Cree un grupo de subprocesos: administre los subprocesos a través del grupo de subprocesos para evitar la creación y destrucción frecuente de subprocesos. El grupo de subprocesos puede controlar la cantidad de subprocesos para evitar la sobrecarga de subprocesos no válidos.

  5. Use el marco Fork/Join: el marco Fork/Join se introdujo en Java 7, que se usa para el procesamiento simultáneo de tareas de dividir y vencer, dividir tareas grandes en varias tareas pequeñas, asignar un subproceso para ejecutar cada tarea pequeña y resumiendo los resultados.

Todos los métodos anteriores se pueden usar para implementar subprocesos múltiples, y el método a elegir depende del escenario y los requisitos de la aplicación. La herencia de la clase Thread y la implementación de la interfaz Runnable son relativamente simples, adecuadas para algunas tareas concurrentes relativamente simples; el uso de la interfaz Callable puede obtener resultados de ejecución de subprocesos e información de excepción, que es más flexible; los subprocesos de gestión de grupos de subprocesos pueden evitar la creación y destrucción frecuente de subprocesos. subprocesos y mejorar la eficiencia del programa; el marco Fork/Join es adecuado para la computación paralela a gran escala y tareas de divide y vencerás

¿Se ha implementado el grupo de subprocesos, para qué se ha utilizado y qué parámetros se han utilizado? Hablemos de las colas de bloqueo comúnmente utilizadas en el grupo de subprocesos.

Obtenga información sobre las implementaciones de grupos de subprocesos. La agrupación de subprocesos es una tecnología para la ejecución simultánea de tareas que mejora el rendimiento y la escalabilidad al administrar y reutilizar subprocesos.

En el grupo de subprocesos, se deben especificar los siguientes parámetros:

  • corePoolSize: la cantidad de subprocesos principales en el grupo de subprocesos, es decir, la cantidad de subprocesos que siguen ejecutándose.

  • MaximumPoolSize: el número máximo de subprocesos en el grupo de subprocesos, es decir, el número máximo de subprocesos que se pueden crear.

  • keepAliveTime: cuando la cantidad de subprocesos en el grupo de subprocesos supera la cantidad de subprocesos principales, el tiempo de supervivencia de los subprocesos inactivos redundantes.

  • TimeUnit: la unidad de tiempo de keepAliveTime.

  • workQueue: una cola de bloqueo que almacena tareas que aún no se han ejecutado.

  • threadFactory: un método de fábrica para crear nuevos hilos.

  • RejectedExecutionHandler: cuando el grupo de subprocesos no puede continuar agregando tareas, la estrategia para manejar las tareas rechazadas.

Las colas de bloqueo comúnmente utilizadas para grupos de subprocesos incluyen:

  1. ArrayBlockingQueue Esta es una cola de bloqueo implementada en base a una matriz, y el tamaño de la cola debe especificarse durante la construcción. Cuando la cola está llena, las tareas nuevas se bloquearán, esperando que se tomen otras tareas antes de ejecutarlas.

  2. LinkedBlockingQueue Esta es una cola de bloqueo implementada en base a una lista enlazada.El tamaño de la cola se puede especificar, pero si no se especifica el tamaño, el valor predeterminado es Integer.MAX_VALUE. Cuando la cola está llena, las tareas nuevas se bloquearán, esperando que se tomen otras tareas antes de ejecutarlas.

  3. SynchronousQueue Esta es una cola de bloqueo sin capacidad, donde cada operación de inserción espera una operación de eliminación correspondiente, y viceversa. Por lo tanto, a menudo se usa en situaciones en las que se emparejan productores y consumidores.

Las anteriores son las implementaciones del grupo de subprocesos y las colas de bloqueo de uso común que entiendo.

Hablemos de ThreadLocal

ThreadLocal es un mecanismo de confinamiento de subprocesos en Java, que es una clase para crear variables locales de subprocesos. En el caso de use  ThreadLocal , cada subproceso tendrá su propia copia independiente de variables, por lo que los datos entre diferentes subprocesos no interferirán entre sí.

Cuando está en uso  ThreadLocal , podemos llamar  a un método para establecer un valor para el hilo actual y luego llamar  a un método para obtenerlo set() cuando necesitemos acceder a este valor  . get()Dado que cada subproceso tiene su propia variable independiente, el valor establecido por cada subproceso no será visto por otros subprocesos, lo que evita problemas de seguridad de subprocesos.

Diseño de casos de prueba Enviar archivos a un grupo de WeChat

Incluyendo, entre otros, los siguientes casos de uso:

Basado en el escenario de "enviar archivos a un grupo de WeChat", los siguientes son algunos diseños de casos de prueba:

  1. Pruebe la funcionalidad de carga de archivos. paso:

    • Confirme que puede seleccionar el archivo para cargar.

    • Después de hacer clic en el botón Enviar, si el archivo se puede cargar correctamente en el servidor de WeChat.

    • Verifique que el archivo cargado se muestre correctamente en el historial de chat.

  2. Pruebe diferentes tipos de cargas de archivos. paso:

    • Intente cargar varios tipos de archivos, como archivos de texto, imágenes, video, audio, etc.

    • El método de verificación específico es el mismo que el paso 1.

  3. Pruebe las cargas de archivos grandes. paso:

    • Seleccione un archivo grande para cargar.

    • Confirme si el archivo se puede cargar correctamente y si la velocidad está dentro de un rango razonable.

    • Verifique si el archivo cargado se puede mostrar normalmente en el historial de chat.

  4. Pruebe varias cargas de archivos al mismo tiempo. paso:

    • Seleccione varios archivos para la operación de carga.

    • Confirme si el archivo se puede cargar correctamente y si la velocidad es la esperada.

    • Verifique que todos los archivos se muestren correctamente en el historial de chat después de que se hayan cargado.

  5. Pruebe la funcionalidad de descarga de archivos. paso:

    • Elija un archivo que se haya subido al historial de chat.

    • Haga clic en el botón de descarga para confirmar que el archivo se puede descargar con éxito en el local.

    • Verifique que el contenido del archivo descargado sea el mismo que cuando se cargó.

  6. Pruebe el caso en el que falla la carga de un archivo. paso:

    • Intente cargar un archivo demasiado grande o en un formato de archivo no admitido.

    • Confirme que la operación de carga se rechazó correctamente y que se muestra el mensaje de error correspondiente.

  7. Pruebe la concurrencia de carga y descarga de archivos. paso:

    • Cargue y descargue varios archivos al mismo tiempo.

    • Verifique que todos los archivos se puedan procesar sin conflictos ni errores.

Los anteriores son algunos casos de prueba que pueden usarse para probar el escenario "enviar archivos a un grupo de WeChat". Es necesario seguir diseñando y mejorando los casos de prueba de acuerdo con los requisitos específicos y las funciones específicas del software.

Código desgarrado a mano: convertir números arábigos a caracteres chinos (la persona que terminó la pregunta se ha ido y no sé los límites superior e inferior de los dígitos, así que terminé de escribirlo con una cara de confusión)

def num_to_chinese(num):
# 汉字数值词典
    chinese_num = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']
    chinese_unit = ['', '十', '百', '千']

# 将数字拆分成千百十个位上的数字
    digits = [int(x) for x in str(num)]
    digits.reverse()

# 数字转换成汉字
    result = ''
if num == 0:
return chinese_num[0]
else:
for i, digit in enumerate(digits):
if i == 0 and digit == 0:
continue
elif digit == 0:
                result = chinese_num[0] + result
else:
                result = chinese_num[digit] + chinese_unit[i] + result

    return result

Pregunta retórica: le pregunté al entrevistador si ha estado haciendo un trabajo relacionado con las pruebas y el desarrollo. ¿Cree que se requieren habilidades especiales para las pruebas y el desarrollo en comparación con el desarrollo? El entrevistador dijo que no tenía nada que ver conmigo,

Dije que no hay problema.

Puede ser porque me atraparon, la entrevista sintió que la hermana mayor había estado buscando preguntas en la computadora a su lado, y luego respondí la respuesta correcta, y después de encontrar una pregunta, fruncí el ceño y corregí la respuesta, la grabé. , y luego encontré el siguiente Pregunte, no hay interacción en absoluto, los estereotipos no son difíciles, hay muchas preguntas sobre el proyecto y el mano a mano también está escrito, pero la experiencia de la entrevista es muy mala. ,

La primera es que estuve completamente distraída durante la entrevista con la hermana mayor, ella solo miró hacia otro lado cuando hizo una pregunta y no sonó bien. Entonces, aunque siento que las respuestas a las preguntas son bastante buenas, el viernes recibí la carta de agradecimiento a tiempo. Si me atraparan, significaría que el KPI aumentó y el rendimiento mejoró. Afortunadamente, no lo hice. Reportar demasiada expectativa en ese momento, de lo contrario le tomaría mucho tiempo a la emo.

Finalmente: el tutorial completo de aprendizaje en video de prueba de software a continuación se ha ordenado y cargado, y los amigos pueden obtenerlo gratis si lo necesitan【保证100%免费】

inserte la descripción de la imagen aquí

 Estos materiales deben ser el almacén de preparación más amplio y completo para los amigos [de pruebas de software] Este almacén también ha acompañado a decenas de miles de ingenieros de pruebas a través del viaje más difícil, ¡y espero que también pueda ayudarlo a usted!

Supongo que te gusta

Origin blog.csdn.net/weixin_50829653/article/details/130506205
Recomendado
Clasificación