I can't deny the performance benefit of a duplex async call, but some things about makes me feel wary.
My concern is that given a client object instantiated, will WCF be able to tell which particular client service instance will receive the callback argument?
Can anyone tell me if this is a good idea? If not why not?
new DuplexChannelFactory<IServerWithCallback>(
new ClientService(),
new NetTcpBinding(),
new EndpointAddress("net.tcp://localhost:1234/"+Guid.NewGuid()))
If the virtual path above is reserved how can it be discarded. I want the client service lifetime to be fairly short. IE make a request and receive a response and when done receiving, kill it. How bad is the performance penalty in making the client service lifetime short as opposed to pooling it and keeping it alive longer.
The idea is to avoid timeout issue. When done receiving, sending, dispose ASAP. By convention - can't pass the client services around. If you need info, create a new one, simple - just like EF/L2S etc.
From inside the WCF service itself, how do I kill the session with the client. ie. I don't want the client ending the session - I know I can decorate my operation accordingly, but I want the service to terminate itself programmatically when certain conditions are met.
I can affix the port and forward accordingly to resolve any firewall issue, but what I'm worried about is if the client were to sit behind a load-balancer. How would the service know which particular server to call?
I think in the end Duplex services is simply another failed architecture from Microsoft. This is one of those things that looked really good on paper but just falls apart upon closer examination.
There are too many weaknesses:
1) Reliance on session to establish client listener by the server. This is session information is stored in memory. Hence the server itself cannot be load balanced. Or if it were load balanced you need to turn ip affinity on, but now if one of the servers is bombarded you can't simply add another one and expect all these sessions to automagically migrate over to the new server.
2) For each client sitting behind a router/firewall/loadbalancer, a new end point with specific port needs to be created. Otherwise the router will not be able to properly route the callback messages to the appropriate client. An alternative is to have a router that allows custom programming to redirect specific path to a particular server. Again a tall order. Or another way is for the client with the callback to host its own database and share data via a database <-- Might work in some situation where licensing fees is not an issue... but it introduces a lot of complexity and so onerous on the client plus it mixes the application and services layer together (which might be acceptable in some exceptional situation, but not on top of the huge setup cost)
3) All this basically says that duplex is practically useless. If you need call back then you will do well to setup a wcf host on the client end. It will be simpler and much more scalable. Plus there is less coupling between client and server.
The best duplex solution for scalable architecture is in the end not using one.
It will depend on how short you need the clients new'd up and how long they will last. Pooling would not be an option if you specifically need a new client each time, but if the clients keep doing the same thing why not have a pool of them waiting to be used, if they fault out recreate that same client again.
In reality in a callback scenario if the service is calling back to the client (really calling a function on the client) to pass information the service is now the client and vice versa. You can have the service that's making the callback .Close() the connection but it will be open until the GC can dispose of it, from my experience that can take longer than expected. So in short the client should be responsible (the client being the one making the call to something) for shutting itself down, or disconnecting, the service should only give back answers or take data from a client.
In duplex callbacks the service now calling back to the client will get the address of the client abstracted behind the duplexchannelfactory. If the service can't call back to the client I don't think there's much that can be done, you'd have to ensure the port that your clients are calling to the service is open to receive callbacks I would guess.
Related
WCF duplex performs a callback after a method has run on the server that then runs code on the client.
If i want to execute a method on the client from the server at the push of a button on the server then i don't think WCF duplex is appropriate.
Why would i not just create a client and a server at each end of my 2 applications?
I was one of the people that commented on your previous question so I probably owe you an answer here :o)
You have posted rather a lot of code and I have not looked at it in detail. However, in general terms, there is a reason for using wsDualHttpBinding and duplex contracts in general instead of more of a peer-to-peer approach where you have services on both sides, as follows:
The duplex approach is appropriate where you have a clearly defined server that is running permanently. This provides the hub of the interaction. The idea is that clients are in some way more transient than the server. The clients can start up and shut down or move location and the server does not need to be aware of them in advance. When the client starts up, it is pre-configured to know where the server is, so it can "register" itself with the server.
In contrast, the server does not need to be preconfigured to know where the clients are. It starts up and can run independently of any clients. It just accepts "registrations" from all clients that have valid credentials whenever they come online, and can continue to run after the client goes offline. Also, if the client moves, it just re-registers itself with the server at its new location.
So the server is in some sense a more "important" part of the system. No client can participate in the communication without the server, but the server can operate independently of any client.
To do this with WCF duplex service, you have to do some extra work yourself to implement the publish/subscribe behaviour. Fortunately, the MSFT Patterns and Practises team have provided some guidance on how to do it
http://msdn.microsoft.com/en-us/library/ms752254.aspx
This is fundamentally different from a genuine peer-to-peer approach where there is no well-defined hub (i.e. server) for the network and each node can come and go without affecting the overall functioning of the network.
WCF Duplex is used when you have a Publish/Subscribe setting (also known as the Observer Pattern). Let's say you have a service that subscribes for notifications of some sort (e.g. new email). Normally, you would need to check periodically for updates. Using WCF Duplex, the subscriber can be notified automatically by the publisher when there are updates.
I am using WCF and I am putting a chatroom facility in my C# program. So I need to be able to send information from the server to the clients for two events -
When a user connects/disconnects I update the list of connected users and send that back to all clients for display in a TextBlock
When a user posts a message, I need the server to send that message out to all clients
So I am looking for advice on the best way of implementing this. I was going to use netTcpBinding for duplex callbacks to clients but then I ran into some issues regarding not being able to call back the client if the connection is closed. I need to use percall instances for scalibility. I was advised in this thread that I shouldnt leave connections open as it would 'significantly limit scalibity' - WCF duplex callbacks, how do I send a message to all clients?
However I had a look through the book Programming WCF Services and the author seems to state that this is not an issue because 'In between calls, the client holds a reference on a proxy that doesn’t have an actual object at the end of the wire. This means that you can dispose of the expensive resources the service instance occupies long before the client closes the proxy'
So which is correct, is it fine to keep proxies open on clients?
But even if that is fine it leads to another issue. If the service instances are destroyed between call, how can they do duplex callbacks to update the clients? Regarding percall instances, the author of Programming WCF Services says 'Because the object will be discarded once the method returns, you should not spin off background threads or dispatch asynchronous calls back into the instance'
Would I be better off having clients poll the service for updates? I would have imagined that this is much more inefficient than duplex callbacks, clients could end up polling the service 50+ times as often as using a duplex callback. But maybe there is no other way? Would this be scalable? I envisage several hundred concurrent users.
Since I am guilty of telling you that server callbacks won't scale, I should probably explain a bit more. Let me start by addressing your questions:
Without owning the book in question, I can only assume that the author is either referring to http-based transports or request-response only, with no callbacks. Callbacks require one of two things- either the server needs to maintain an open TCP connection to the client (meaning that there are resources in use on the server for each client), or the server needs to be able to open a connection to a listening port on the client. Since you are using netTcpBinding, your situation would be the former. wsDualHttpBinding is an example of the latter, but that introduces a lot of routing and firewall issues that make it unworkable over the internet (I am assuming that the public internet is your target environment here- if not, let us know).
You have intuitively figured out why server resources are required for callbacks. Again, wsDualHttpBinding is a bit different, because in that case the server is actually calling back to the client over a new connection in order to send the async reply. This basically requires ports to be opened on the client's side and punched through any firewalls, something that you can't expect of the average internet user. Lots more on that here: WSDualHttpBinding for duplex callbacks
You can architect this a few different ways, but it's understandable if you don't want the overhead (and potential for delay) of the clients constantly hammering the server for updates. Again, at several hundred concurrent users, you are likely still within the range that one good server could handle using callbacks, but I assume you'd like to have a system that can scale beyond that if needed (or at peak times). What I'd do is this:
Use callback proxies (I know, I told you not to)... Clients connecting create new proxies, which are stored in a thread-safe collection and occasionally checked for live-ness (and purged if found to be dead).
Instead of having the server post messages directly from one client to another, have the server post the messages to some Message Queue Middleware. There are tons of these out there- MSMQ is popular with Windows, ActiveMQ and RabbitMQ are FOSS (Free Open Source Software), and Tibco EMS is popular in big enterprises (but can be very expensive). What you probably want to use is a topic, not a queue (more on queues vs topics here).
Have a thread (or several threads) on the server dedicated to reading messages off of the topic, and if that message is addressed to a live session on that server, deliver that message to the proxy on the server.
Here's a rough sketch of the architecture:
This architecture should allow you to automatically scale out by simply adding more servers, and load balancing new connections among them. The message queueing infrastructure would be the only limiting factor, and all of the ones I mentioned would scale beyond any likely use case you'd ever see. Because you'd be using topics and not queues, every message would be broadcast to each server- you might need to figure out a better way of distributing the messages, like using hash-based partitioning.
I have a duplex WCF service that relies on a consistent named pipe connection between the service and the client. It's sort of a publish/subscribe system where the client calls Subscribe on the service and gets put in a subscription list. Then, the service calls certain update methods of its own, which will push the update to the client(s) via callbacks.
I've set the recieveTimeout for the netnamedpipebinding to "infinite." Can I reasonably rely on this connection to be open forever? More importantly, are there situations where the channel will fault outside of timeouts?
Since a named pipe is just a shared memory location, I can't think of many reasons why it would fail consistently besides hardware problems. Furthermore, there isn't much of a way of guaranteeing the connection outside of pinging at a certain interval.
On a side note, my gut feel is to avoid also making the client a WCF service. I know it's not a real circular dependency, but it just feels icky. However, I'm open to people telling me I'm just being paranoid and that that kind of pattern is a-okay.
You can never rely on the connection. Single unhandled exception / fault on the service will close the channel. I think you should handle Closed and Faulted events on client or implement pinging mechanism with proxy recreation and resubscribtion.
When using duplex communication you simply need the client to expose contract - it is not the same as exposing the service because client do not expose an endpoint. The communication is performed by single channel created from client to service because Named pipes are duplex by design. Every time you will want to have duplex communication over some transport you will need some handling code on the client.
I'm writing a client/server architecture where there are going to be possibly hundreds of clients over multiple virtual machines, mostly on the intranet but some in other locations.
Each client will be gathering data constantly and sending a message to a server every second or so. Each message will probably be about 128 characters or so in length.
My question is, for this architecture where I am writing both client/server in .NET is should I go with WCF or some socket code I've written previously. I need scalability (which the socket code has in mind), reliability and just the ability to handle that many messages.
I would not make final decision without peforming some proof of concept. Create very simple service, host it and use some stress test to get real performance results. Than validate results against your requirements. You have mentioned amount of messages but you didn't mentioned expected response time. There is currently discussed similar question on MSDN forum which complains about slow response time of WCF compared to sockets.
Other requirements are not directly mentioned in your post so I will make some assumption for best performance:
Use netTcpBinding - best performance, binary encoding, requires .NET server / clients. I guess you are going to use Net.Tcp because your other choice was direct socket programming.
Don't use security if you don't have to - reduces performance. Probably not possible for clients outside your intranet.
Reuse proxy on clients if possible. Openning TCP connection is expensive if you reuse the same proxy you will have single connection per proxy. This will affect instancing of you services - by default single service instance will handle all requests from single proxy.
Set service throttling so that your service host is ready for many clients
Also you should make some decisions about load balancing. Load balancing for WCF net.tcp connections requires sticky sessions (session affinity) so that after openning the channel client always calls the service on the same server (bacause instance of that service was created only on single server).
100 requests per second does not sound like much for a WCF service, especially with that little payload. But it should be quite quick to setup a simple setup with a WCF service with one echo method just returning the input and then hook up a client with a bunch of threads and a loop.
If you already have a working socket implementation you might keep it, but otherwise you can pick WCF and spend your precious development time elsewhere.
From my experience with WCF, i can tell you that it's performance on high load is very very nice. Especially you can chose between several bindings to achieve your requirements for the different scenarios (httpBinding for outside communication, netPeerTcpBinding in local network e.g.).
Im writing an application which transfers files using WCF. The transfers are done in segments so that they can be resumed after any unforeseen interruption.
My question concerns the use of the client side proxy, is it better to keep it open and reuse it to transfer each file segment or should I be reopening it each time I want to send something?
The reason to close a proxy as quickly as possible is the fact that you might be having a session in place which ties up system resources (netTcpBinding uses a transport-level session, wsHttpBinding can use security or reliability-based sessions).
But you're right - as long as a client proxy isn't in a faulted state, you can totally reuse it.
If you want to go one step further, and if you can share a common assembly with the service and data contracts between server and client, you could split up the client proxy creation into two steps:
create a ChannelFactory<IYourServiceContract> once and cache that - this is a very expensive and resource-intensive operation; since you need to make this a generic using your service contract (interface), you need to be able to share contracts between server and client
given that factory, you can create your channels using factory.CreateChannel() as needed - this operation is much less "heavy" and can be done quickly and over and over again
This is one possible optimization you could look into - given the scenario that you control both ends of the communication, and you can share the contract assembly between server and client.
You can reuse your WCF client proxy and that will make your client application faster, as proxy just will initialize once.
Creation of a new proxy takes up about 50-100 ms of time, if your system needs good scaling, it's quite a significant time.
When reusing the proxy, you have to be careful of its state and threading issues. Do not try to send data using a proxy that is already busy with sending data. (or receiving) You'll have terrible sleepless nights.
One way of reusing is, having a [ThreadStatic] private field for the proxy and testing its state & presence each time you need to send data. If a new thread was created, the thread static field will be null and you'll need to create a proxy. Assuming you have a simple threading model, this will keep the different threads from stepping on each other's toes and you'll have to worry only about the faulted state of the proxy.