Maison >développement back-end >Tutoriel Python >Mots originaux réécrits : une découverte inattendue est que ce qui était initialement considéré comme un bug est en réalité une fonctionnalité de la conception de Protobuf.

Mots originaux réécrits : une découverte inattendue est que ce qui était initialement considéré comme un bug est en réalité une fonctionnalité de la conception de Protobuf.

PHPz
PHPzavant
2023-05-09 16:22:09927parcourir

Bonjour à tous, je suis incroyable.

Récemment, dans notre projet, nous utilisons le format protobuf comme support pour stocker les données. J'ai accidentellement enterré un grand trou pour moi-même, mais il m'a fallu beaucoup de temps pour le découvrir.

Introduction à protobuf

Le nom complet de protobuf est Protocal buffers. Il a été développé par Google et constitue un mécanisme multilingue, multiplateforme et évolutif pour la sérialisation des données. Similaire à XML, mais plus petit, plus rapide et plus simple. Il vous suffit de définir une seule fois la façon dont vous souhaitez que vos données soient structurées, puis vous pouvez utiliser ses outils de génération pour générer du code source qui inclut certaines opérations de sérialisation et de désérialisation. Les données structurées peuvent être facilement écrites et lues à partir de divers flux de données et à l'aide de divers langages de programmation.

La version proto2 prend en charge la génération de code en Java, Python, Objective-C et C++. Avec la nouvelle version du langage proto3, vous pouvez également utiliser Kotlin, Dart, Go, Ruby, PHP et C#, et bien d'autres langages.

Comment l'avez-vous découvert ?

Dans notre nouveau projet, nous stockons les données du projet exécuté en utilisant le format protobuf. De cette manière, pendant le processus de débogage, nous pouvons effectuer un débogage local sur la base des données enregistrées sur site.

message ImageData {
// ms
int64 timestamp = 1;
int32 id = 2;
Data mat = 3;
}

message PointCloud {
// ms
int64 timestamp = 1;
int32 id = 2;
PointData pointcloud = 3;
}

message State {
// ms
int64 timestamp = 1;
string direction = 2;
}

message Sensor {
repeated PointCloud point_data = 1;
repeated ImageData image_data = 2;
repeated State vehicle_data = 3;
}

Nous définissons un tel ensemble de données, puis lors du stockage, car les fréquences d'images des trois sources de données du capteur sont différentes, lors du stockage, un seul capteur ne contient en fait qu'un seul ensemble de données, et les deux autres types de données ne sont pas inclus.

Nous n’avons pas eu de problème lorsque nous n’avons enregistré qu’un seul pack. Jusqu'à ce que nous sentions qu'un seul paquet ne peut pas être enregistré pendant une longue période, nous devons trouver une solution pour diviser le paquet.

À cette époque, je pensais que cela devait être très simple, alors nous le configurons lorsqu'un package atteint 500 Mo, nous stockerons les données suivantes dans un nouveau package. J'ai fini de l'écrire très facilement, puis je l'ai mis sur place pour l'enregistrement des données. Après avoir enregistré pendant un moment, nous avons repris le package et simulé le test de notre nouveau programme. Il a été constaté qu'il y avait un problème lors de l'analyse des données de certains packages. Le programme restera bloqué au milieu de l'exécution. Après de nombreux tests, il a été constaté que certains packages présentaient ce problème.

Ce que nous soupçonnions au départ, c'est que la façon de juger de la taille des fichiers était erronée, ce qui affectait la sous-traitance. Parce qu'en jugeant la taille du fichier, le fichier sera ouvert. Mais après avoir jugé plusieurs autres moyens de ne pas ouvrir le dossier, la scission a été réalisée. J'ai encore rencontré des problèmes avec certains des packages enregistrés.

C'est alors que j'ai soupçonné que protobuf avait des exigences particulières en matière de stockage de données. Plus tard, j'ai lu quelques articles et appris que protobuf nécessite des identifiants pour stocker plusieurs ensembles de données dans un seul fichier. Sinon, lors de l'analyse du fichier, protobuf ne sait pas où se trouve le caractère d'arrêt d'une seule donnée, ce qui provoque des erreurs d'analyse des données.

Ici, cette fosse apparaît. Nous stockons une série de données dans un seul package sans effectuer aucune opération de séparation. Lorsque protobuf analyse, tout le contenu du fichier est analysé dans un seul capteur. Le capteur contient toutes les données et protobuf fusionne activement toutes les données stockées.

À ce moment-là, j'ai découvert que lorsque j'enregistrais des paquets individuels auparavant, les données étaient toutes correctes. C'était vraiment ma chance. protobuf est analysé avec succès.

Comment le résoudre ?

Maintenant que nous savons que protobuf fonctionnera de cette manière, il ne nous reste plus qu'à savoir comment diviser protobuf. Cette méthode est vraiment difficile à trouver car trop peu de gens comme nous l’utilisent. La recherche chinoise ne trouve pas du tout ce contenu. Peut-être que tout le monde n'utilise pas protobuf pour stocker des données. La méthode que tout le monde utilise devrait être le scénario d'interaction entre plusieurs services.

J'ai finalement trouvé la réponse grâce à quelques réponses sur stackoverflow. D'après les réponses, j'ai appris que cette solution n'a été officiellement fusionnée que dans protobuf 3.3. Il semble que cette fonction soit vraiment rarement utilisée.

bool SerializeDelimitedToOstream(const MessageLite& message,
 std::ostream* output);
bool ParseDelimitedFromZeroCopyStream(
MessageLite* message, io::ZeroCopyInputStream* input, bool* clean_eof);

Grâce à cette paire de méthodes, les fichiers peuvent être stockés et lus un par un en fonction du flux de données. Ne vous inquiétez plus de la fusion et de la lecture des données.

Bien entendu, les données stockées de cette manière ne peuvent pas être analysées par la méthode d'analyse d'origine et le format de stockage a complètement changé. Cette méthode stockera d'abord la taille des données binaires, puis stockera les données binaires.

Remarques finales

Après beaucoup de problèmes, j'ai finalement résolu cette fosse de séparation. Le scénario d'utilisation peut être relativement spécialisé, ce qui entraîne de nombreuses informations introuvables. J'ai découvert ces problèmes en regardant moi-même le code source. Le code source du C++ est vraiment difficile à lire. Il existe de nombreuses méthodes de modèles et classes de modèles et il est facile de manquer certains détails. Enfin, j'ai regardé le code C# et je l'ai finalement confirmé.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer