I have a client that connects to a server which can potentially go down and come back up a few times a day. So far at the clients I'm using the following method to check for a faulted connection, the on faulted handler re-establishes a connection back to the server:
ICommunicationObject communicationObject = this as ICommunicationObject;
communicationObject.Faulted +=
new EventHandler((sender, e) => { OnFaulted(sender, e); });
Can anyone advise on the best possible (best practice) way to maintain a persistent duplex connection from the client side?
Extra Info:
With the above code where 'this' is the client connection inheriting from DuplexClientBase the handler is not triggered if the server is simply shutdown (application.exit), is there a better way to handle this?
Related
I am trying to set Disconnect Timeout to higher value from the default 30s.
All examples on web are more JS oriented.
var hubConnection = new HubConnection("http://localhost:8087");
var testHubProxy = hubConnection.CreateHubProxy("TestHub");
Error: System.TimeoutException: Couldn't reconnect within the configured timeout of 00:00:30, disconnecting.
This did not work:
GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromSeconds(35);
Update:
It looks like DisconnectTimeout needs to be set on the server side!?
What is the reason for disallowing different clients to have different Disconnect Timeout?
Disconnect Timeout is configured on server-side. The main reasons could be as follows:
We know the server may take some N-time units to respond so that the all clients may be well aware.
The server should be pinging the clients for connection at regular times. So the server is aware of clients connection and can manage other hubs and eradicate the expired connections from its connection pool.
The client is not supposed to set disconnect timeout because it does not know when could it shutdown e.g. the internet switched off accidentally on client side than the client is not able to tell server that I am not going to connect to you again. Yes but we have some events at client-side which tells it that it is not connected to the signalr hub anymore. Please see the reconnecting and disconnected events.
Summary:
Disconnect timeout is to inform the server that its client is not connected anymore even if it disconnects disgracefully .
I need to make persistance connection to Aerospike noSQL DB in a Web service.
In a not-Web application, connection is straightfoward as
using (AerospikeClient client = new AerospikeClient("127.0.0.1", 3000))
{
...
}
But in a Web service application, creating new client for each request is expensive. The Best Practices say this too: "use only one client instance per cluster in a program and share that instance among multiple threads. AerospikeClient and AsyncClient are thread-safe."
I can make a static object, but what if the client disconnects, either by error or timeout (24 hours max connection living time)? Can anyone provide any fault-tolerant code spippet? (Maybe similar to redis pattern How does ConnectionMultiplexer deal with disconnects?)
The client manages a socket pool. If a socket error or timeout occurs, the socket is disposed of.
hopefully a simple WCF beginners question..
I have a WCF channel factory, returning a service proxy TChannel:
// setup connection to server
var endpointAddress = new EndpointAddress(GetAppSetting("Endpoint"));
var tcpBinding = new NetTcpBinding();
channelFactory = new DuplexChannelFactory<IExcelServer>(this, tcpBinding, endpointAddress);
server = channelFactory.CreateChannel();
I would like to know when this service proxy changes state (Faulted, Closed etc). I can see events on the ChannelFactory itself, however I'm not sure this is the same as the channel itself, and even here stopping the server process doesn't cause a state transition.
This is a CallbackContract service, and in almost all interactions the server is sending data to the client. Therefore I can't simply rely on catching the failure when I make a server call from the client.
Should I send a heartbeat from client to server to trigger the state change?
The instance you get back from CreateChannel implements TChannel but also IClientChannel which has state changed events like Closed, Closing, Opened, etc.:
server = channelFactory.CreateChannel();
((IClientChannel)server).Faulted += FaultedHandler;
P.S: As you pointed out, the states of the channel and channel factory are related but not the same. If a Channel is faulted it doesn't necessarily mean that the ChannelFactory is.
I'm trying to let my service knows when one of the clients is disconnected.
I'm using wsDualHttpBinding.
Currently, I'm tried to use this event :
OperationContext.Current.Channel.Closed += new EventHandler((sender, e) => ClientIsDisconnected(sender, e, currentCallbackChannel));
But this event is never fired...
Please help me to know how it'd be done !
Edit :
Thanks to anderhil, I finally replaced wsDualHttpBinding by netTcpBinding (with the appropriate configuration described here : http://msdn.microsoft.com/en-us/library/ff647180.aspx#Step1).
With netTcpBinding, the Closed event fires without any problem... Still don't know why but it works.
The issue you are having is likely becuase of WsDualHttpBinding. In case you have this binding, two connections are created, from client to service and from service to client.
When the application is deployed over the internet it can create some issues with supporting such applications, you need to be sure that people are not behind the firewall or NAT or etc that can prevent your service to connect back to client.
I still don't know why it doesn't work on local machine when testing, but i will try to resolve it and update the answer.
As you told me more details in our chat, from the nature of your application it's better to use NetTcpBinding. In this case it's easier to understand what is happening cause one connection is created, and you will receive the notifications in case of gracefull close or abort of client.
As i told you before, anyway it's better to create some heartbeat mechanism to have things more reliable in case of unexpected computer or router shutdown.
Also, you can find this good cheat sheet on how to select communication between parties that involve WCF:
The Closed event should occur on a graceful disconnect; is that what's happening?
To detect the pure socket disconnect, listen for the Faulted event:
OperationContext.Current.Channel.Faulted += new EventHandler(FaultedHandler);
I want to create a simple client-server example in WCF. I did some testing with callbacks, and it works fine so far. I played around a little bit with the following interface:
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IStringCallback))]
public interface ISubscribeableService
{
[OperationContract]
void ExecuteStringCallBack(string value);
[OperationContract]
ServerInformation Subscribe(ClientInformation c);
[OperationContract]
ServerInformation Unsubscribe(ClientInformation c);
}
Its a simple example. a little bit adjusted. You can ask the server to "execute a string callback" in which case the server reversed the string and calls all subscribed client callbacks.
Now, here comes the question: If I want to implement a system where all clients "register" with the server, and the server can "ask" the clients if they are still alive, would you implement this with callbacks (so instead of this "stringcallback" a kind of TellTheClientThatIAmStillHereCallback). By checking the communication state on the callback I can also "know" if a client is dead. Something similar to this:
Subscribers.ForEach(delegate(IStringCallback callback)
{
if (((ICommunicationObject)callback).State == CommunicationState.Opened)
{
callback.StringCallbackFunction(new string(retVal));
}
else
{
Subscribers.Remove(callback);
}
});
My problem, put in another way:
The server might have 3 clients
Client A dies (I pull the plug of the laptop)
The server dies and comes back online
A new client comes up
So basically, would you use callbacks to verify the "still living state" of clients, or would you use polling and keep track "how long I havent heard of a client"...
You can detect most changes to the connection state via the Closed, Closing, and Faulted events of ICommunicationObject. You can hook them at the same time that you set up the callback. This is definitely better than polling.
IIRC, the Faulted event will only fire after you actually try to use the callback (unsuccessfully). So if the Client just disappears - for example, a hard reboot or power-off - then you won't be notified right away. But do you need to be? And if so, why?
A WCF callback might fail at any time, and you always need to keep this in the back of your mind. Even if both the client and server are fine, you might still end up with a faulted channel due to an exception or a network outage. Or maybe the client went offline sometime between your last poll and your current operation. The point is, as long as you code your callback operations defensively (which is good practice anyway), then hooking the events above is usually enough for most designs. If an error occurs for any reason - including a client failing to respond - the Faulted event will kick in and run your cleanup code.
This is what I would refer to as the passive/lazy approach and requires less coding and network chatter than polling or keep-alive approaches.
If you enable reliable sessions, WCF internally maintains a keep-alive control mechanism. It regularly checks, via hidden infrastructure test messages, if the other end is still there. The time interval of these checks can be influenced via the ReliableSession.InactivityTimeout property. If you set the property to, say, 20 seconds, then the ICommunicationObject.Faulted event will be raised about 20 to 30 (maximum) seconds after a service breakdown has occurred on the other side.
If you want to be sure that client applications always remain "auto-connected", even after temporary service breakdowns, you may want to use a worker thread (from the thread pool) that repeatedly tries to create a new proxy instance on the client side, and calls a session-initiating operation, after the Faulted event has been raised there.
As a second approach, since you are implementing a worker thread mechanism anyway, you might also ignore the Faulted event and let the worker thread loop during the whole lifetime of the client application. You let the thread repeatedly check the proxy state, and try to do its repair work whenever the state is faulted.
Using the first or the second approach, you can implement a service bus architecture (mediator pattern), guaranteeing that all client application instances are constantly ready to receive "spontaneous" service messages whenever the service is running.
Of course, this only works if the reliable session "as such" is configured correctly to begin with (using a session-capable binding, and applying the ServiceContractAttribute.SessionMode, ServiceBehaviorAttribute.InstanceContextMode, OperationContractAttribute.IsInitiating, and OperationContractAttribute.IsTerminating properties in meaningful ways).
I had a similar situation using WCF and callbacks. I did not want to use polling, but I was using a "reilable" protocol, so if a client died, then it would hang the server until it timed out and crashed.
I do not know if this is the most correct or elegant solution, but what I did was create a class in the service to represent the client proxy. Each instance of this class contained a reference to the client proxy, and would execute the callback function whenever the server set the "message" property of the class. By doing this, when a client disconnected, the individual wrapper class would get the timeout excetpion, and remove itself from the server's list of listeners, but the service would not have to wait for it. This doesn't actually answer your question about determining if the client is alive, but it is another way of structuring the service to addrss the issue. If you needed to know when a client died, you would be able to pick up when the client wrapper removed itself from the listener list.
I have not tried to use WCF callbacks over the wire but i have used them for interprocess communication. I was having a problem where call of the calls that were being sent were ending up on the same thread and making the service dead lock when there were calls that were dependant on the same thread.
This may apply to the problem that you are currently have so here is what I had to do to fix the problem.
Put this attribute onto the server and client of the WCF server implemetation class
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class WCFServerClass
The ConcurrencyMode.Multiple makes each call process on its own thread which should help you with the server locking up when a client dies until it timesout.
I also made sure to use a Thread Pool on the client side to make sure that there were no threading issues on the client side