Nous avons récemment identifié un problème avec l'une de nos bases de données où suite à une configuration 'fire & forget' (ie les conversations étant fermées immédiatement après l'envoi), notre table sys.conversation_endpoints se remplissait de messages DI / DISCONNECTED_INBOUND. Cela a finalement débordé dans le tempDB, l'amenant à se développer énormément et à manger de l'espace disque précieux. Nous avons finalement résolu ce problème en commentant la ligne
END CONVERSATION @handle WITH CLEANUP
dans notre envoi de SP et la fermeture des conversations dans notre SP de réception en utilisant le même code,
END CONVERSATION @handle WITH CLEANUP
Cependant, nous avons maintenant un nouveau problème. Depuis le déplacement des servers (et la migration de SQL Server 2005 vers SQL Server 2008), nous avons récemment découvert que sys.conversation_endpoints est maintenant rempli de messages CO / CONVERSING, indiquant que les conversations ne sont pas fermées. Le SP destinataire les ferme, ou au less exécute la command pour le faire, donc je ne comprends pas d'où viennent ces messages.
J'ai essayé de revenir à la fin de la conversation au moment de l'envoi, mais cela n'a aucun effet. Est-ce mal de mettre fin aux conversations sur la réception en utilisant WITH CLEANUP
? Ou y a-t-il un autre problème?
Cet article sur techtarget semble suggérer qu'il s'agit d'un bug, et que l'exécution d'un travail pour nettoyer les rests est la seule solution …
MISE À JOUR: Pawel a souligné ci-dessous que je devrais éviter le model Fire & Forget, et j'ai ajouté un SP activé à la queue initiateur pour mettre fin à toutes les conversations. Cependant, sys.conversation_endpoints est encore en train de se remplir, cette fois avec des messages CD / CLOSED. Voici la structure de mes files d'attente
Send_SP:
DECLARE @h UNIQUEIDENTIFIER BEGIN DIALOG CONVERSATION @h FROM SERVICE 'InitiatorQueue' TO SERVICE 'TargetQueue' ON CONTRACT 'MyContract' WITH ENCRYPTION = OFF; SEND ON CONVERSATION @h MESSAGE TYPE 'MyMessage' (@msg)
Receive_SP (SP activé sur TargetQueue)
DECLARE @type SYSNAME, @h UNIQUEIDENTIFIER, @msg XML; DECLARE @target TABLE ( [message_type_name] SYSNAME, [message_body] VARBINARY(MAX), [conversation_handle] UNIQUEIDENTIFIER ) WHILE(1=1) BEGIN TRANSACTION WAITFOR(RECEIVE TOP (1000) [message_type_name],[message_body],[conversation_handle] FROM TargetQueue INTO @target), TIMEOUT 2000 IF(@@rowcount!=0) BEGIN WHILE((SELECT count(*) FROM @target) > 0) BEGIN SELECT TOP (1) @type = [message_type_name], @msg = [message_body], @h = [conversation_handle] FROM @target; // Handle Message Here END CONVERSATION @h; DELETE TOP (1) FROM @target; END END COMMIT TRANSACTION;
End_SP (SP activé sur InitiatorQueue)
DECLARE @type SYSNAME, @h UNIQUEIDENTIFIER, @msg XML; DECLARE @init TABLE ( [message_type_name] SYSNAME, [message_body] VARBINARY(MAX), [conversation_handle] UNIQUEIDENTIFIER ) WHILE(1=1) BEGIN TRANSACTION WAITFOR(RECEIVE TOP (1000) [message_type_name],[message_body],[conversation_handle] FROM InitiatorQueue INTO @init), TIMEOUT 2000 IF(@@rowcount!=0) BEGIN WHILE((SELECT count(*) FROM @init) > 0) BEGIN SELECT TOP (1) @type = [message_type_name], @msg = [message_body], @h = [conversation_handle] FROM @init; END CONVERSATION @h; DELETE TOP (1) FROM @init; END END COMMIT TRANSACTION;
L'utilisation du model fire-and-forget conduira inévitablement à ceci et à d'autres types de problèmes. De plus, toutes les erreurs hypothétiques passeront inaperçues. Y a-t-il une raison pour laquelle vous ne pouvez pas changer le model d'échange de messages pour que la cible émette END CONVERSATION (sans nettoyage!) Une fois qu'il reçoit un message et que l'initiateur appelle seulement END CONVERSATION (encore, sans nettoyage) de la cible?