After posting this question:
How to lock on an integer in C#?
Many of the answers made me feel that I'm a 'sinner' for using lock in my web apps. I never thought this is a problem (if used wisely), what about you? Do you ever use it in your web applications?
I don't see how a web application can be written without locking, for example if you want to load some data from a database and you want to be sure that no other thread will load it (also for singletons), normally you use locking, for example:
private _locker = new object();
private YourClass[] _data;
public YourClass[] Data
{
get
{
if(_data == null)
{
lock( _locker)
{
// get your data
_data = GetYourData();
}
}
return _data;
}
}
Is there a problem with this?!
Edit:
Please note that I'm referring to a single server scenario here, for a server farm you need some distributed locking mechanism, but you don't expect every site you create to get millions of hits in a couple of weeks, do you? What if you need locking, should you create your site with that distributed locking, isn't that too much for an application which you have no idea whether it will ever need to be scaled or not? Besides computers have gotten really fast these days, one server can handle tons of traffic and this has been proven so many times, some examples are plentyoffish.com and this very site you're using right now, do some googling and I'm sure you'll come across so many others.
If you use a lock to try to control access to a remote resource (e.g. something from the database) then you'll have problems when you try to scale to more servers.
If you just want to have an AppDomain-specific lock (e.g. for a cache) then it makes perfect sense.
I disagree with your implied assertion that web applications can't be written without locking (at the web server level) though. It really depends on the application - usually database contention is handled at the database rather than the web server, precisely so that you can have multiple machines in your web tier.
For singletons it makes a certain amount of sense, but I rarely use singletons anyway...
Yes, you need to check for the data once more. Known as a double check lock. http://en.wikipedia.org/wiki/Double_checked_locking_pattern
Theoretically, a second thread could get past your first null check before your lock is created.
if(_data == null)
{
lock( _locker)
{
if (_data == null) {
// get your data
_data = GetYourData();
}
}
}
Bad idea to do this in a web app unless you really, really know what you're doing.
I would look into Upgradeable Locks http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.enterupgradeablereadlock.aspx
I don't know how you do data-access, but I've never found it needed to lock the database for one request only. I'm not sure, but I could imagine you'd try to solve certain problems with a Microsoft Access database, but thats just because it's not a good database system to use for a website (or just anything which leaves your local desktop).
Locking a local contested resource at some point within a request is fine (although rare). Locking a request and trying to hold the lock across several requests is not really going to work too well. Even if you can get it to work in a single server environment if you ever have to scale to a multi-server environment then it's just not going to work the way you expect.
The remote resource that you try to access should be in charge of the locking. As someone already pointed out, locks are process-wide, and as soon as you scale up your locks will just fail to work.
Databases also should do all the locking you need. It's one of the main requirements for a DBMS: data integrity.
I've never needed to use any synchronization mechanism on any of my webapps. Unless you're dealing with say, a raw XML file that multiple sessions are changing, I can't see the need for it. Like most people here have said - your database will take care of that for you. Updates, queries, what have you, database systems (at least ones you are likely to use with ASP.NET) take care of synchronization for you.
Related
We have an application that reads and writes to a third party data storage.
The code of that data storage is closed source, we do not know about it and can not change it.
There is only a slim API that allows reading and writing to it.
An pessimistic offline lock helps to span transactions and have concurrent applications work with it. That will work fine I believe.
But now we have the problem that other software will also write and read to that storage
and our application shall update when changes in that data storage happen. The data storage itself does not provide any notification. The third party software will not change some global state that indicates that something has changed.
Is there any kind of pattern or best practise to "observe" that data storage and
publish events to update all clients (of our software)?
I really do not want to periodically read, compare and publish events if it is not
absolutely the last resort. Perhaps someone has a better idea here?
A non-System implemented Pessimistic Offline Lock requires cooperation/participation/enforcement among all possible modifers of the data. This is generally not possible and is one of the two reasons that this approach is rarely taken in modern software. To do anything remotely like this (i.e., with multiple heterogenuous writers) in a useful way requires some kind help/assistance from the System facilities themselves. (The second reason is the issues of determining and resolving abandoned locks, very problematic).
As for possible solutions, then from a purely design viewpoint, either optimistic offline locks, which still need some System help, but much less, or avoid the issue altogether through more detailed state-progression/control in your data model.
My approach, however, would be to set-aside the design question (initially) recognizing that this is primarily an issue of the data-store's capabilities and start there, looking to use System-provided lock/transaction control, (which both 1: usually works and 2: is how it is usually done).
AFAIK, issues of synchronizing multi-writer access always have to start with "What tools/controls/facilities are available to constrain, divert and/or track the out-of-application writers?" What you can accomplish is practically limited by those facilities.
For instance, if you can force all access through a service of your own, then you can do almost anything. But if all you have is the OS's file-locking and file-modification-dates, then you are a lot more constrained. And if you don't have even that, then there's not much you can do.
In fact I do not have direct access to the data store, it is hosted on
some server and I have no control over the other applications that
read and write to it. Right now, the best I can think of is having a
service as a proxy which periodically queries the store, compares it
to an older state and fires update events to my clients if some other
application has altered it (and fire some other event if my
application alters it to notify my own clients, leaving the other
applications with their own problems). It sound not very good to me,
but it probably does the job.
Yep, that's about all you can do, and that only supports Optimistic Concurrency (partially), not Pessimistic. You might get improvements by adding some kind of checksum/hash to your stored data, but that's only an optimization.
I understand that a static member will be shared by all users of an ASP.NET website; but in this particular case - that's exactly what I want.
It's a private-use webpage I threw together to facilitate web-based chatting between two users. I wanted to avoid persisting data to a database or a datafile, and thought I could store the last X messages in a static concurrent queue. This seems to work great on my development machine.
I'm very inexperienced with ASP.NET, but in all of the examples I've found, none use this approach. Is this a bad-practice, are there 'gotchas' I should be aware of? The alternative, that I can see, is to use a database. But I felt like it would be more effort and, my guess, is more resources (I figure my 'buffer' of messages will take about 40kb of memory and save quite a few trips to the database).
Assuming that you make sure that the entire thing is thread-safe, that will work.
However, IIS can recycle your AppDomain at any time, so your queue may get blow away when you don't expect it.
Even if IIS wouldn't flush and restart your AppDomain every now and then, using static variables for this purpose sounds like a smelly hack to me.
The HttpApplicationState class provides access to an application-wide cache you can use to store information.
ASP.NET Application State Overview
This is perfectly fine as long as your requirements don't change and you are OK with randomly loosing all messages on server side.
I would slightly refactor code to provide "message storage" interface to simplify testing of the code (with potential benefit in the future if you decide to make it more complicated/persisted/multi-user).
Pro of the static storage approach (or HttpApplicationState):
no issues with server side storage of the messages - less privacy concerns. Nothing is stored forever so you can say whatever you want.
extremely simple implementation.
perfect for IM / phone conversation.
unlikely to have performance problems in single server case
Cons:
messages can be lost. Can be mitigated by storing history on the client (i.e. retrieving message with AJAX queries on the same web page)
require more care if data is sensitive when more users are involved/or application is shared with some other code as static data is visible to everyone. Also not much different from any other storage.
Can't be directly migrated to multiple servers/web garden scenario. Really unlikely issue for 2 person chat server.
Sure, one gotcha I've seen in the past has been the use of static variables with Web Gardens.
See this SO question:
Web Garden and Static Objects difficult to understand
Note a key point from the discussion:
Static objects are not shared in web gardens/web farms.
Coming from an Classic ASP background I'm pretty cautious about placing objects into Session.
Would it be a bad idea for me to store an object of type Dictionary into Session within .NET?
Well, you won't have some of the issues that you would have with ASP. .net is not STA COM, so the thread affinity problems that you had with ASP are not going to hurt you (unless you try to store an STA COM object in the session, or in your dictionary).
Do be careful about concurrent access, though. If it is possible that multiple threads could access the dictionary (do to asynchronous page code, or maybe AJAX calls), then you will need to apply appropriate locking to the dictionary.
Well, it depends on what you want to achieve, for simple things like persisting state between page postbacks, I recommend you to use the ViewState.
You can put anything into Session... You just have to make sure not too much data is put into Session as this takes up server resources. This is something that will not be visible when testing your site at first, only when you deploy it and a lot of users start using it, as every user has its own Session object on the server.
The big picture issues aren't really different than classic ASP (though I confess I didn't think about the differences that JMarsch raised). The answer depends on numerous factors:
How many concurrent sessions you expect (and how many you intend to support)
The size of the Dictionary
Your server(s)'s memory characteristics
Everything else your server(s) need to do
At the moment I am working on a project admin application in C# 3.5 on ASP.net. In order to reduce hits to the database, I'm caching a lot of information using static variables. For example, a list of users is kept in memory in a static class. The class reads in all the information from the database on startup, and will update the database whenever changes are made, but it never needs to read from the datebase.
The class pings other webservers (if they exist) with updated information at the same time as a write to the database. The pinging mechanism is a Windows service to which the cache object registers using a random available port. It is used for other things as well.
The amount of data isn't all that great. At the moment I'm using it just to cache the users (password hashes, permissions, name, email etc.) It just saves a pile of calls being made to the database.
I was wondering if there are any pitfalls to this method and/or if there are better ways to cache the data?
A pitfall: A static field is scoped per app domain, and increased load will make the server generate more app domains in the pool. This is not necessarily a problem if you only read from the statics, but you will get duplicate data in memory, and you will get a hit every time an app domain is created or recycled.
Better to use the Cache object - it's intended for things like this.
Edit: Turns out I was wrong about AppDomains (as pointed out in comments) - more instances of the Application will be generated under load, but they will all run in the same AppDomain. (But you should still use the Cache object!)
As long as you can expect that the cache will never grow to a size greater than the amount of available memory, it's fine. Also, be sure that there will only be one instance of this application per database, or the caches in the different instances of the app could "fall out of sync."
Where I work, we have a homegrown O/RM, and we do something similar to what you're doing with certain tables which are not expected to grow or change much. So, what you're doing is not unprecedented, and in fact in our system, is tried and true.
Another Pitfall you must consider is thread safety. All of your application requests are running in the same AppDomain but may come on different threads. Accessing a static variable must account for it being accessed from multiple threads. Probably a bit more overhead than you are looking for. Cache object is better for this purpose.
Hmmm... The "classic" method would be the application cache, but provided you never update the static variables, or understand the locking issues if you do, and you understand that they can disappear at anytime with an appdomain restart then I don't really see the harm in using a static.
I suggest you look into ways of having a distributed cache for your app. You can take a look at NCache or indeXus.Net
The reason I suggested that is because you rolled your own ad-hoc way of updating information that you're caching. Static variables/references are fine but they don't update/refresh (so you'll have to handle aging on your own) and you seem to have a distributed setup.
I'm developing a web service whose methods will be called from a "dynamic banner" that will show a sort of queue of messages read from a sql server table.
The banner will have a heavy pressure in the home pages of high traffic sites; every time the banner will be loaded, it will call my web service, in order to obtain the new queue of messages.
Now: I don't want that all this traffic drives queries to the database every time the banner is loaded, so I'm thinking to use the asp.net cache (i.e. HttpRuntime.Cache[cacheKey]) to limit database accesses; I will try to have a cache refresh every minute or so.
Obviously I'll try have the messages as little as possible, to limit traffic.
But maybe there are other ways to deal with such a scenario; for example I could write the last version of the queue on the file system, and have the web service access that file; or something mixing the two approaches...
The solution is c# web service, asp.net 3.5, sql server 2000.
Any hint? Other approaches?
Thanks
Andrea
It depends on a lot of things:
If there is little change in the data (think backend with "publish" button or daily batches), then I would definitely use static files (updated via push from the backend). We used this solution on a couple of large sites and worked really well.
If the data is small enough, memory caching (i.e. Http Cache) is viable, but beware of locking issues and also beware that Http Cache will not work that well under heavy memory load, because items can be expired early if the framework needs memory. I have been bitten by it before! With the above caveats, Http Cache works quite well.
I think caching is a reasonable approach and you can take it a step further and add a SQL Dependency to it.
ASP.NET Caching: SQL Cache Dependency With SQL Server 2000
If you go the file route, keep this in mind.
http://petesbloggerama.blogspot.com/2008/02/aspnet-writing-files-vs-application.html
Writing a file is a better solution IMHO - its served by IIS kernel code, w/o the huge asp.net overhead and you can copy the file to CDNs later.
AFAIK dependency cashing is not very efficient with SQL Server 2000.
Also, one way to get around the memory limitation mentioned by Skliwz is that if you are using this service outside of the normal application you can isolate it in it's own app pool. I have seen this done before which helps as well.
Thanks all, as the data are little in size, but the underlying tables will change, I think that I'll go the HttpCache way: I need actually a way to reduce db access, even if the data are changing (so that's the reason to not using a direct Sql dependency as suggested by #Bloodhound).
I'll make some stress test before going public, I think.
Thanks again all.
Of course you could (should) also use the caching features in the SixPack library .
Forward (normal) cache, based on HttpCache, which works by putting attributes on your class. Simplest to use, but in some cases you have to wait for the content to be actually be fetched from database.
Pre-fetch cache, from scratch, which, after the first call will start refreshing the cache behind the scenes, and you are guaranteed to have content without wait in some cases.
More info on the SixPack library homepage. Note that the code (especially the forward cache) is load tested.
Here's an example of simple caching:
[Cached]
public class MyTime : ContextBoundObject
{
[CachedMethod(1)]
public DateTime Get()
{
Console.WriteLine("Get invoked.");
return DateTime.Now;
}
}