شرکت مایکروسافت (
Microsoft) برای اولین بار در Sql Server 2005، ویژگی Service Broker را ارائه کرد که به اختصار SSSB هم خوانده میشود. با کمک Service Broker میتوانیم ارسال و دریافت پیام به صورت غیرهمزمان و تضمین شده را در یک یا چند دیتابیس متفاوت (حتی در سرور جداگانه) داشته باشیم. در این مقاله قصد داریم به ویژگیهای اصلی Service Broker بپردازیم. هدف اصلی Service Broker ایجاد قابلیت ارسال غیر همزمان پیامها (Asynchronous Message Queue) است که این تبادل پیام یا Message به صورت امن (Secure)، مطمئن (Reliable) و مقیاسپذیر (Scalable) صورت میپذیرد.
کاربرد Service Broker
برای درک بهتر این که Service Broker چیست؟ و چه کاربردی دارد، در ادامه با هم یک مثال ساده را بررسی میکنیم. یک سیستم ثبت سفارش را تصور کنید. وقتی کاربر اقدام به ثبت سفارش میکند، چندین فرآیند باید پشت سر هم انجام شود تا آن سفارش به صورت کامل ثبت شود. این فرایندها شامل درج سفارش، درج سند حسابداری، درج لاگ سفارش، ارسال ایمیل و پیامک جهت تایید سفارش و… است. انجام تمامی این فرایند در یک تراکنش به صورت همزمان میتواند باعث طولانی شدن فرایند ثبت سفارش شود در صورتی که میتوان یکسری از این فرایندها را به صورت غیرهمزمان انجام داد.
این کار باعث کارکرد و عملکرد بهتر در زمان ثبت سفارش میشود. در مثال ما ثبت سفارش و ثبت سند حسابداری باید به صورت همزمان اتفاق بیفتد ولی فرایندهای ثبت لاگ، ارسال پیامک و ایمیل میتوانند طی یک فرایند جداگانه و به صورت غیرهمزمان انجام شود. در این جا میتوان از Service Broker استفاده کرد.
اجزای مهم Service Broker
Service Broker از ۴ جزء مهم تشکیل شده است که سعی میکنیم هر کدام را به صورت جداگانه توضیح دهیم:
- Message types
- Contracts
- Queues
- Service program
نصب و کانفیگ Service Broker:
برای فعال سازی Service Broker از کوئری زیر استفاده کنید:
USE master
ALTER DATABASE HelloWorldServiceBroker SET ENABLE_BROKER;
GO
نکته ای که لازم است به آن توجه کنید، این است که فعال سازی Service Broker به ازای
دیتابیس انجام میشود.
برای دیدن فهرست دیتابیسهایی که Service Broker برای آنها فعال است، میتوانید از دستور زیر استفاده کنید:
USE master
select name,is_broker_enabled from sys.databases
GO
Message Types
ماهیت Service Broker، ارسال پیام بین سرویسهایی است که با هم صحبت میکنند. این پیامها همان رکوردهای ما و در واقع Message Type ها هستند. پیام دارای یک بدنه اصلی دارد که به صورت پیش فرض Var Binary است. در زمان ایجاد پیام، باید نام و قالب دیتا (DataType) را مشخص کنیم.
در حال حاضر Service Broker از ۴ قالب داده پشتیبانی میکند. برای ارسال پیام، میتوانیم از هر کدام از آنها استفاده کنیم که عبارتند از:
Well-formed XML
XML validated against a registered XML schema collection
No validation (e.g. for binary data)
Empty (the message body must be empty)
در مثال زیر، برای ارسال و دریافت پیامها دو Message Type از نوع xml درست کردیم. Message type با نام [Request Message] و نوع xml برای ارسال پیامها و Message Type دیگری با نام [Response Message] برای دریافت پیامها که همانند نوع پیام قبلی از xml استفاده کردیم.
Use HelloWorldServiceBroker
GO
CREATE MESSAGE TYPE
[RequestMessage]
VALIDATION = WELL_FORMED_XML
GO
CREATE MESSAGE TYPE
[ResponseMessage]
VALIDATION = WELL_FORMED_XML
قراردادها (Contracts)
service broker برای ارسال پیامها از منطق صف یا Queue استفاده میکند که برای تحقق این امر نیاز به یک قرارداد دارد. در این قرارداد مشخص میشود که آغازگر (Initiator) و دریافتکننده پیام (Target) کدام سرویس است.
تعریف Contract بخشهای مختلفی دارد که شامل موارد زیر است:
- Send By Initiator
- Send By Target
- Send By ANY
در مثال زیر، یک قرارداد با نام [HelloWorldContract] ایجاد کردیم که در آن (Request Message) ارسالکننده و (Response Message) دریافتکننده پیام خواهند بود. ارسالکننده را با Send By Initiator و دریافتکننده پیام را با Send By Target مشخص کردیم.
CREATE CONTRACT [HelloWorldContract]
(
[RequestMessage] SENT BY Initiator,
[ResponseMessage] SENT BY TARGET
)
صفها (Queues)
صف محل ذخیره پیامها در Service Broker است، شما میتوانید مانند جداول معمولی روی صف، کوئری select را اجرا کنید و از وضعیت صف با خبر شوید.
SELECT * FROM InitiatorQueue
در مثال زیر، براساس Initiator و Target دو صف ایجاد کردهایم که در آن پیامها توسط سرویس که در ادامه مقاله به آن اشاره خواهیم کرد، به صف هدایت میشوند.
CREATE QUEUE InitiatorQueue
WITH STATUS = ON
GO
CREATE QUEUE TargetQueue
WITH STATUS = ON
سرویس (Service)
اگر بخواهیم یک تعریف کلی و ساده از Service داشته باشیم، میتوان گفت وظیفه service هدایت پیامها به صف مورد نظر است. در واقع سرویس و صف به هم وابستگی دارند .هنگامی که Initiator یا Target پیامی را ارسال یا دریافت میکنند، سرویس پیامها را به صفهای مناسب هدایت میکند به طور مثال Initiator شروع به ارسال پیام میکند، سرویس، پیام را که از سمت Initiator ارسال شده است، به صف مورد نظری که در مثال ما Target Queue است، هدایت میکند و این فرایند تا زمان به پایان رسیدن مکالمه، ادامه خواهد یافت. در مثال زیر بر اساس هر کدام از صفهایی که در بالا ایجاد کردیم، سرویس تعریف شده است.
CREATE SERVICE Initiator Service
ON QUEUE Initiator Queue
(
[HelloWorldContract]
)
GO
CREATE SERVICE TargetService
ON QUEUE TargetQueue
(
[HelloWorldContract]
)
GO
در نهایت، پس از ایجاد زیر ساختهای اصلی Service Broker، آمادهایم که ارسال پیامها را شروع کنیم. این کار توسط BEGIN DIALOG CONVERSATION انجام میشود اما قبل از این کار اجازه دهید، یک جمع بندی سریع داشته باشیم از کارهایی که تا الان انجام دادهایم.
در ابتدا، در سطح دیتابیس Service Broker را فعال کردیم.
بعد از فعال کردن سرویس، message type با نوع xml را برای ارسال و دریافت پیامها تعریف کردیم.
یک قرار داد که مشخصکننده Initiator یا Target است را ایجاد کردیم .
در مرحله بعد، دو صف بر اساس Initiator یا Target برای ذخیره پیامها تعریف کردیم .
در انتها، دو سرویس برای هدایت پیامها به صفهای مورد نظر ایجاد کردیم.
مکالمات (Dialogue یا Conversations)
شروع فرایند ارسال پیام با دیالوگ انجام میشود. مفهوم دیالوگ بسیار ساده است. یک آغازکننده ارسال پیام، یک دریافتکننده پیام و در نهایت تایید دریافت پیام و پایان دیالوگ. در service broker برای آغاز ارسال پیام، نیاز به Begin Dialog Conversation است که شامل یک سرویس آغازگر (Initiator)، سرویس مقصد (Target) و همچنین قرارداد است. در صورت تمایل، شما میتوانید تعیین کنید که آیا از رمزگذاری استفاده شود یا خیر. در حال حاضر ما برای سادهسازی فرایند چیزی را رمزگذاری نمیکنیم.
پیگیری پیام بین سرویسها توسط یک UNIQUEIDENTIFIER انجام میشود. در مثال زیر، یک دیالوگ ایجاد کردهایم:
BEGIN TRANSACTION ;
DECLARE @ch UNIQUEIDENTIFIER
DECLARE @msg NVARCHAR(MAX) ;
BEGIN DIALOG CONVERSATION @ch
FROM SERVICE [InitiatorService]
TO SERVICE 'TargetService'
ON CONTRACT [HelloWorldContract]
WITH ENCRYPTION = OFF ;
SET @msg = '<HelloWorldRequest>
Send message hello
</HelloWorldRequest>' ;
SEND ON CONVERSATION @ch
MESSAGE TYPE [RequestMessage]
(@msg) ;
COMMIT TRANSACTION
GO
قبل از این که سراغ مرحله بعد برویم، بهتر است بر روی Queue دستور select را اجرا کنیم:
select * from TargetQueue
همانطور که در خروجی مشاهده میکنید، یک رکورد در صف وجود دارد، این رکورد همان پیامی است که توسط دستورات بالا ایجاد و در صف قرار گرفته است.
پس از ارسال پیام از سمت آغازگر، برای دریافت و پردازش پیام میتوان از عبارت Receive استفاده کرد. در این مرحله، از صف Target Queue پیام ارسال شده خوانده و پردازش میشود و سپس جواب آن به صف Initiator ارسال میشود.
DECLARE @ch UNIQUEIDENTIFIER
DECLARE @messagetypename NVARCHAR(256)
DECLARE @messagebody XML
DECLARE @responsemessage XML
BEGIN TRANSACTION ;
RECEIVE TOP(1)
@ch = conversation_handle,
@messagetypename = message_type_name,
@messagebody = CAST(message_body AS XML)
FROM TargetQueue
PRINT 'Conversation handle: ' + CAST(@ch AS NVARCHAR(MAX))
PRINT 'Message type: ' + @messagetypename
PRINT 'Message body: ' + CAST(@messagebody AS NVARCHAR(MAX))
IF ( @messagetypename = RequestMessage' )
BEGIN
-- Construct the response message
SET @responsemessage = '<HelloWorldResponse>Hello World, '
+ @messagebody.value('/HelloWorldRequest[1]', 'NVARCHAR(MAX)')
+ '</HelloWorldResponse>' ;
-- Send the response message back to the initiating service
SEND ON CONVERSATION @ch MESSAGE TYPE [ResponseMessage] (@responsemessage) ;
-- End the conversation on the target's side
END CONVERSATION @ch ;
END
COMMIT TRANSACTION
GO
بعد از اجرا کوئری بالا، میتوانید دستور select * from InitiatorQueue را برای مشاهده وضعیت صف اجرا کنید.
DECLARE @ch UNIQUEIDENTIFIER
DECLARE @messagetypename NVARCHAR(256)
DECLARE @messagebody XML
BEGIN TRANSACTION ;
RECEIVE TOP (1)
@ch = conversation_handle,
@messagetypename = message_type_name,
@messagebody = CAST(message_body AS XML)
FROM InitiatorQueue
IF ( @messagetypename = ‘ResponseMessage' )
BEGIN
PRINT 'Conversation handle: ' + CAST(@ch AS NVARCHAR(MAX))
PRINT 'Message type: ' + @messagetypename
PRINT 'Message body: ' + CAST(@messagebody AS NVARCHAR(MAX))
END
IF ( @messagetypename = 'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog' )
BEGIN
-- End the conversation on the initiator's side
END CONVERSATION @ch ;
END
COMMIT TRANSACTION
GO
جمعبندی
در پاسخ به سوال Service Broker چیست؟ میتوان گفت، Service Broker یک ویژگی قدرتمند و کاربردی است که در sql server 2005 معرفی شده است. این ویژگی به ما کمک میکند تا یک سری از فرایندها را به صورت Asynchronous (غیر همزمان ) انجام دهیم که بهترین مثال برای این موضوع ارسال ایمیل یا پیامک است. در این مقاله ما تعریف، کاربرد و اجزای، نمونه کد و مثال Service Broker با هم بررسی کردیم.
دیدگاهتان را بنویسید