Nous essayons de faire fonctionner Service Broker dans notre environnement afin de résoudre une analyse de rentabilisation. Je ne sais pas si le titre du message est bon, mais ma question est ci-dessous. Mais ce n'est peut-être pas une bonne question, alors après c'est ce que nous faisons et pourquoi je pense que c'est la bonne question.
Combien de messages doivent être envoyés lors d'une conversation avant de mettre fin à la conversation?
Nous voulons utiliser Service Broker afin de mettre à jour de manière asynchrone une table de résultats. Le tableau des résultats est aplati et rapide. Nous avons des déclencheurs sur les tables de base qui envoient un message avec leur table et leur clé primaire. Nous avons trois files d'attente:
- Faible latence - l'objectif est de 15 secondes à traiter. Il gère les éléments qui changent par rapport à un élément spécifique.
- Bulk Queue - l'objectif est de 5 minutes à traiter. Il gère quand quelque chose change qui affecte plusieurs centaines (ou milliers) d'éléments. Il éclate la liste des éléments qui ont été affectés et les alimente dans la file d'attente à faible latence différée
- Faible latence différée - l'objectif est de 30 minutes à traiter. Cela traite les éléments mais uniquement à partir de la file d'attente en bloc.
Fondamentalement, si les informations d'un client sont mises à jour; cela affecte de nombreux produits et est envoyé à la file d'attente en bloc pour un traitement plus lent. Cependant, si un produit est mis à jour, il est envoyé à la file d'attente à faible latence.
Nous réutilisons des conversations similaires au blog de Remus Rusanu http://rusanu.com/2007/04/25/reusing-conversations/ , à l'exception que nous le faisons en fonction du module de la clé primaire. Cela a l'avantage secondaire de faciliter la déduplication des clés primaires.
Nous réutilisons donc les conversations et respectons nos directives. Avec deux threads, j'ai pu graver 125 messages / seconde (baisse artificielle de plusieurs milliers de messages), ce qui est plus que capable de suivre la production (environ 15 messages / sec).
Cependant, le problème que nous rencontrons est qu'après une période de temps, ~ 4 heures ou 120 000 messages, nous avons commencé à voir des blocs et des conflits élevés sur sysdesend et la table de file d'attente. Les verrous sont LCK_M_U et sont des verrous KEY. Parfois, le hobt se résout en sysdesend et d'autres fois en table de file d'attente spécifique (queue_).
Nous avons un processus en place qui mettra fin aux conversations après 24 heures ou 30 minutes d'inactivité, nous pourrions donc simplement augmenter le temps avant de parcourir les conversations.
Nous utilisons SQL 2016 Enterprise (13.0.4001.0)
- Déclencher des incendies (envoyer à faible latence ou en masse)
- Recherchez ou créez une poignée de conversation.
- envoyer le message
- Procédure activée dans la file d'attente
- Mettre à jour le tableau des résultats
Le processus de nettoyage s'exécute toutes les 10 minutes pour voir s'il y a des conversations inactives. s'il les trouve plus de trois fois de suite, il le marque comme inactif et met fin aux conversations.
Veuillez me faire savoir s'il y a des détails supplémentaires qui pourraient être bénéfiques. Je n'ai pas beaucoup d'expérience avec Service Broker, donc je ne sais pas si nos messages / sec sont faibles, élevés ou indifférents.
MISE À JOUR
Nous avons donc réessayé aujourd'hui et avons rencontré le même problème. Nous avons changé la durée de vie de la conversation à 2 heures et cela n'a eu aucun effet. Nous avons donc mis en œuvre l'astuce 150; qui avait le même problème.
Des tonnes d'attente sur SEND CONVERSATION, en attente sur sysdesend. Quelqu'un a-t-il d'autres idées?
MISE À JOUR 2
Nous avons effectué le test plus longtemps aujourd'hui et pendant l'une des périodes d'échantillonnage de 17 minutes, nous avons traité 41 000 messages sur 4 poignées de conversation. Nous avons pu suivre, sauf vers la fin, lorsque les verrous du sysdesend et de la table de file d'attente sont devenus trop importants et nous avons commencé à dériver derrière avant de l'arrêter. Nous semblons n'avoir aucun problème à traiter les messages, sans que des choses entrent dans la file d'attente, nous pouvons les retirer et les traiter au moins 5 fois cette vitesse. Notre vitesse semble être limitée en fonction de l'ajout de messages.
Lors d'un test ultérieur, nous avons supprimé l'un des déclencheurs qui représentaient 80% des messages. Même avec cette charge très réduite, nous avons commencé à voir les mêmes attentes.
MISE À JOUR 3
Merci, Remus pour vos conseils (et merci d'avoir posté d'excellents articles de blog sur le sujet, ils ont contribué à ce point).
Nous l'avons couru à nouveau aujourd'hui et nous avons fait mieux (comme nous y sommes allés plus longtemps avant de voir les attentes et encore plus longtemps avant qu'il ne nous paralyse). Donc, les détails.
Nous avons changé: * Augmentation du nombre de conversations maintenues par thread de 1: 1 à 2: 1. Fondamentalement, nous avions 8 poignées de conversation pour 4 threads.
- consolidé la file d'attente en masse (car un message entrant peut signifier des centaines de messages sortants) pour se regrouper en moins de messages plus volumineux.
Remarques sur cette tentative:
désactivation de la procédure d'activation de la file d'attente cible. aucun changement dans le blocage (nous avons attendu 5 minutes) et les messages ont été envoyés à sys.transmission_queues.
surveillance de sys.conversation_endpoints. Ce nombre est passé de 0 à 13K très rapidement, puis a augmenté plus lentement tout au long de la journée pour atteindre environ 25K après environ 5 heures. Le blocage n'a commencé à se produire qu'après avoir atteint 16K +/-
Je suis entré dans le DAC et j'ai exécuté les commandes DBREINDEX pour les files d'attente, bien que, à partir d'une requête, les enregistrements fantômes n'aient jamais dépassé 200 ou plus avant le nettoyage et que le nombre soit tombé à 0.
sysdesend et sysdercv avaient des comptes identiques de 24 932 lorsque j'ai terminé le test.
nous avons traité environ 310 000 messages en 5 heures.
Nous sommes allés si longtemps avant que les choses ne s'effondrent que je pensais vraiment que nous réussirions cette fois. Demain, nous essaierons de forcer les messages à passer par le fil.
la source
we started seeing blocks and high contention on sysdesend and the queue table.
-> Quel est le type d'attente -PAGELATCH_EX/SH and WRITELOG
? Avez-vous utilisé le truc 150 ? Si les tables système sont votre point de contention, l'astuce 150 sera très utile.sys.conversation_endpoints
pendant le test (constant ou augmente, et quelle est sa taille lorsque le blocage se produit). 2) Lorsque le blocage se produit, la désactivation de la file d'attente cible fait-elle une différence dans le blocage de SEND (la désactivation de la file d'attente doit acheminer SEND vers sys.transmission_queue). et 3) Forcer les messages à passer au fil, même localement (configurer un point de terminaison SSB, ajouter des routes) change le comportement à long termeALTER QUEUE ... REBUILD
fait-elle une différence une fois que le blocage commence?Réponses:
Je sais que c'est une mauvaise forme de répondre à votre propre question, mais je voulais que cela soit clos pour toute personne intéressée. Nous avons finalement réussi à résoudre le problème, ou du moins à le résoudre suffisamment pour répondre à nos besoins. Je tiens à remercier tous ceux qui ont contribué aux commentaires; Remus Rusanu et Kin car ils étaient très utiles.
Notre base de données est assez occupée et est en mode RCSI. Nous avons plusieurs (milliers) d'appareils mobiles qui mettent à jour leurs informations de localisation toutes les 45 secondes. Grâce à ces mises à jour, plusieurs tables obtiennent leurs informations mises à jour (mauvaise conception, car j'aurais limité les informations volatiles à une seule table, puis je les ai jointes pour les résultats). Ces tables sont les mêmes que celles que nous tentions de générer de manière asynchrone pour les rapports plutôt que de demander aux utilisateurs finaux d'aller directement contre les tables de base.
Au départ, les déclencheurs faisaient passer un curseur sur les enregistrements modifiés dans chaque instruction update / insert (cela devait être une ligne dans la plupart des cas) et envoyaient chaque clé primaire dans un message au service broker. À l'intérieur du courtier de services, en particulier la file d'attente en vrac, il y avait d'autres curseurs qui exécutaient la procédure upsert pour le rapport (une exécution par clé primaire).
Ce qui nous a finalement fait travailler:
Nous avons supprimé les curseurs et décidé d'envoyer des messages plus volumineux. Encore un message par transaction utilisateur par table, mais nous envoyons maintenant des messages avec plus d'une clé primaire.
Le processeur en vrac envoie également plusieurs clés par message, ce qui a réduit le nombre de SEND CONVERSATIONS qui étaient en cours car il a mélangé les messages vers l'autre file d'attente, le cas échéant.
Les déclencheurs ont été supprimés de la table la plus volatile (notre table de données d'appareils mobiles). Nous avons mis à jour la procédure upsert pour inclure les clés étrangères appropriées et maintenant nous rejoignons simplement cette table lors de la récupération des résultats aux utilisateurs. Ce tableau a facilement contribué à 80% des messages que nous avons dû traiter en une journée.
Nous traitons environ 1 million de messages par jour (sans la table mobile) et la grande majorité (99% +) de nos messages sont traités dans notre objectif. Nous avons encore la valeur aberrante occasionnelle, mais étant donné la nature rare de la, elle est jugée acceptable.
Facteurs contributifs:
J'ai trouvé un bogue dans la procédure de nettoyage de conversation mentionné plus tôt qui ne nettoyait pas réellement les conversations de manière appropriée et les mettait fin prématurément. Cela a maintenant pour résultat que notre nombre de sysdesend ne dépasse jamais quelques milliers (la plupart provient de l'utilisation de l'astuce 150).
Les curseurs dans les déclencheurs semblaient contenir plus de verrouillage que prévu (même avec statique, forward_only). la suppression de ceux-ci semble avoir rendu les verrous que nous voyons sur SEND CONVERSATION plus transitoires (ou du moins les temps que nous voyons sont beaucoup plus bas).
Nous exécutions essentiellement deux solutions côte à côte (le backend de la solution Service Broker (pour les tests sous charge de production)) et la solution actuelle (terrible requête qui s'étend sur de nombreuses tables).
En tant qu'avantage secondaire, cela a révélé un problème de nettoyage des enregistrements fantômes et bien qu'il ne soit pas sur les tables Service Broker (système ou file d'attente), il est assez répandu dans notre système et les symptômes correspondent très bien à notre "cause non claire" problèmes que nous rencontrons parfois. Une enquête est en cours à ce sujet, nous essayons de trouver les tables qui y contribuent et nous allons probablement juste reconstruire régulièrement leurs index.
Merci une fois de plus.
la source