powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Service Broker, MESSAGE TYPE VALIDATION через XSD
24 сообщений из 24, страница 1 из 1
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991384
Tketano
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привествую всех!

Вопрос по очередям Service Broker. Для очереди был определен специальный тип сообщений с контролем по XSD:
Код: sql
1.
CREATE MESSAGE TYPE MSG	VALIDATION = VALID_XML WITH SCHEMA COLLECTION XSD_DOC;



Однако данная очередь без проблем "жрет" пустые сообщения (пустая строка) и при этом говорит, что сообщение валидно. При этом прямая конвертация тела сообщения в процедуре активации завершается ошибкой:
Код: sql
1.
DECLARE  @XML_MESSAGE xml (DOCUMENT XSD_DOC) = @MESSAGE_BODY



В чем прикол? Какие еще нюансы есть при использовании VALID_XML WITH SCHEMA COLLECTION ?

Допонительный вопрос - как через MSSMS удалять конкретные сообщения из очереди?
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991394
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tketano,

коллекцию схем в студию
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991403
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а сорян невнимательно прочитал вопрос.

Да есть такой нюанс, пустой xml не запускает валидацию по схеме

у вас даже инструкция вида
Код: sql
1.
declare @x xml(XSD_DOC) = '';



должна нормально отработать.

точнее смотрите как: валидации есть два вида content и document
вот в случае
declare @x xml(xsd_doc) = ''; используется content validation которая разрешает пустой элемент
declare @x xml(document xsd_doc) = ''; используется document validation которая проверяет что бы в теле был именно валидный документ.

в случае валидации service broker используется content validation
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991408
Tketano
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff,

При использовании типизированного xml такого поведения не замечал. Конструкция вида
Код: sql
1.
declare @x xml(DOCUMENT XSD_DOC) = '';

возвращает ошибку "Проверка XML: экземпляр XML должен быть документом". Но я кажись понял в чем проблема... в типизированном xml указан DOCUMENT, т.е.ровно 1 элемент верхнего уровня. А при создании типа сообщения указать данных флаг возможности нет. В этом случае пустая строка естественно валидна.
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991412
Tketano
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff,

Ага, спасибо, тоже допер. Важный нюанс. Получается может прилететь много сообщений в одном при такой валидации. Может тогда откажусь от XSD в пользу well formed xml )) Все равно потом типизируется документ.
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991413
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tketano,

вы лучше вообще откажитесь от валидации типа, пусть будет разрешена validation = none.
а валидацию будуте производить непосредственно перед отправкой на инициаторе или после получения на таргете сами.

использование validation отличной от none - несколько нагружает очередь, при больших объемах сообщений это становится заметно.
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991420
Tketano
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff,

Сейчас подумаю над типизацией сообщений, хорошо.

Дополнительный вопрос. Что за особенное поведение у очереди, если в нее подпадает сообщение с телом NULL? Ошибка при отправке естесвенно появляется, однако сообщение в очереди так же оказывается. И далее сваливается процедура активации (где вроде бы есть попытка отловить этот NULL).
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991427
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tketano,

это в какой это ситуации у вас разрешается тело null?
оно может быть быть только в двух случаях:

1)тело сообщения обязано быть null если validation на message_type = EMPTY;
2) тело сообщения может быть null если при инструкции send не указывать содержимое
аля
Код: sql
1.
send on conversation @h;
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991432
Tketano
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff,

В том то и дело, что null не разрешено. Тестирую очередь на сбои. При попытке вставить null выдается сообщение "Тело сообщения не может быть равно NULL. Допустимо использование имеющей нулевую длину строки в Юникоде или двоичной строки". Однако само сообщение попадает в очередь с пустым телом ('') и после этого очередь сваливается. После того, как включил VALIDATION = NONE проблема вроде ушла. Ну понятно почему.
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991435
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tketano,

если валидацию выполнять на принимающей стороне, то контроль ошибок становится проще.
WITH SCHEMA COLLECTION XSD_DOC используют, если принимающая сторона нам недоступна, то есть мы должны гарантировать внешней системе, что передали то, что они хотят.
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991453
Tketano
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Владислав Колосов,

Ну контролировать мне все равно где. Хотел облегчить себе жизнь, а как будто усложнил. Моя задача сейчас сделать очередь максимально отказоустойчивой. Положили в нее левое сообщение - ну ок, сформируем ответ, что валидацию не прошло. Главное чтобы очередь не останавливалась. На VALID_XML WITH SCHEMA часто выключается при попытке отправить кривое сообщение.

В данном случае я - принимающая сторона, а внешние системы в этот сервис отправляют запросы.
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991663
Tketano
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Tketano,

Убрал валидацию по умолчанию. Решилась одна проблема, появилась новая. Процедура активации стандартная, предлагаемая BOL:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
WHILE ( 1 = 1 )
	BEGIN
		BEGIN TRANSACTION;

		WAITFOR
		(
			RECEIVE TOP (1)
					@CONVERSATION_HANDLE = [conversation_handle],
					@MESSAGE_BODY = CAST(message_body as nvarchar(max)),
					@MESSAGE_TYPE = message_type_name
			FROM API_PROCESSING_QUEUE
		), TIMEOUT 5000;

		IF @@ROWCOUNT = 0
		BEGIN
			ROLLBACK TRANSACTION;
			BREAK;
		END
 
		IF @MESSAGE_TYPE = 'MY_MESSAGE'
		BEGIN
			EXEC dbo.DO_SOMETHING
						@MESSAGE = @MESSAGE_BODY,
						@REPLY = @REPLY OUTPUT;

			--	--------------------------------------------------
			--	Формируем ответ
			--	--------------------------------------------------
			SEND ON CONVERSATION @CONVERSATION_HANDLE
			MESSAGE TYPE [MSG_OUTPUT] ( @REPLY);
		END
 
		--	Завершение диалога
		ELSE IF @MESSAGE_TYPE = N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'
		BEGIN
			END CONVERSATION @CONVERSATION_HANDLE;
		END
 
		--	Ошибка
		ELSE IF @MESSAGE_TYPE = N'http://schemas.microsoft.com/SQL/ServiceBroker/Error'
		BEGIN
			END CONVERSATION @CONVERSATION_HANDLE;
		END
 
		COMMIT TRANSACTION;
	END



Валидация схемой внутри dbo.DO_SOMETHING происходит следующим кодом:
Код: sql
1.
2.
3.
4.
5.
BEGIN TRY
 DECLARE @XML_DOC xml (DOCUMENT XSD_DOC) = @MESSAGE
END TRY
BEGIN CATCH
...



Валидация происходит корректно. Однако исключение рушит внешнюю транзакцию из процедура активации и команда COMMIT TRAN выполняется с ошибкой (нельзя зафиксировать транзакцию). Пробовал добавить анализ XACT_STATE() ( если = -1, то откат). Но тогда под откат попадает и контрукция SEND ON CONVERSATION. В общем блуждаю в трех соснах. Если убрать все транзакции в процедуре активации, то работать начинает.
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991668
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tketano,

сообщение
Код: sql
1.
N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'


специально не надо отправлять, его отсылает команда
Код: sql
1.
END CONVERSATION @CONVERSATION_HANDLE;



Забираете из очереди, если это шпионское сообщение, то машете в ответ рукой и закрываете диалог. Если прилетела с той стороны ошибка и ее нет интереса обрабатывать, то тоже машете рукой. Свои сообщения обрабатываете. Передающая сторона вам ошибку врят ли пришлёт.

А вот это: BEGIN TRANSACTION; приедет к интересному результату. Если в процессе валидации будет выброшено исключение, то транзакция откатится и сообщение останется в очереди. После пятого отката очередь остановится в случае включения параметра обработки отравленных/токсичных сообщений. Причем, неважно на каком уровне стека выполнения процедур произойдет откат. Даже если это откат, обработанный через try-catch.

Чтобы ловить ошибки и не повторять проверку одного и того же сообщения, "отравленное" сообщение после отката необходимо извлекать из очереди или отказаться от использования транзакции.
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991672
Tketano
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Владислав Колосов,

Владислав Колосовсообщение
N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'

специально не надо отправлять, его отсылает команда
END CONVERSATION @CONVERSATION_HANDLE;
Я, честно говоря, таких сообщений в очереди не видел и теоретически не понимаю откуда оно может там взяться. Как и писал выше, использовал шаблон обработки microsoft по умолчанию, где обрабатывается Error и EndDialog в явном виде.

Владислав КолосовА вот это: BEGIN TRANSACTION; приедет к интересному результату. Если в процессе валидации будет выброшено исключение, то транзакция откатится и сообщение останется в очереди. После пятого отката очередь остановится в случае включения параметра обработки отравленных/токсичных сообщений. Причем, неважно на каком уровне стека выполнения процедур произойдет откат. Даже если это откат, обработанный через try-catch.
Да, все именно так и происходит по логу. Сообщение неудовлетворяющее XSD схеме является в данном коде токсичным и после 5-ти попыток его обработки очередь просто отключается и весь сервис падает.

