0

Je suis chargé d'optimiser les performances d'une routine de traitement de données linéaire. Voici un aperçu de ce qui est déjà en place:Traitement de données par lots en temps réel

Les données arrivent sur les ports UDP, nous avons plusieurs écouteurs écoutant sur un port différent et écrivant des données brutes dans la base de données SQL Server (appelons la table un RawData). Ensuite, nous avons plusieurs instances d'une application linéaire à un seul thread saisissant des données brutes de la table RawData et traitant des datarows individuelles. Quels moyens de traitement sont les données brutes sont comparées aux données précédemment reçues pour l'entité donnée, les calculs sont effectués pour calculer le nombre de lectures différentes, puis deux services Web sont appelés pour chaque ligne de données individuelle et enfin un nouvel enregistrement est ajouté pour chaque donnée ligne dans la table ProcessedData. L'enregistrement d'entité correspondant est également mis à jour dans l'autre table. La façon dont je vois le problème, il peut être divisé en plus petites parties et je pourrais utiliser le modèle Producer/Consumer pour le traitement des données: Un thread du producteur remplit une file d'attente partagée (blocage), plusieurs consommateurs saisissent des lignes de données la file d'attente et faire un traitement parallèle d'entre eux. Une fois les consommateurs terminés, ils placent les données traitées dans une autre file d'attente partagée, qui sera ensuite accessible par un autre thread consommateur (single) qui fera un SqlBulkCopy pour insérer de nouveaux enregistrements. Au cours du processus, il y aura d'autres files d'attente partagées qui stockeront les informations d'entité pour les mises à jour et un autre consommateur saisira des informations mises à jour pour les entités et effectuera des mises à jour. La question est, même si elle semble simple, elle me semble être une approche encombrante. Je pense qu'il y a une meilleure façon de faire ce que je cherche. Des suggestions sur la mise en œuvre du modèle Producer/Consumer ci-dessus? Ou devrais-je chercher un modèle de conception différent pour mon problème?

Merci à l'avance

+0

Quand vous dites « requête partagiez », voulez-vous dire « file d'attente partagée »? –

+0

oui, ma mauvaise. Merci de l'avoir remarqué. Corrigé – Dimitri

Répondre

2

Votre solution proposée semble raisonnable, et je ne considère pas comme lourdeur du tout. C'est simple à comprendre, simple à mettre en œuvre, efficace et efficace. Il vous permet également d'ajuster le nombre de producteurs et de consommateurs pour obtenir les meilleures performances. La décomposition en parties plus petites avec une communication limitée entre les parties est une très bonne chose. Vous avez donc plusieurs threads (producteurs) qui lisent les données d'UDP et stockent ces éléments dans une file d'attente partagée. Appelez-la la file d'attente RawData. Plusieurs consommateurs lisent cette file, traitent les éléments et placent les résultats dans une autre file d'attente partagée. Appelez-la la file d'attente ProcessedData. Enfin, vous avez un seul thread qui lit la file d'attente ProcessedData et stocke des éléments dans la base de données.

Le .NET BlockingCollection est parfait pour cela.

Cela pourrait être une aide: Question on C# threading with RFID

+0

Merci Jim pour répondre. Oui, j'ai été divisé sur quel type de file d'attente correspondrait le mieux à mes besoins. J'envisageais d'utiliser une file d'attente circulaire ou un double tampon, pour minimiser les temps de verrouillage. Je sais que nous n'avons pas beaucoup de données à traiter pour le moment, mais je pense toujours à l'évolutivité. Je détesterais revenir en arrière et réécrire l'application lorsque le trafic monte. – Dimitri

+0

J'ai un petit problème avec BlockingCollection. Même si elle implémente ConcurrentQueue en tant que base de collection, j'ai remarqué que lorsque j'ajoute plusieurs threads pour les consommateurs, ils ne garantissent pas de récupérer les éléments de la file d'attente de façon séquentielle. J'ai essayé Parallel.Foreach et Parallel.For. Ils semblent tous deux ne pas honorer l'ordre des articles. Puis j'ai essayé Task.StartNew, qui semble honorer la séquence. En outre, j'ai besoin de stocker la sortie des consommateurs à une autre file d'attente, qui doit être commandée. Puis-je utiliser le même BlockingCollection et exécuter .OrderBy dessus?ou id être mieux en utilisant SortedList et en manipulant le verrouillage manuellement? – Dimitri

+0

@Dimitri: Vous touchez à beaucoup de problèmes là-bas. C'est probablement mieux si vous postez cela comme une autre question. –