1 votes

Conception du système / architecture Meilleure approche

J'ai un système qui comporte trois parties générales pour faciliter ma description.

1) BASE DE DONNÉES - pour stocker toutes les tables, cette même base de données stockera également des données pour d'autres services, y compris une application web, silverlight etc... (doit être flexible, si elle se trouve sur un serveur distant, elle peut être exposée via un service web, si elle se trouve localement, elle peut se connecter localement ou via TCP au service Windows).

2) BOÎTE NOIRE - traiter UN élément à la fois en injectant la liste des éléments requis à partir de la base de données, comme un tuyau, où l'on introduit un ensemble de conditions, de valeurs pour un seul élément, et où l'on renvoie les résultats pour cet unique élément traité.

3) SERVICE Windows - pour extraire des données de la base de données, les injecter dans la boîte noire, enregistrer les résultats de la boîte noire dans la base de données à des intervalles prédéfinis. Le service peut se trouver sur un serveur différent de celui de la base de données. Il enregistre les erreurs et continue en cas d'erreur.

En moyenne, le service Windows devra traiter environ 5000 éléments, et il faudra à la boîte noire environ 1,5 seconde pour traiter 5000 éléments.

Mes questions sont les suivantes :

a) Le service Windows doit-il obtenir une liste de lots d'éléments à traiter à partir de la base de données, ou doit-il obtenir une liste d'identifiants et, dans une boucle, récupérer chaque élément individuel de la base de données avant de le transmettre à la boîte noire ? Notez que la même base de données est également utilisée par d'autres applications. Je suppose que la base de données devrait être un appel à un service web quelconque.

b) Un article individuel doit-il être sauvegardé immédiatement après son traitement ? Ou doit-on attendre la fin du traitement du lot avant de l'enregistrer ? Étant donné que la sauvegarde de chaque élément individuel après traitement est une bonne chose lorsque le système tombe soudainement en panne au milieu du processus, au moins les éléments traités sont sauvegardés, mais au détriment des performances en raison des 5 000 appels au service web ?

Des conseils sur une solution optimale ?

Santé

2voto

dan Points 4107
  1. Vous devriez extraire vos éléments par lots afin de ne pas encombrer le réseau avec des requêtes. Saisir une liste d'identifiants, puis les mettre en boucle et extraire l'élément complet à chaque fois, c'est N appels supplémentaires à la base de données.

    • vous pouvez utiliser un webservice pour gérer l'appel à la base de données, si vous pensez bénéficier de l'abstraction. sinon, vous ne ferez que créer une complexité inutile.
  2. mettre à jour la base de données au fur et à mesure que vous terminez chaque article. les articles terminés peuvent être utilisés dès qu'ils sont prêts, au lieu d'attendre que les lots de 5 000 articles soient terminés.

    • Cela suppose que vous enregistrez les données pour chaque élément.

    • vous devez faire N appels (pour sauvegarder chaque élément) quoi qu'il arrive, vous ne gagnez donc pas grand-chose à attendre et à mettre à jour à la fin de chaque lot.

    • s'il tombe en panne, vous perdrez toutes les données non sauvegardées.

    • si vous n'avez pas besoin de stocker les résultats par élément de la boîte noire, vous avez une bonne raison d'envisager de tout mettre à jour par lots.

