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.
Related
We're writing a WCF service which will have to manage external client petitions, on those petitions we will:
Connect to another external service (not under our control) and validate a signature to ensure the identity of the caller.
Make several operations on our environment.
Finally, if everything is ok, call to another external service (again not under our control) and obtain a registry number to send to the client as a response.
From my point of view, the external services calls add too much entropy to allow all process in only one operation, there are lots of possible scenarios out of our reach that can finish with a timeout on the final client.
IMHO we should try to write different operations to manage each of the different parts (generating a secure token to carry authentication during 2nd and 3rd steps) so we can avoid an scenario where all the processes works fine but takes too much time and the client stops waiting for the response, generating a timeout.
My opinion is not shared for other members of the team, who wants to do all in a single operation.
Is there a best practice for this type of scenarios?
Will be better to use different operations or won't it have impact at all?
You can leverage of callback contract. Create oneway operation and let client invoke service and order all work to be done. Within method save client's reference and once all the long-running work is done, check if client's reference is not null so as to make sure client has not been closed. If not then invoce callback operation specified in callback contract. The pros of such as way out is that client does not keep waiting for the result but he is informed when result is obtained and ready to be provided. I refer you to this post.
I have a WCF Service that is transferring large files.
Currently I'm using Singleton service with list of instances from my class to hold the state and to response to the client requests for transfer progress and so on.
The instanced class itself handles new threads for each transfer when needed.
Clients who add transfer requests and request progress can disconnect meanwhile and reconnect at random time for the requests.
Also several different clients may want to request progress of all transfers that are going on.
Everything is working great as it is, but I'm sure there is better way of doing this?
Storing state somehow in SQL?
Storing state as I'm currently doing and somehow reconnecting to the same instance? How to get data from all instances then?
I hope you understood my rather long question :)
Yor solution would work great if there is only one instance of yor WCF service.
When you instantiate more than 1 instance with loadballancing then that approach won't work.
In such case you need to keep the state is some place which is common to all instances. It could be SQL, State server, another WCF service which could keep state, etc.
UPDATE:
You need to generate id for each file tranfer task. Then Singletone can assosiate id with instance which does transfer (let's call it Executor).
When client wants to get progress or cancel transfer then it requests Singletone and provides task id.
Singletone should use task id to resolve the actual Executor and forvard client's request to the right Executor.
As result you will be able to instantiate as many Executors as you need. Client should not worry which exactly Executor processes file. Everithing what client should know is task id.
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.
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.).
We are currently working on an application that will use a WCF service. The host (the client) is using the excellent WCF Service Proxy Helper from Erwyn van der Meer.
What I would like to know... is if I open this object multiple times... will it lead to multiple (expensive) connections or will WCF manage it and pool the connections.
The reason why I want to know this is because we will be calling methods of the service at different point in time within the same web request and we currently have wrapped the instanciation of the Service proxy class within the call.
Eg.:
MyService.MyMethod1() // wraps the connection usage as well as the call to the service
Any suggestions about how I would go to minimize the amount of connection while keeping the code conform with SRP would be excellent.
So? Any idea?
You should try to minimize the number of proxy objects you create. Proxies in WCF are quite expensive to set up, so creating one and calling functions on it multiple times is definitely more efficient than creating a new one for each method invocation.
The relationship between proxy objects and connections depends on the transport used. For http transports, an HTTP connection is initiated for each function invocation. For the net.tcp transport, the connection is established at Open() time and kept until a Close(). Certain binding settings (eg those supporting WS-SecureConversation) will incur extra "housekeeping" connections and message exchanges.
AKAIK, none of the out-of-the-box bindings perform connection pooling.
It doesn't do pooling like SqlConnection, if that is what you mean.
[caveat: I use "connection" here loosely to mean a logical connection, not necessarily a physical connection]
Between using a connection on-demand, and keeping one around, there are advantages and disadvantages to both approaches. There is some overhead in initializing a connection, so if you are doing 5 things you should try to do them on the same proxy - but I wouldn't keep a long term proxy around just for the sake of it.
In particular, in terms of life-cycle management, once a proxy has faulted, it stays faulted - so you need to be able to recover from the occasional failure (which should be expected). Equally, in some configurations (some combinations of session/instancing), a connection has a definite footprint on the server - so to improve scalability you should keep connections short-lived. Of course, for true scalability you'd usually want to disable those options anyway!
The cost of creating a connection also depends on things like the security mode. IIRC, it will be more expensive to open a two-way validated connection using message security than it will to set up a TransportWithMessageCredential connection - so "YMMV" is very much the case here.
Personally, I find that the biggest common issue with proxy performance isn't anything to do with the time to set up a conncetion - it is the chattiness of the API. i.e.
Scenario A:
open a connection
perform 1 operation with a large payload (i.e. a message that means "do these 19 things")
close the proxy
Scenario B:
open a connecton
perform 19 operations with small payloads
close the connection
Then scenario A will usually be significantly faster due to latency etc. And IMO don't even think about distributed transactions over WCF ;-p