WCF service clear buffer - wcf

I am currently working on a WCF service and have a small issue. The service is a Polling Duplex service. I initiate data transfer through a message sent to the server. Then the server sends large packets of data back through the callback channel to the client fairly quickly.
To stop the I send a message to the sever telling it do stop. Then it sends a message over the callback channel acknowledging this to let the client know.
The problem is that a bunch of packets of data get buffered up to be sent through the callback channel to the client. This causes a long wait for the acknowledgement to make it back because it has to wait for all the data to go through first.
Is there any way that I can clear the buffer for the callback channel on the server side? I don't need to worry about loosing the data, I just need to throw it away and immediately send the acknowledgement message.

I'm not sure if this can lead you into the correct direction or not... I have a similar service where when I look in my Subscribe() method, I can access this:
var context = OperationContext.Current;
var sessionId = context.SessionId;
var currentClient = context.GetCallbackChannel<IClient>();
context.OutgoingMessageHeaders.Clear();
context.OutgoingMessageProperties.Clear();
Now, if you had a way of using your IClient object, and to access the context where you got the instance of IClient from (resolve it's context), could running the following two statements do what you want?
context.OutgoingMessageHeaders.Clear();
context.OutgoingMessageProperties.Clear();
Just a quick ramble from my thoughts. Would love to know if this would fix it or not, for personal information if nothing else. Could you cache the OperationContext as part of a SubscriptionObject which would contain 2 properties, the first being for the OperationContext, and the second being your IClient object.

Related

Azure service bus multiple instances for the same subscriber

I have a situation where I have an asp.net core application which registers a subscription client to a topic on startup (IHostedService), this subscription client essentially has a dictionary of callbacks that need to be fired whenever it detects a new message in a topic with an id (this id is stored on the message properties). This dictionary lives throughout the lifetime of the application, and is in memory.
Everything works fine on a single instance of the asp.net core app service on azure, as soon as I scale up to 2, I notice that sometimes the callbacks in the subscription are not firing. This makes sense, as we have two instances now, each with its own dictionary store of callbacks.
So I updated the code to check if the id of the subscription exists, if not, abandon message, if yes, get the callback and invoke it.
public async Task HandleMessage(Microsoft.Azure.ServiceBus.Message message, CancellationToken cancellationToken)
{
var queueItem = this.converter.DeserializeItem(message);
var sessionId = // get the session id from the message
if (string.IsNullOrEmpty(sessionId))
{
await this.subscriptionClient.AbandonAsync(message.SystemProperties.LockToken);
return;
}
if (!this.subscriptions.TryGetValue(sessionId, out var subscription))
{
await this.subscriptionClient.AbandonAsync(message.SystemProperties.LockToken);
return;
}
await subscription.Call(queueItem);
// subscription was found and executed. Complete message
await this.subscriptionClient.CompleteAsync(message.SystemProperties.LockToken);
}
However, the problem still occurs. My only guess is that when calling AbandonAsync, the same instance is picking up the message again?
I guess what I am really trying to ask is, if I have multiple instances of a topic subscription client all pointing to the same subscriber for the topic, is it possible for all the instances to get a copy of the message? Or is that not guaranteed.
if I have multiple instances of a topic subscription client all pointing to the same subscriber for the topic, is it possible for all the instances to get a copy of the message? Or is that not guaranteed.
No. If it's the same subscription all clients are pointing to, only one will be receiving that message.
You're running into an issue of scaling out with competing consumers. If you're scaling out, you never know what instance will pick the message. And since your state is local (in memory of each instance), this will fail from time to time. Additional downside is the cost. By fetching messages on the "wrong" instance and abandoning, you're going to pay higher cost on the messaging side.
To address this issue you either need to have a shared/centralized or change your architecture around this.
I managed to solve the issue by making use of service bus sessions. What I was trying to do with the dictionary of callbacks is basically a session manager anyway!
Service bus sessions allow me to have multiple instances of a session client all pointing to the same subscription. However, each instance will only know or care about the sessions it is currently dealing with.

MessageBus: wait when processing is done and send ACK to requestor

We work with external TCP/IP interfaces and one of the requirements is to keep connection open, wait when processing is done and send ACK with the results back.
What would be best approach to achieve that assuming we want to use MessageBus (masstransit/nservicebus) for communication with processing module and tracing message states: received, processing, succeeded, failed?
Specifically, when message arrives to handler/consumer, how it will know about TCP/IP connection? Should I store it in some custom container and inject it to consumer?
Any guidance is appreciated. Thanks.
The consumer will know how to initiate and manage the TCP connection lifecycle.
When a message is received, the handler can invoke the code which performs some action based on the message data. Whether this involves displaying an green elephant on a screen somewhere or opening a port, making a call, and then processing the ACK, does not change how you handle the message.
The actual code which is responsible for performing the action could be packaged into something like a nuget package and exposed over some kind of generic interface if that makes you happier, but there is no contradiction with a component having a dual role as a message consumer and processor of that message.
A new instance of the consumer will be created for each message
receiving. Also, in my case, consumer can’t initiate TCP/IP
connection, it has been already opened earlier (and stored somewhere
else) and consumer needs just have access to use it.
Sorry, I should have read your original question more closely.
There is a solution to shared access to a resource from NServiceBus, as documented here.
public class SomeEventHandler : IHandleMessages<SomeEvent>
{
private IMakeTcpCall _caller;
public SomeEventHandler(IMakeTcpCalls caller)
{
_caller = caller;
}
public Task Handle(SomeEvent message, IMessageHandlerContext context)
{
// Use the caller
var ack = _caller.Call(message.SomeData);
// Do something with ack
...
return Task.CompletedTask;
}
}
You would ideally have a DI container which would manage the lifecycle of the IMakeTcpCall instance as a singleton (though this might get weird in high volume scenarios), so that you can re-use the open TCP channel.
Eg, in Castle Windsor:
Component.For<IMakeTcpCalls>().ImplementedBy<MyThreadsafeTcpCaller>().LifestyleSingleton();
Castle Windsor integrates with NServiceBus

Any way to tell if a DuplexClientBase is busy?

I was looking at Microsoft's duplex WCF sample:
It starts here but the interesting bit is here at the end with the client.
// Wait for callback messages to complete before
// closing.
System.Threading.Thread.Sleep(5000);
// Close the WCF client.
wcfClient.Close();
Console.WriteLine("Done!");
If you take out the Sleep, you will get an exception
The session was closed before message transfer was complete.
So clearly the client knows there's stuff in the air, is there a way to ask it for its current status? There's a state but that just defines whether it's open or closed (i.e. connected not active).
This is not entirely true. Your methods are one-way method calls. So, when you call the service from your client, that call (or set of calls) is completed. In other words, the "message" has been delivered to the service and there is no expectation for a response since it is one-way. It might callback on the callback contract...it might not.
When you setup Duplex channel, you're standing up an endpoint for the service to call back on (client becomes a service essentially). If you close the client, then if/when the service decides to call back, the communication exception will occur. That's just the way this message exchange pattern works.
You really sort of answered your own question. Which is, when you check the status it is either open, closed (or faulted). When you're using a duplex channel, open in this case means there is potentially "activity" on the channel. That's why the sleep is there - to allow the service time to call back. If you look at the SDK sample (http://msdn.microsoft.com/en-us/library/vstudio/ms752216(v=vs.110).aspx), it's basically doing the same thing except it sits there waiting for you to press ENTER before it closes the client application.
So, in a real application (not a console based sample like these are), either keep your client proxy active or change your message exchange pattern to a request/reply pattern.

keeping a wcf callback channel open indefinitely / reconnecting from client if it faults

i'm currently trying to set up something like this:
a server side windows wcf service hangs out and listens via tcp for connections from a client side windows service.
when a connection is received (the client calls the CheckIn method on the service) the service obtains a callback channel via OperationContext.Current.GetCallbackChannel<T>
this channel is stored in a collection along with a unique key (specifically, i store the callback interface, the channel, and the key in a List<ClientConnection> where each of those is a property)
calls should now be able to be passed to that client service based on said unique key
this works at first, but after a while stops -- i'm no longer able to pass calls to the client. i'm assuming it's because the connection has been dropped internally and i'm trying to work with a dead connection.
that in mind, i've got the following questions:
how do i tell wcf i want to keep those tcp connections indefinitely (or for as long as possible)?
how do i check, from the client side, whether or not my connection to the server is still valid so i can drop it and check in with the server again if my connection is fried?
i can think of gimpy solutions, but I'm hoping someone here will tell me the RIGHT way.
When you establish the connection from the client, you should set two timeout values in your tcp binding (the binding that you will pass to ClientBase<> or DuplexClientBase<>):
NetTcpBinding binding = new NetTcpBinding();
binding.ReceiveTimeout = TimeSpan.FromHours(20f);
binding.ReliableSession.InactivityTimeout = TimeSpan.FromHours(20f);
My sample uses 20 hours for timeout, you can use whatever value makes sense for you. Then WCF will attempt to keep your client and server connected for this period of time. The default is relatively brief (perhaps 5 minutes?) and could explain why your connection is dropped.
Whenever there is a communication problem between the client and server (including WCF itself dropping the channel), WCF will raise a Faulted event in the client, which you can handle to do whatever you feel appropriate. In my project, I cast my DuplexClientBase<> derived object to ICommunicationObject to get a hold of the Faulted event and forward it to an event called OnFaulted exposed in my class:
ICommunicationObject communicationObject = this as ICommunicationObject;
communicationObject.Faulted +=
new EventHandler((sender, e) => { OnFaulted(sender, e); });
In the above code snippet, this is an instance of my WCF client type, which in my case is derived from DuplexClientBase<>. What you do in this event is specific to your application. In my case, the application is a non-critical UI, so if there is a WCF fault I simply display a message box to the end-user and shut down the app - it'd be a nice world if it were always this easy!

Nservicebus synchronous call

I am using request reply model of NServiceBUs for one of my project.There is a self hosted service bus listening for a request message and reply back with a request message.
So in WCF message code i have coded like
// sent the message to bus.
var synchronousMessageSent =
this._bus.Send(destinationQueueName, requestMessage)
.Register(
(AsyncCallback)delegate(IAsyncResult ar)
{
// process the response from the message.
NServiceBus.CompletionResult completionResult = ar.AsyncState as NServiceBus.CompletionResult;
if (completionResult != null)
{
// set the response messages.
response = completionResult.Messages;
}
},
null);
// block the current thread.
synchronousMessageSent.AsyncWaitHandle.WaitOne(1000);
return response;
The destinaton que will sent the reply.
I am getting the resault one or tweo times afetr that the reply is not coming to the client. Am i doing anything wrong
Why are you trying to turn an a-synchronous framework into a synchronous one? There is a fundamental flaw with what you are trying to do.
You should take a long hard look at your design and appreciate the benefits of a-sync calls. The fact that you are doing
// block the current thread.
synchronousMessageSent.AsyncWaitHandle.WaitOne(1000);
Is highly concerning. What are you trying to achieve with this? Design your system based on a-synchronous messaging communication and you will have a MUCH better system. Otherwise you might as well just use some kind of blocking tcp/ip sockets.