Владислав КолосовЧтобы ловить ошибки и не повторять проверку одного и того же сообщения, "отравленное" сообщение после отката необходимо извлекать из очереди или отказаться от использования транзакции.

Вот тут самое непонятное. Почему не отрабатывается примерно следующий код?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
EXEC dbo.DO_SOMETHING
	@MESSAGE = @MESSAGE_BODY,
	@REPLY = @REPLY OUTPUT;

-- Транзакция подлежит откату
IF XACT_STATE() = -1
BEGIN
	ROLLBACK TRAN;
END;

--	--------------------------------------------------
--	Формируем ответ
--	--------------------------------------------------
SEND ON CONVERSATION @CONVERSATION_HANDLE
MESSAGE TYPE [MSG_OUTPUT] ( @REPLY);


После данного кода сообщение не удаляется из очереди, хотя мы в явном виде вызвали ROLLBACK и только после этого вызвали конструкцию SEND ON CONVERSATION. Неужели надо повторно выбирать данное сообщение из очереди (RECEIVE)?

А какие опасности отказа от транзакции в активирующей процедуре? Без нее есть риск при некорректной обработке сообщения (или сбоя) потерять сообщение в принципе?
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991681
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tketano,

в do_something отключите xact_abort, что бы у вас транзакция не принимала uncommitable state

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
create or alter procedure [dbo].[do_something]
     @msg varchar(max)
as
if @@options & 16384 = 16384 set xact_abort off;

begin try
    declare @x xml (document xsd) = @msg;
end try
begin catch
    --something to log errror
end catch;
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991725
Tketano
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff,

Попробовал. Транзакция все равно сваливается в нефиксируемое состояние. Пробовал следующим примером:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
create procedure [dbo].[do_something]
     @msg varchar(max)
as
if @@options & 16384 = 16384 set xact_abort off;

begin try
    declare @x xml (document XSD_DOC) = @msg;
end try
begin catch
end catch;
go

begin tran;
exec dbo.do_something
	@msg = '123'

select XACT_STATE()		-- будет равно -1
commit tran;


Как итог стандартная ошибка:
Код: sql
1.
2.
3.
4.
Сообщение 3930, уровень 16, состояние 1, строка 10
Текущая транзакция не может быть зафиксирована и не может поддерживать операции, производящие запись в файл журнала. Выполните откат транзакции.
Сообщение 3998, уровень 16, состояние 1, строка 1
Нефиксируемая транзакция обнаружена в конце пакета. Был выполнен откат транзакции.
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991726
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tketano,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
BEGIN TRY
BEGIN TRAN

RECEIVE TOP (1) ....

.....

EXEC dbo.DO_SOMETHING
	@MESSAGE = @MESSAGE_BODY,
	@REPLY = @REPLY OUTPUT;

COMMIT
END TRY
BEGIN CATCH
  ID @@trancount > 0
	ROLLBACK TRAN; /*откат может выполнить процедура*/

        RECEIVE TOP (1) ..... /*изъять токсичное сообщение*/
        EXEC dbo.WRITE_LOG /*записать себе в журнал ошибок*/
END;

END CONVERSATION @handle
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991741
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tketano,

авторЯ, честно говоря, таких сообщений в очереди не видел и теоретически не понимаю откуда оно может там взяться.

Моя вина, невнимательно посмотрел. Показалось, что сообщение отправляется в очередь.
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39991855
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tketano,

а да, согласен ошибка проверке по схеме вызывает исключение которое приводит к откату транзакции и в случае с xact_abort off к нефиксируемуму состоянию.

ну тогда здесь как вариант решения использовать "автономную транзакцию" через петлю линкованного сервера.

то есть валидацию проводите в виде процедуры
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
create or alter procedure [dbo].[xml_validate]
         @xml xml,
         @schema sysname
as
if @@options & 512 = 0 set nocount on;

declare @r int = 0;

begin try
     declare @stmt nvarchar(max) = FORMATMESSAGE('declare @x xml (DOCUMENT %s) = @xml', @schema);
     exec sp_executesql
         @stmt = @stmt,
         @params = N'@xml xml',
         @xml = @xml;
end try
begin catch
     set @r = ERROR_NUMBER();
end catch;

return @r;




и типа валидацию производить вида
Код: sql
1.
2.
3.
4.
5.
6.
declare @r int = 0;
exec @r = [LOOPBACK].[basename].[dbo].[xml_validate]
       @xml  =@xml,
       @schema = 'XSD_DOC';

if @r in (6908, 6913) --do some log actions
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39997028
Tketano
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Владислав Колосов, felix_ff Спасибо! Был занят переделкой лога и изменением валидации сообщений в очереди.

Новый вопрос. Почему conversation_handle после инструкции BEGIN DIALOG не совпадает со значением conversation_handle в очереди? В чем прикол? При том, что значения крайне похоже и, судя по всему, отличаются всего на тройку байт:

Код: sql
1.
2.
3.
4.
5.
--7D7B61A3-ADF2-EA11-A472-6CF0495233B0 (BEGIN DIALOG)
--7A7B61A3-ADF2-EA11-A472-6CF0495233B0 (QUEUE)

--C135F003-AEF2-EA11-A472-6CF0495233B0 (BEGIN DIALOG)
--C435F003-AEF2-EA11-A472-6CF0495233B0 (QUEUE)



Задача после BEGIN DIALOG записать в лог присвоенный conversation_handle (для отладки сообщений очереди).
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39997039
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tketano,

вы не учитываете тот факт что у вас conversation_handle от инструкции begin dialog conversation это хэндл отправляющей стороны


а в очереди лежит хэндл принимающей стороны .

если посмотрите в sys.conversation_endpoints вот так то поймете:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
declare @h uniqueidentifier;

begin dialog conversation @h
from service [s] to service 'r'
with encryption = off;

send on conversation @h ('hello');

declare @dialog_id uniqueidentifier;
select @dialog_id = [conversation_id] from sys.conversation_endpoints where [conversation_handle] = @h;

select e.[conversation_id] as [dialog_id], e.[conversation_handle], e.[is_initiator], s.[name] as [local_service], e.[far_service]
from sys.conversation_endpoints e
      left join sys.services s on s.[service_id] = e.[service_id]
where e.[conversation_id] = @dialog_id;
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39997080
Tketano
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff,

Так, так, так... ну приехали)) Еще один сюрприз)

После инструкции BEGIN DIALOG можно узнать CH принимающего сервиса? Необходимо зафиксировать его в логе, чтобы в случае сваливания принимающей очереди разобраться что с чем связано. Судя по всему в sys.conversation_endpoints для обоих сообщений одниковый conversation_id...
Возможно, это странный подход, не отрицаю)
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39997097
Tketano
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Tketano
felix_ff,

Так, так, так... ну приехали)) Еще один сюрприз)

После инструкции BEGIN DIALOG можно узнать CH принимающего сервиса? Необходимо зафиксировать его в логе, чтобы в случае сваливания принимающей очереди разобраться что с чем связано. Судя по всему в sys.conversation_endpoints для обоих сообщений одниковый conversation_id...
Возможно, это странный подход, не отрицаю)


Ну типа такого варианта (не уверен в нем):
Код: sql
1.
2.
3.
4.
SELECT	@CONVERSATION_HANDLE_TO = [conversation_handle]
FROM	sys.conversation_endpoints
WHERE	far_service	= @TO_SERVICE	AND
	conversation_id = ( select conversation_id from sys.conversation_endpoints where  [conversation_handle] = @CONVERSATION_HANDLE_FROM )
...
Рейтинг: 0 / 0
Service Broker, MESSAGE TYPE VALIDATION через XSD
    #39997110
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tketano
Tketano
felix_ff,

Так, так, так... ну приехали)) Еще один сюрприз)

После инструкции BEGIN DIALOG можно узнать CH принимающего сервиса? Необходимо зафиксировать его в логе, чтобы в случае сваливания принимающей очереди разобраться что с чем связано. Судя по всему в sys.conversation_endpoints для обоих сообщений одниковый conversation_id...
Возможно, это странный подход, не отрицаю)


Ну типа такого варианта (не уверен в нем):
Код: sql
1.
2.
3.
4.
SELECT	@CONVERSATION_HANDLE_TO = [conversation_handle]
FROM	sys.conversation_endpoints
WHERE	far_service	= @TO_SERVICE	AND
	conversation_id = ( select conversation_id from sys.conversation_endpoints where  [conversation_handle] = @CONVERSATION_HANDLE_FROM )



немного не так. для точки получателя far_service будет имя сервиса отправителя. поэтому вот так:
Код: sql
1.
2.
3.
4.
5.
6.
declare @h uniqueidentifier

select e2.[conversation_handle]
from sys.conversation_endpoints e1
    join sys.conversation_endpoints e2 on e2.[conversation_id] = e1.[conversation_id] and e2.[far_service] = N'initiator_service_name'
where e1.[conversation_handle] = @hж
...
Рейтинг: 0 / 0
24 сообщений из 24, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Service Broker, MESSAGE TYPE VALIDATION через XSD
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]