I have a web server (ASP.NET - Mono 2.6.7) with a value static float x in it and two methods : getX() and setX(newX). I also have two clients one is a pc with c# console application and the other one is a mobile device with android (ksoap2). Both can access the web server.
What I do not know is : if my mobile device try to do a getX() while my pc is doing a setX(newX), will it result any trouble ?
Thanks.
It's not a good practice to have a state-full implementation for services. You can have different instances serving multiple requests. This is the case in ASP.NET web services. In WCF, using configuration, you can change instancing behavior. For example, you can have a single instance serving all requests (few of them can be concurrent) - in case, one has mutable state (as in your case), you have to synchronize the access to the state. Thread synchronization on shared state will create a bottleneck in serving the requests because at the most only one request thread can access the state. Further, you cannot scale horizontally (i.e. web farm scenario where requests will be served from multiple machines). If you choose to have multiple instances serving the request then you need to externalize the state e.g. put it into the database. In such case, you will incur in the penalty of accessing external data source (which can be much higher than thread synchronization) but you will have scalable design.
Roughly-speaking, a web service class/object should not be stateful in itself. You can store state, but it's usually externally, for example in a database.
This is because, depending on configuration, there's no guarantee that it will be the same instance of the class for every request for every client.
Related
What's the general rule of thumb to decide whether to use PerSession or PerCall?
I have a slightly heavy (I think..) WCF service, containing CRUD methods to about 80 tables.
I have separated the WCF service into 7 contracts within 1 service, (i.e., 7 end points within 1 service) such that each contract takes care of its own domain, for example I have a Sales contract, so all sales related tables, and its corresponding operations are within the sales "bounded context"
So my WCF service structure looks something like this:
public partial class ABCService : ISalesService
{
//CRUD methods of all tables related to Sales
}
public partial class ABCService : IMarketingService
{
//CRUD methods of all tables related to Marketing
}
public partial class ABCService : ICustomerService
{
//CRUD methods of all tables related to Customer
}
public partial class ABCService : IProductService
{
//CRUD methods of all tables related to Products
}
My concern with PerCall is that, because I have a fairly large DB/WCF service, I'm afraid that the amount of resources consumed by each call, multiplied by the number of users and the rate of which they call the service, would be far too great.
I do not know the fine details, but I have read that creating a Channel Proxies are expensive operations.
Oh, I'm using hand coded proxies instead of VS's Add service reference to consume my WCF service.
So, my question is, which should I use? PerSession or PerCall?
Update:
I do not need to maintain state between calls.
I'm using NetTCP bindings
In my opinion, to take a decision consider these two points
For going with InstanceContextMode.PerSession - If your users have some session values stored on the WCF service on the server.
For going with InstanceContextMode.PerCall - If your users have nothing stored in session on the WCF service on the server i.e. WCF service requires No per user settings required to store in memory. Requires scalability.
Some points regarding When-And-Why,
InstanceContextMode.PerCall
If your service is stateless and scalable, i.e. benefits are similar to HTTP as it is also stateless.
If service has light-weight initialization code (or none at all).
If your service is single threaded.
Example scenario: For any 1000 client requests in a given time period in a PerCall situation, there will only be 100 objects instantiated for 100 active calls. Secondly if server were to crash then in PerCall situation the only errors that would occur would be to the 100 actual requests that were in progress (assuming fast failover). The other 900 clients could be routed to another server on their next call.
InstanceContextMode.PerSession
If your service has to maintain some state between calls from the same client.
If your service has light-weight initialization code (or none at all). Even though you are only getting a new instance for each client proxy, you still want to be careful about having expensive initialization code in a constructor.
Example scenario: For any 1000 client requests in a given time period in a PerSession situation you may have 1000 objects instantiated on the server but only 100 are actually active in call at any moment. And thus instantiated PerSession objects could be a waste of resources and may impact the ability to serve requests under load. Secondly if server were to crash then in PerSession all 1000 clients who have a session on that server would lose their session and be unable to complete their work.
Reference links:
MSDN - WCF Instancing, Concurrency, and Throttling
SO - Per-Call vs Per-Session
MSDN - Using Sessions in WCF context
The reason you don't see many answers to this type of question online is that it depends. What I would do is try it out -- then open up perfmon on the server where you are hosting the service and add the counters for your service. Just google wcf performance manager counters if you aren't familiar.
The good news is that WCF makes changing the setup pretty easy.
If you are concerned with the cost of instantiating a proxy on the client side, remember that perCall is a service behavior, not a client behavior. Even if you set the service instance context to PerCall, you can still create one instance of your proxy and make a bunch of method calls from that proxy. All perCall means is that when you make a call, an instance of the service is created, your method is called, and the instance of the service is torn down again. If you don't have any expensive initialization on the service instance (i.e. if they're basically static methods) you're probably ok with per call.
Am stuck on what am sure is a fundamental and easy to solve problem in WCF, just need to be guided towards the right way.
I have a large object (which is actually a trained text classifier) that I need to expose through a Web Service in C# .NET. The classifier object can be loaded from disk when the service initially starts, but I don't want to keep loading it from disk for every request (the object that services requests currently occupies about 6 GB in memory, and it takes a while to keep loading it from disk for every request), so instead I want to persist that object in memory throughout all requests to that web service, and the object should only be loaded when the service starts (instead of loading it when the first web request triggers it).
How would I go about doing that?
Thanks for any help!
Probably the easiest way is to create your service as a singleton. This involves specifying InstanceContextMode = InstanceContextMode.Single in a ServiceBehavior attribute on your service class definition.
However it is very questionable if sending a 6GB object over the wire using WCF is advisable. You can run into all sorts of service availability issues with this approach.
Additionally, singletons are not scalable within a host (can be only one instance per host), although you can host multiple singleton services and then load-balance the requests.
The way I've done this in projects that I've had the problem with in the past is to self host the WCF service inside a Windows Service.
I've then set the data storage object up inside the service as a singleton that persists for the life of the service. Each WCF service call then gets the singleton each time it needs to do something with the data.
I would avoid running in IIS simply because you don't have direct control of the service's lifetime and therefore don't have enough control of when things are disposed and instantiated.
I am working on a project in which a WCF service will be consumed by iOS apps. The number of hits expected on the webserver at any given point in time is around 900-1000. Every request may take 1-2 seconds to complete. The same number of requests are expected on every second 24/7.
This is what my plan:
Write WCF RESTful service (the instance context mode will be percall).
Request/Response will be in Json.
There are some information that needs to be persisted in the server - this information is actually received from another remote system - which is shared among all the requests. Since using a database may not be a good idea (response time is very important - 2 seconds is the max the customer can wait), would it be good to keep it in server memory (say a static Dictionary - assume this dictionary will be a collection of 150000 objects - each object consists of 5-7 string types and their keys). I know, this is volatile!
Each request will spawn a new thread (by using Threading.Timers) to do some cleanup - this thread will do some database read/write as well.
Now, if there is a load balancer introduced sometime later, the in-memory stored objects cannot be shared between requests routed through another node - any ideas?
I hope you gurus could help me by throwing your comments/suggestions on the entire architecture, WCF throttling, object state persistence etc. Please provide some pointers on the required Hardware as well. We plan to use Windows 2008 Enterprise Edition server, IIS and SQL Server 2008 Std edition database.
Adding more t #3:
As I said, we get some information to the service from a remote system. On the web server where the the WCF is hosted, a client of the remote system will be installed and WCF references one of this client dlls to get the information, in the form of a hashtable(that method returns a hashtable - around 150000 objects will be there in this collection). Would you suggest writing this information to the database, and the iOS requests (on every second) which reach the service retrieves this information from the database directly? Would it perform better than consuming directly from this hashtable if this is made static?
Since you are using Windows Server 2008 I would definitely use the Windows Server App Fabric Cache to store your state:
http://msdn.microsoft.com/en-us/library/ff383813.aspx
It is free to use, well supported and integrated and is (more or less) API compatible with the Windows Azure App Fabric Cache if you every shift your service to Azure. In our company (disclaimer: not my team) we used to use MemCache but changed to the App Fabirc Cache and don't regret it.
Let me throw some comments/suggestions based on my experience in serving a similar amount or request under the WCF framework, 3.5 back in the days.
I don't agree to #3. Using a database here is the right thing to do. To address response time, implement caching and possibly cache dependency in order to keep the data synchronized across all instances (assuming that you are load balanced)(also see App Fabric suggested above/below). In real world scenarios, data changes, often, and you must minimize the impact.
We used Barracuda hardware and software to handle scalability as far as I can tell.
Consider indexing keys/values with Lucene if applicable. Lucene delivers extremely good performances when it comes to read/write. Do not use it to store your entire data, read on it. A life saver if used correctly. Note that it could be complicated to implement on a load balanced environment.
Basically, caching might be the only necessary change to your architecture.
I've created an old-style .ASMX web service and would like to know how the built-in ADO.NET connection pooling works with it.
The web service is not using a singleton pattern, so it is instantiated anew with every request. My question is will connections be removed from the pool after each service request, or are they kept in the pool across requests? My service is called very frequently but I don't want to be doing setup and teardown of connections every time, if it can be avoided.
I have read that the pool is maintained for the AppDomain, but I'm not sure if each request generates a new AppDomain or not.
I am also curious if it would be beneficial to set Min Pool Size (to a small number other than 0) in this case.
Anyone know?
No each request does not generate a new app domain. All the requests for that web site/application are in the same application domain, and so share the connection pool. Once the asmx request is finished with the connection, it returns it to the pool and the next request in line grabs it (assuming there isn't another connection in the pool readily available).
One point of clarification. You can have two different web applications which point to the same code, and are in different app domains. The two applications don't share anything (think about launching the same application twice).
I am also curious if it would be
beneficial to set Min Pool Size (to a
small number other than 0) in this
case.
So it can be beneficial depending on the application. Creating connections takes time, so having some ready allows you to forgo that. If you have request that say uses one connection, that might be fine to make a person wait for (it all depends on fast you want the application to respond). This can really come into play when you need to say 3 or 4 different ones (you get the point) open for one request. So why would you need multiple connections? What about one for accessing data and a separate thread for logging to the database (logging to the database vs a file is a totally different conversation)? Now you need two. There are multiple scenarios where this can come into play. Depending on your database server holding an open connection can be pretty cheap, so setting it to a small number can be a huge bang for your buck. (For the record I've seen scenarios where connecting to a database took several seconds, like 3-5, so in that case holding an open connection for a user was beneficial.)
This is for Max Pool Size
No it's not beneficial, because all requests to that service use the same pool (assuming the connections are using the same connection string, and aren't hitting different servers. Those have separate connection pools). Having no available connections, is a really fast and surefire way of crushing the performance of your service.
I'm using in memory sessions in my ASP.NET MVC application which means that I can only have one single worker thread correct? Does this mean I have parallel processing in my application (think concurrent requests) or not? Does my application accept only 1 request at a time?
Edit: According to the IIS7 web site:
If the application uses in-process session variables,
the application will not function correctly, because the same user requests
are picked up by different worker processes that
do not share the same session details.
So this means in-memory session can only have 1 worker thread or not? See also here from the IIS7 forums.
Your application receives multiple requests at a time. Based on your edits and comments here you are looking for information on Web Gardens and sessions, as opposed to threads and session state.
Web Gardens use multiple processes and act like a load balancer when it comes to session state. Each process will have a separate in memory session store. IIS will send requests to any available process. Since the processes do not share session state then session usage will only really work if your session provider is shared between all the web garden processes.
Web Gardens only make sense if you use something like SQL Server for session state, and want to have affinity with a particular CPU/core. Since you can increase the number of threads this may be a more appropriate optimization for some users than using web gardens. However some applications may perform better with web gardens due to a particular work load or application characteristic. Use of web gardens in testing could also help work out some potential issues present under load balancing.
I believe it uses the .NET ThreadPool and has 20 threads by default. The each request coming into the server may be handled on a separate thread. The ASP.NET performance guidelines have some information on this topic.
In memory sessions means you should typically only have one front-end web server at a time, not a single worker thread :D
The reason being that any information stored in session on one machine is not available on the other. If you have two front-end web servers and your proxy or firewall does "load-balancing" whereby it will randomly assign requests to web servers, then you will have problems. That said, the problem is easily solved with so called "sticky sessions" where users are always sent to the same server.
-Oisin