All articles

Gondolatok a queue alapú kliens-szerviz kommunikációhoz

Published 2011-06-16 - Last modified 2011-06-16

Original: https://soci.hu/blog/index.php/2011/06/16/gondolatok-a-queue-alapu-kliens-szerviz-kommunikaciohoz/

Az előző post kommentjei alapján (amit nagyon köszönök mindenkinek) nem kaptam sok bátorítást az aszinkron, queue alapú, kérés-választ különválasztó gazdag kliens – szerviz kommunikációhoz, úgy tűnik senki nem csinált ilyet, így nem akarok úttörő lenni a témában.
Ehhez még hozzájárul, hogy hétvégén méregettem az MSMQ teljesítményét. Azért ezt, mert a WCF is erre épít, és pl. az NServiceBus is.

A tesztkód 1.5kByteos üzeneteket rak át egyik sorból a másikba. Az ötlet innen jött, csak többszálasítottam.

A tesztkód:

using System;
using System.Diagnostics;
using System.Messaging;
using System.Threading;

namespace MsmqTran
{
class Program
{
private const int NumberOfTests = 1000;
private const int MaxDop = 10;
private static readonly ManualResetEvent[] WaitForEmpty = new ManualResetEvent[MaxDop];

static void Main()
{
var q1 = new MessageQueue(@”.\private$\test_queue1″);
var q2 = new MessageQueue(@”.\private$\test_queue2″);

Console.WriteLine(“Filling source queue…”);
var b = new byte[1500];
using (var msmqTx = new MessageQueueTransaction())
{
msmqTx.Begin();
for (int i = 0; i < NumberOfTests; i++) { q1.Send(b, msmqTx); } msmqTx.Commit(); } q2.Purge(); Console.WriteLine("Starting to move data from source queue to destination queue"); var sp = Stopwatch.StartNew(); for (int i = 0; i < MaxDop; i++) { WaitForEmpty[i] = new ManualResetEvent(false); ThreadPool.QueueUserWorkItem(o => ProcessMsg(q1, q2, (ManualResetEvent)o), WaitForEmpty[i]);
}

WaitHandle.WaitAll(WaitForEmpty);

Console.WriteLine(“Duration: {0}ms, throughput: {1:F0} messages/s”, sp.ElapsedMilliseconds, 1000.0 * NumberOfTests / sp.ElapsedMilliseconds);
}

private static void ProcessMsg(MessageQueue q1, MessageQueue q2, ManualResetEvent w)
{
while (true)
{
using (var msmqTx = new MessageQueueTransaction())
{
msmqTx.Begin();

Message message;
try
{
message = q1.Receive(TimeSpan.FromMilliseconds(0), msmqTx);
}
catch (MessageQueueException e)
{
Console.WriteLine(e);
w.Set();
break;
}

q2.Send(message, msmqTx);

msmqTx.Commit();
}
}
}
}
}

A gépemen 50 tran/sec-kel megy 1 szálon, és 200 fölé nem nagyon megy. Jó, ez laptop, de relációs adatbáziskezelővel (sql server és oracle is fut a gépen) több ezer tran/seccel mennek a dolgok. Szóval ez elég gázosan lassú. Emellett csúnya leállásokról is írnak a blogokban, amikor beáll az msmq.

Marad a aszinkronított WCF egyelőre, csak a szerverről visszafelé hívásokat tervezem queue alapon megcsinálni, WCF msmq bindinggal. Így tudom értesíteni az appokat polling nélkül. Erre 3 okom van most:
1. Az offline (disconnected) pessimistic lock feloldódott, lehet szerkeszteni valamit.
2. Frissíteni kell a kliens cache-ben valamit.
3. Email jellegű üzenetküldés az appok között.

Köszönöm még egyszer az építő javaslatokat.