J'ai écrit un ensemble d'applications comme cela pour une banque. Mon approche habituelle est la suivante : elle est simple, tolérante aux pannes et efficace. (en supposant que vous ayez besoin de traiter des ensembles d'éléments et d'enregistrer des données pour chacun d'entre eux)

  1. la base de données comporte une table représentant l'état de traitement d'un article, en plus de la table des articles. moyennant un peu de travail supplémentaire au départ, cela facilitera le débogage et l'audit du processus :

    table ItemsProcessStatus  -- feel free to improve upon the name
    int orderID (auto increment)
    int itemID  (fk to items)
    datetime pulledForProcessing null
    datetime finishedProcessing null
    ..etc
  2. Service Windows s'exécute sur une minuterie, par exemple toutes les X minutes, et tire limit(Y) à traiter. cela marque l'entrée en vigueur de la pulledForProcessing avec un horodatage dans la base de données ItemsProcessStatus table.

    • Vous souhaitez extraire les éléments dont la date d'extraction est nulle [ainsi que ceux qui ont été extraits, mais qui n'ont pas été achevés et qui sont antérieurs à Z minutes (je choisis généralement 15 à 30 minutes)]

    • Soyez prudent avec la procédure qui tire ces. vous devez utiliser des verrous

    • Vous pouvez l'affiner davantage : Lors de la première itération, saisissez Y les éléments, où Y est une bonne estimation de la quantité de données que vous pouvez traiter dans ce laps de temps. Lors de l'itération suivante, vous calculez le taux de traitement (sous forme de moyenne glissante) et vous ajustez le nombre d'articles à retirer.

  3. le service Windows les traite un par un (en général, il est multithreadé, donc plusieurs à la fois) en les envoyant à la boîte noire.

    • Je les place dans une file d'attente threadsafe Queue<> (à ne pas confondre avec msmq). Les threads de travail bouclent, puisent dans la file d'attente, traitent l'élément dans la boîte noire, puis mettent à jour la base de données.

    • vous pouvez utiliser n'importe laquelle des techniques typiques du multithreading (wait/pulse, reader/writer lock slim, wait handles), ou simplement faire dormir le thread worker pendant quelques secondes si la file d'attente est vide.

  4. après la fin du traitement de chaque élément, appeler le processus de mise à jour pour cet élément, qui met également à jour le tableau ItemsProcessStatus (signifiant que le traitement est terminé).

  5. Lorsque votre service est arrêté, terminez le traitement des éléments en cours et mettez-les à jour dans la base de données.

    • Pour tous les éléments qui n'ont pas été envoyés dans la boîte noire, vous les désélectionnez dans le tableau des processus en définissant l'option pulledForProcessing à null.
  6. si votre service tombe en panne, vous ne "perdez" pas beaucoup de données. les éléments qui n'ont pas été démarqués seront à nouveau retirés lorsqu'ils auront dépassé un certain âge (tableau des processus).

Cela fonctionne avec plusieurs instances du service Windows installées sur un ensemble de serveurs (bien que vous deviez ajouter le service ComputerName à la table des processus pour identifier l'ordinateur sur lequel chaque service s'exécute). Cela fonctionne parce que chaque service se contente d'attraper le "prochain ensemble d'éléments" à traiter - il n'y a pas besoin d'un quelconque routage ou d'une communication entre les processus.

1voto

Larry Watanabe Points 7305

MSMQ est l'approche de Microsoft en matière de file d'attente. Je suis d'accord pour dire qu'il faut utiliser une approche de file d'attente - c'est le cas dans la plupart des systèmes qui traitent un grand nombre de transactions. Par exemple, dans la banque où je travaillais, nous utilisions MQ comme solution intermédiaire.

L'avantage est que l'étape suivante du processus peut commencer immédiatement après la première, sans attendre que les 5 000 entrées aient été traitées. Que se passe-t-il si le nombre d'entrées passe à 500 000 000 ? Le temps d'attente pour le traitement du premier élément augmentera alors considérablement. En utilisant une approche de file d'attente, il ne changerait pas du tout.

Il y a d'autres avantages - évolutivité, robustesse, garantie de livraison - mais vous en apprendrez plus sur ces questions plus tard.

De plus, une file d'attente bien implémentée produit très peu de surcharge d'attente dans les processus qui l'utilisent, puisqu'ils supportent presque toujours plusieurs threads accédant aux files d'attente. (Il y aura une surcharge, mais le temps d'attente ne sera pas beaucoup plus long).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X