Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion Groups
DB Engine
SQL ServerMSDESQL Server CE
Services
Analysis (Data Mining)Analysis (OLAP)DTSIntegration ServicesNotification ServicesReporting Services
Programming
CLRConnectivitySQLXML
Other Technologies
ClusteringEnglish QueryFull-Text SearchReplicationService Broker
General
Data WarehousingPerformanceSecuritySetupSQL Server ToolsOther SQL Server Topics
DirectoryUser Groups
Related Topics
MS AccessOther DB ProductsMS Server Products.NET DevelopmentVB DevelopmentJava DevelopmentMore Topics ...

SQL Server Forum / Other Technologies / Service Broker / July 2006

Tip: Looking for answers? Try searching our database.

Conversation Groups

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Ramiro Calderón Romero - 04 Jul 2006 17:40 GMT
Hi all,

I'm having this scenario: A client service sends a message to a router
service which, according to some business rules, determines an actual
processor service. Since those rules are quite complex I decided to host it
inside a Win Service, which on its start method sets up several threads
listening the router service's incoming queue. with the following code:

private static void ConfigThreads()
{
int threadCount = GetThreadCount();
for (int i = 0; i < hilos; threadCount)
{
 ThreadPool.QueueUserWorkItem(new WaitCallback(SetUpListener), null);
}
}

private static void SetUpListener(object context)
{
using (SqlConnection con = GetConnection())
{
 con.Open();
 string serviceName = GetRoutingServiceName();
 RouterService router = new RouterService(serviceName, con);
 service.WaitforTimeout = TimeSpan.FromSeconds(-1);
 service.FetchSize = 1;
 service.Run(true, con, null);
}
}

Inside de DispatchMethod of the RouterService I wrote:

.....................
ProcessorService svc = new ProcessorService(GetRoutingServiceName(), con);
svc.WaitForTimeOut = GetTimeOut();
Conversation conv = svc.BeginDialog(GetProcessingService(), null,
mensaje.ContractName, TimeSpan.FromMinutes(5), true, null, con, tran);
using (Stream streamBody = new MemoryStream(Encoding.UTF8.GetBytes(body)))
{
Message msgCopy = new Message(originalMessage.Type, streamBody);
conv.Send(mensajeNuevo, con, tran);
tran.Commit();
}
tran = con.BeginTransaction();
if (svc.GetConversation(conv, con, tran) == null)
{
response = new Response("Processing")
}
else
{
Message msgResponse = conv.Receive();
if (msgRespuesta.Body != null)
{
 using (StreamReader reader = new StreamReader(msgRespuesta.Body))
 {
  string xmlResp = reader.ReadToEnd();
  resp =
(RespuestaPeticion)SerializationUtil.GetObject<responseType>(xmlResp);
  originalMessage.Conversation.End(con, tran);
 }
}
RegistrarDepuracion("Mensaje deserializado desde el servicio remoto
conversacion {0}", conv.Handle);
}
tran.Commit();
....................

The thing is while this code is waiting for the response from de processing
service ("if (svc.GetConversation(conv, con, tran) == null)") some other
thread in the pool process the response message leading to a "message
starving", so all the clients are getting the "processing" response message.
I don´t understand why the other thread reads the response message since the
original thread hasn't finished its operation (it is inside the service::run
method which RECEIVE'S command transaction hasn't commited yet) and
therefore its conversation group should be locked.  A workaround to this
issue is to have another service/queue pair dedicated only to receive the
response messages with no thread/readers associated.

Any advice would be greatly appreciated,I'm not sure what am I missing here.

Regards,

Ramiro Calderon
Roger Wolter[MSFT] - 05 Jul 2006 00:09 GMT
A couple things to keep in mind:
1)  Service Broker does Asynchronous processing so send out a message and
then waiting for a response on the same thread loses all the advantages that
asynchronous processing gives you by changing the asynchronous programming
model into a synchronous model.  The advantage of the Service Broker
reliable messaging is that it works even if the response isn't returned for
a week or so.  In your code, you would have a thread hung for a week in this
case.  The right thing to do is to have a process that sends messages out
and another one that receives responses.  You can use the conversation group
id or conversation handle to correlate the sent messages.with the responses.

2)  You do a send and then a GetConversation.  GetConversation will get you
the next conversation that has a message available on the queue which in all
probability is not the same conversation you did the send on.  If you want
to get the reply on the same conversation as the send you will have to do a
receive with a where clause to specify the conversation but as I said above,
this isn't a good use of Service Broker.  GetConversationGroup really
doesn't do anything other than waste a network round trip.  It is intended
or use in stored procedures to allow you to get the conversation state
before you do a receive.  Since you are not doing this, GetConversationGroup
is a waste of time.
Signature

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm

> Hi all,
>
[quoted text clipped - 81 lines]
>
> Ramiro Calderon
Ramiro Calderón Romero - 05 Jul 2006 01:03 GMT
Hi Roger,

Let me ellaborate a little bit:

> 1)  Service Broker does Asynchronous processing so send out a message and
> then waiting for a response on the same thread loses all the advantages
[quoted text clipped - 6 lines]
> the conversation group id or conversation handle to correlate the sent
> messages.with the responses.

The reason why I am sending out the message and wait for a response on a
same thread is becase we want some Sync/Async approach. I mean, I do wait
for the response in a given amount of time (configured in the
Service::WaitForTimeOut property); if in such time frame the remote system
responds I will return that answer; if not, I will return some sort of
"Working...." response. So, the thread will wait at most the WaitForTimeOut
property.

> 2)  You do a send and then a GetConversation.  GetConversation will get
> you the next conversation that has a message available on the queue which
[quoted text clipped - 6 lines]
> get the conversation state before you do a receive.  Since you are not
> doing this, GetConversationGroup is a waste of time.

2) I used GetConversation because it is the way that it is done in the
samples provided in the documentation, but you actually have a point here
that I haven't realized. I'll optimize the code so that the first round-trip
to the server would be avoided.

I already solved the problem of my first post by decoupling the receive
service from the sending service; but I already don't get completely why the
conversation locking allows other thread to read a message from a locked
conversation group.

Thanks for your guidance!!

Regards,

Ramiro

>A couple things to keep in mind:
> 1)  Service Broker does Asynchronous processing so send out a message and
[quoted text clipped - 106 lines]
>>
>> Ramiro Calderon
Roger Wolter[MSFT] - 05 Jul 2006 07:17 GMT
It doesn't allow a message to be received from a locked conversation group
but the conversation group you did the SEND on was unlocked as soon as you
committed the SEND transaction.  If you specify the ConversationHaandle in a
the receive where clause to be the same as the one you did the send on you
will have a much better chance of locking the conversation group you want
but there's still a chance that another thread will grab the lock before you
get to the receive call.

Signature

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm

> Hi Roger,
>
[quoted text clipped - 156 lines]
>>>
>>> Ramiro Calderon
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.