We are planning to develop a web service using WCF. Is there a good way to limit the number of calls to the service in a period of time for a single IP? We don't want to put a hard limit (X number of times an hour), but we want to be able to prevent a spike from a single user.
Rather than trying to come up with our own custom solution and reinventing the wheel, is there an existing implementation or strategy that can be used? Will the different hosting environments in WCF make any difference?
Note: This question is related to this question. Comments were made about better extensibility in WCF, so I'm keeping these two questions separate.
Related
What is a best practice for designing WCF services concerning to the use of more or less operations under a single service.
Taking into consideration that a Service must be generic and Business oriented, I have encountered some SOAP services # work that have too much XML elements per operation in their contracts and too many operations in a single service.
From my point of view, without testing, I think the number of operations within a service will not have any impact on the performance in the middleware since a response is build specifically for each operation containing only the XML elements concerning that operation.
Or are there any issues for having too many operations within a SOAP service ?
There is an issue, and that is when trying to do a metadata exchange or a proxy creation against a service with many methods (probably in the thousands). Since it will be trying to do the entire thing at once, it could timeout, or even hit an OutOfMemory exception.
Dont hink it will impact performance much but important thing is methods must be logically grouped in different service. Service with large number of method usually mean they are not logically factored.
I would like to intercept WCF messages on the client side. I cannot use any MessageInspector for this, because I would like to implement a client side WCF cache. If the request has been cached before, the response should come from the cache, otherwise the request ist forwarded to the service.
As I am using netTcpBinding and netNamedPipeBinding, the "simple" way, implementing IRequestChannel is not possible. I need to implement IDuplexSessionChannel. Now, I am looking for a working sample how to intercept and replace messages.
But why is this important?
In theory WCF-services, as all other calls that possibly goes over a network, should have coarse-grained interfaces. The reason is obvious: WCF has tons of features to secure the connection, enable reliable-messing, ensures authentication, enable transactions (... continued ...). This will not come for free, obviously.
In practice we ofen encounter "exeptions" from that rules. Services that are called a thousend times in one service method and other violations of best practices. Well, of course the best way to deal with this situation would be to redesign the services. Unfortunately, that rarely happens (you name the reasons ...).
That is where caching comes into play. There are, basically, two ways of doing this:
Implementing a solution that needs to rewrite parts of your applications. One way of doing this is to write a proxy-caller (e.g. using generics for that).
List item
Implementing a "transparent" solution, that works with all WCF-services, without any modifications
For obvious reasons the second solution seems more promising. Again, there are two alternatives:
Writing a servers-side-caching solution, using WCF behaviors and IOperationInvoker. This is pretty straightforward to accomplish and the web gives you some good samples how to do this. Such as olution is acceptable, if the service to be cached is pretty expensive in its methods, e.g. loading lots of information from a database, so that looking up the result in your cache is much faster than perform all necessary calculations and IO-operations. However, the WCF-call is still there, with all overhead that comes with it. The advantage is, that you only need to define that behavior once in your service and all clients of this service will benefit from the cache.
Writing a client-side-caching-solution, that prevents the WCF-call, if the response is already in the cache. This, of course, prevents all the WCF-overhead, but requires to define the (endpoint) behavior within all clients that accesses the services to be cached (e.g. any master data service or any other "slowly changing dimension"-services).
The second solution is much more complicated, as you need a channel factory, (and / or a listener) and an implementation of the channel itself. The channel could be a IRequestChannel or a IDuplexSessionChannel. Again, you will find a working solution for the first type on the web, but that, naturally, will not work for netTcpBining or netNamedPipeBinding, which uses the IDuplexSessionChannel. That is, why I am looking for a sample that illustrates how to do it right.
Just to give an impression of what the benefits would be: One solution, that has a long-running service method, the execution time is (approx. 150000 calls of other services within that service):
netTcpBinding, no caching: 65 minutes
netNamedPipeBinding, no caching: 40 minutes
netNamedPipeBinding, server-side-caching: 27 minutes
netNamedPipeBinding, client-side-caching: 19 minutes
The no. of calls drops fro 150000 to about 40000 in that szenario. However, my solution for client-side-caching will not work well for duplex-channels and other special commmunication types. Therefor, I am looking for a sample.
Any help would be appreciated.
This is a design question, I guess there going to be several suggestions (I hope so!)
We are a small travelling agent office, we are developing a software for our need. We have 30 clients on the local LAN, sometime later some other 5-10 from outside the office. (This will be agents on route).
Would you create a WCF service for this scenario or just leave the DL in the client (for direct access to the SQL)??
Our DataAccess Technology is EntityFramework 4.0 (4.1), ALL clients are Windows 7 based.
About the travelling agents, wouldn't it be much more simple to just use a VPN for the agents connection??
We have plans to supply our guides (outside the office ) with 3G tablets in about 1 year from now.
Developing clients with a DL is of course much more straight forward solution, but our plans for the near future will require some kind of service. The tablets application will have a much more simple interface and functionality. So maybe developing a WCF service dedicated for the tablets will be better?
Our first consideration is time, we are in great need for a working software.
Well, I hope I managed to share with you our thoughts clearly enough.
Thank you for reading.
I think one technology that would be a) very well-suited to your needs, and b) doesn't impose a huge overhead on your development effort would be WCF Data Services.
This is a REST-based WCF service based on a model - like your Entity Framework model.
Check out:
the WCF Data Services Developer Center
MSDN docs on WCF Data Services
I would see clear benefits in architecting a new solution from the get-go to use a service-based approach - even if your local LAN client might end up not using that service layer. Thinking in services, thinking also about the limitations of sending data across a potentially slower link than your LAN usually helps avoid silly mistakes like loading 200'000 customers into a dropdown box and stuff like that...
Having a service layer also makes your client app much less dependent on the actual database technology - that client might be a Winforms, WPF or Silverlight app, a web site, a tablet - you name it. If they all share the service layer, development of the client app will become less of a burden - the majority of your work will be in your data model and your service layer (which is shared across all clients).
I'm working on a 4-player network game in WPF and learning WCF in the process. So far, to handle the network communication, I've followed the advice from the YeahTrivia game on Coding4Fun game: I use a dualHttpBinding, and have use a CallbackContract interface to send back messages to clients. It works pretty well.
However, my service is getting very large. It has methods/callbacks to handle the game itself, but also the chat system, the login/registration process, the matchmaking, the roster/player info, etc. Both the server and client are becoming hard to maintain because everything is tied into a single interface. On the client for example, I have to redirect the callbacks to either the game page, the lobby page, etc, and I find that very tedious. I'd prefer being able to handle the game callbacks on the game page, the chat callbacks on the chat window, etc.
So what's the best way to handle that? I've thought of many things, but not sure which is best: splitting the service into multiple ones, having multiple "endpoints" on my service, or is there other tricks to implement a service partially where appropriate?
Thanks
You should have multiple components, each of which should be limited to one responsibility - not necessarily one method, but handling the state for one of the objects you're dealing with. When you have everything all in one service then your service is incredibly coupled to itself. Optimally, each component should be as independent as possible.
I'd say start with splitting it up where it makes sense and things should be MUCH more manageable.
I would support Terry's response - you should definitely split up your big interface into several smaller ones.
Also, you could possibly isolate certain operations like the registration and/or login process into simpler services - not knowing anything about your game, I think this could well be a simple non-duplex service that e.g. provides a valid "player token" as its output which can then be used by the other services to authenticate the players.
Multiple smaller, leaner interfaces also give you the option to potentially create separate, dedicated front-ends (e.g. in Silverlight or something) that would target / handle just certain parts of the whole system.
Marc
Does anyone have any experience with how well web services build with Microsoft's WCF will scale to a large number of users?
The level I'm thinking of is in the region of 1000+ client users connecting to a collection of WCF services providing the business logic for our application, and these talking to a database - similar to a traditional 3-tier architecture.
Are there any particular gotchas that have slowed down performance, or any design lessons learnt that have enabled this level of scalability?
To ensure your WCF application can scale to the desired level I think you might need to tweak your thinking about the stats your services have to meet.
You mention servicing "1000+ client users" but to gauge if your services can perform at that level you'll also need to have some estimated usage figures, which will help you calculate some simpler stats such as the number of requests per second your app needs to handle.
Having just finished working on a WCF project we managed to get 400 requests per second on our test hardware, which combined with our expected usage pattern of each user making 300 requests a day indicated we could handle an average of 100,000 users a day (assuming a flat usage graph across the day).
In addition, since it's fairly common to make the WCF service code stateless, it's pretty easy to scale out the actual WCF code by adding additional boxes, which means the overall performance of your system is much more likely to be limited by your business logic and persistence layer than it is by WCF.
WCF configuration default limits, concurrency and scalability
Probably the 4 biggest things you can start looking at first (besides just having good service code) are items related to:
Bindings - some binding and they protocols they run on are just faster than others, tcp is going to be faster than any of the http bindings
Instance Mode - this determines how your classes are allocated against the session callers
One & Two Way Operations - if a response isn't needed back to the client, then do one-way
Throttling - Max Sessions / Concurant Calls and Instances
They did design WCF to be secure by default so the defaults are very limiting.