Principios de serialización
JSON (JavaScript Object Notation) es un formato ligero de intercambio de datos. En comparación con XML, el flujo de bytes de JSON es más pequeño y más legible. Hoy en día, el formato de datos JSON es la aplicación más común en las empresas y existen muchas herramientas de código abierto de uso común para la serialización JSON.
Entre estas herramientas de serialización json, el rendimiento de Jackson y fastjson es mejor que el de GSON, pero la estabilidad de Jackson y GSON es mejor que la de Fastjson. La ventaja de fastjson es que la API proporcionada es muy fácil de usar.
Hessian es un protocolo de serialización binaria que admite la transmisión entre idiomas. Hessian ofrece mejor rendimiento y facilidad de uso que el mecanismo de serialización predeterminado de Java y admite muchos lenguajes diferentes.
De hecho, Dubbo utiliza la serialización de Hessian para implementarlo, pero Dubbo reconstruyó Hessian con un mayor rendimiento.
Avro es un sistema de serialización de datos diseñado para soportar aplicaciones de intercambio de datos a gran escala. Sus características principales son: admite la serialización binaria y puede procesar grandes cantidades de datos de manera conveniente y rápida. El lenguaje dinámico es amigable y el mecanismo proporcionado por Avro permite que el lenguaje dinámico procese los datos de Avro de manera conveniente.
Kryo es una implementación de serialización muy madura y se usa ampliamente en Hive y Storm, pero no es multilingüe. Actualmente, dubbo ya admite el mecanismo de serialización de kyro en la versión 2.6. Su rendimiento es mejor que el de la arpillera2 anterior.
Protobuf es un formato de intercambio de datos de Google independiente del idioma y la plataforma. Google proporciona múltiples lenguajes de implementación, como Java, C, Go y Python. Cada implementación incluye archivos de compilador y biblioteca para el idioma correspondiente. Protobuf es un protocolo de capa de presentación puro que se puede utilizar con varios protocolos de capa de transporte.
La razón por la que Protobuf se usa ampliamente es principalmente por su baja sobrecarga de espacio y buen rendimiento, lo cual es muy adecuado para llamadas RPC con altos requisitos de rendimiento dentro de la empresa. Además, debido a que el rendimiento del análisis es relativamente alto y la cantidad de datos serializados es relativamente pequeña, también se puede aplicar a escenarios de persistencia de objetos. Sin embargo, usar Protobuf será relativamente problemático porque tiene su propia sintaxis y compilador, y debe hacerlo. invertir en él cuando sea necesario para aprender esta tecnología.
La desventaja de Protobuf es que se debe generar un archivo proto correspondiente para que se transfiera la estructura de cada clase. Si se modifica una clase, se debe regenerar el archivo prototipo correspondiente.
Comparación de rendimiento de varias tecnologías de serialización
Esta dirección tiene una comparación de rendimiento de diferentes tecnologías de serialización: /ei shay/JVM-serializer/wiki.
Los pasos generales para desarrollar usando protobuf son los siguientes
Escribir el archivo prototipo
Tipo de datos
cadena/bytes/bool/ int 32 ( 4 bytes)
/int64/float/double
Clase de enumeración de enumeración
Clase personalizada de mensaje
Modificador
Obligatorio se refiere a los campos obligatorios.
Opcional indica un campo opcional.
Repetible, representando una colección.
1, 2, 3, 4 deben ser únicos dentro del alcance actual para indicar el orden.
Generar clase de entidad
Implementar serialización
Resultado de salida: 10377 10599 16-842
Se puede ver que el número serializado es Básicamente es incomprensible, pero los datos serializados son realmente pequeños, así que comprendamos los principios subyacentes.
Por lo general, para lograr el resultado de serialización más pequeño, se debe utilizar tecnología de compresión y protobuf utiliza dos tecnologías.
Algoritmos de compresión, uno es varint y el otro es zigzag.
-Valante
Primero echemos un vistazo a cómo se comprime el número edad = 300.
Los resultados de estos dos bytes son -84 y 2 respectivamente.
¿Cómo se calcula -84? Sabemos cómo representar números negativos en binario. El bit de orden superior se establece en 1 y la representación en complemento a dos se calcula después de la negación binaria del número correspondiente (el complemento a uno es el complemento a 1).
Entonces, si quieres trabajar al revés,
Cómo convertir caracteres en códigos
El carácter "Mic" debe convertirse en un número de acuerdo con un Tabla de búsqueda ASCII.
M =77, i=105, c=99
Entonces el resultado es 77 105 99.
¿Por qué el resultado aquí es directamente un valor codificado en ASCII? ¿Por qué no lo comprimes?
La razón es que vaint comprime el código de bytes, pero si el binario de este número solo requiere un byte, el resultado final de la codificación no cambiará.
Hay otros dos números, el 3 y el 16. ¿Qué representan? Entonces necesitas comprender el formato de almacenamiento de protobuf.
Formato de almacenamiento
Protobuf utiliza T-L-V como modo de almacenamiento.
La etiqueta se calcula como field_number (el número del campo actual)
Por ejemplo, el número de campo de Mic es 1 y el valor del tipo wire_type es 2, por lo tanto: 1
El número de campo de edad=300 es 2, y el valor de tipo wire_type es 0, entonces: 2
El primer número 10 representa la clave y el resto son valores.
Almacenamiento de números negativos
En las computadoras, los números negativos se representarán como números enteros grandes, porque la computadora define el bit de signo de un número negativo como el bit más significativo de un número. entonces, si está codificado con vaint Para representar un número negativo, se requieren 5 bits. Por lo tanto, en protobuf, los números negativos están representados por el tipo sint32/sint64, y la forma de procesamiento de números negativos es primero codificación en zigzag (conversión de números con signo en números sin signo) y luego codificación varint.
Sint 32: (n lt; lt1) ^ (n 》 gt31)
Sint 64: (n lt; lt1) ^ (n 》 gt63)
Por ejemplo, almacenar un valor (-300)
-300
Código original: 0001 0010 1100.
Invertida: 11110101011.
Agregar 1: 1101101010100.
n lt lt1: Mueve el todo hacia la izquierda una posición, suma 0 a la derecha -》1101 1010 10 1000
n gt gt31: Desplaza el todo hacia la derecha una 31, agregue 1 a la izquierda -》; 1111 1111 1111
n lt lt1 ^ n gt; gt31
1101 1010 1000 ^ 1111 1111 1111 = 0010 0101 0111
Decimal: 00101011111 = 599.
Algoritmo Varint: Trabaja desde la derecha, elige 7 bits, el complemento de orden superior es 1/0 (depende del número de bytes).
Obtiene dos bytes
1101 0111 y 0000 0100.
-41 y 4
El rendimiento del búfer de protocolo es muy bueno, lo que se refleja principalmente en el pequeño tamaño después de la serialización. La alta velocidad de serialización conduce en última instancia a una alta eficiencia de transmisión por las siguientes razones: