I'm considering filing a bug on Connect about this, but I thought I'd post here first and see if I can get an answer...
Following is the script I'm using to test:
Setup / Window #1
--
CREATE DATABASE SimpleSSB
GO
USE SimpleSSB
GO
--Create a database master key
CREATE MASTER KEY
ENCRYPTION BY PASSWORD = 'onteuhoeu'
GO
--Create a message type
CREATE MESSAGE TYPE Simple_Msg
VALIDATION = EMPTY
GO
--Create a contract based on the message type
CREATE CONTRACT Simple_Contract
(Simple_Msg SENT BY INITIATOR)
GO
--create a queue
CREATE QUEUE Simple_Queue
GO
--Create a service
CREATE SERVICE Simple_Service
ON QUEUE Simple_Queue
(Simple_Contract)
GO
--
Go start the other windows now
Readers: Windows #2-n
--
USE SimpleSSB
GO
WAITFOR
(
RECEIVE *
FROM Simple_Queue
), TIMEOUT 300000
--
Start at least two readers, then do
--
--send a message...
DECLARE @.h UNIQUEIDENTIFIER
BEGIN DIALOG CONVERSATION @.h
FROM SERVICE Simple_Service
TO SERVICE 'Simple_Service'
ON CONTRACT Simple_Contract
WITH ENCRYPTION=OFF;
SEND ON CONVERSATION @.h
MESSAGE TYPE Simple_Msg
GO
--
... the last reader you've started will pick up the message first. Note I'm testing on 9.0.3033, in case that matters.
Thanks!
Hi Adam,
The bevior you see is intentional. The purpose is to allow activated tasks to exit after a spike.
Suppose a traffic spike happens and suddenly all queue readers are activated to drain the queue. After the queue is drained, ideally the extra readers should go away. If we'd honor the longest waiting, then potentially all queue readers will stay active because each one will eventually get a message before the WAITFOR times out. With the behavior you see one reader will steal all messages, causing the other activated tasks to time out and exit. The same thinking goes for external readers as well.
HTH,
~ Remus
Thanks for the response. I agree that the behavior you're describing makes sense for activation, but in the scenario I'm working on--a farm of readers waiting on messages--it doesn't really work. I want to balance the activity across the farm so if one reader is working, the one waiting the longest will be the next to pick up a message. Any ideas?
Thanks,
Adam|||
You can't change the way WAITFOR(RECEIVE...) is notified.
If a reader is working, then it won't have any RECEIVE posted, so any available work will go to the next reader. The existing mode of operation will cause the first machine in the farm to take any load up to it's max capacity, then the next machine start picking up load until it max out, then the next and so on. What you describe would cause all machines to take an even workload and all grow simultanously until they all reach the max. Why is the first described behavior unacceptable?
An alternative to consider would be to use the broker built-in load balancing capabilities. If the same service is declared in multiple databases, then dialog targeting the said service will spread evenly across all instances of the service. Maybe you can use this feature to spread the workload.
HTH,
~ Remus
|||Hi Remus,
The reason it's unacceptable is that the readers in this case will be doing other work in addition to processing the queues. Basically, the scenario I'm working with right now is an application that already uses a load balanced server farm for doing some work, and the idea is to add some additional functionality queued via SSB. Obviously since the farm is already balanced it would be nice to also balance the SSB stuff--otherwise the "first" server in the farm is going to overload and not be able to handle the rest of its duties.
I was not aware of the load balancing feature you mention... I'll try it out and see how it fits into the scenario.
Thanks again! Your replies have been very helpful.
Adam
No comments:
Post a Comment