I am trying to figure out what exactly is Appdomain recycling?
When a aspx page is requested for the first time from a DotNet application, i understand that an appdomain for that app is created, and required assemblies are loaded into that appdomain, and the request will be served.
Now, if the web.config file or the contents of the bin folder, etc are modified, the appdomain will be "recycled".
My question is, at the end of the recycling process, will the appdomain be loaded with assemblies and ready to serve the next request? or a page has to be requested to trigger the assemblies to load?.
Well, I think the thread was getting smoothly to a final conclusion, but in the end, it was otherwise.
I'll try to answer the question based on my understanding and leveraging what i've just read about in other web sites.
First of all, I myself try to avoid the term recycle other than for Application Pools since this may render someone confused. Now, getting to process, pools and AppDomain, I see the picture as follows:
An Application Pool is, in short, a region of memory that is maintained up and running by a process called W3WP.exe, aka Worker Process. Recycling an Application Pool means bringing that process down, eliminating it from memory and then originating a brand new Worker Process, with a newly assigned process ID.
Regarding Application Domains, I see it as subsets of memory regions, within the aforementioned region that plays the role of a container. In other words, the process in memory, W3WP.exe in this case, is a macro memory region for applications that stores subset regions, called Application Domains. Having said that, one process in memory may store different Application Domains, one for each application that is assigned to run within a given Application Pool.
When it comes to recycling, as I initially told, it's something that I myself reserve only for Application Pools. For AppDomains, I prefer using the term 'restart', in order to avoid misconception. Based on this, restarting a AppDomain means starting over a given application with the newly added settings, such as refreshing the existing configuration. That happens within the boundaries of that sub-region of memory, called AppDomain, that ultimately lies within the process associated with a respective Application Pool. Those new settings may come from files such as
web.config,
machine.config,
global.asax,
Bin directory,
App_Code,
and there may be others.
AppDomain are isolated from each other, that makes total sense. If not so, if changes to a web.config, let's say, of application 1, requited recycle of the pool, all other applications assigned to that pool would get restarted, what was definitely not desired by Microsoft and by anyone else.
Summarizing my point,
Process (W3WP.exe)
AppDomain 1
AppDomain 2
AppDomain 3
AppDomain n
n = the number of assigned applications to the Application Pool managed by the given W3WP.exe
Processes are memory regions isolated from one another
AppDomains are sub-memory regions isolated from one another, within the same process
Global IIS settings changes may require Application Pool recycle (killing and starting a new Worker Process, W3WP.exe)
Application-wide settings changes AppDomains concerns, and they may get restarted after changes in some specific files such as the ones outline above
For further information, I recommend:
http://blogs.msdn.com/b/david.wang/archive/2006/03/12/thoughts-on-iis-configuration-changes-and-when-it-takes-effect.aspx
What causes an application pool in IIS to recycle?
http://blogs.msdn.com/b/tess/archive/2006/08/02/asp-net-case-study-lost-session-variables-and-appdomain-recycles.aspx
Regards from Brazil!
Take a look at this - that might explain it:
http://weblogs.asp.net/owscott/archive/2006/02/21/ASP.NET-v2.0-2D00-AppDomain-recycles_2C00_-more-common-than-before.aspx#440333
In general. What is called "first hit" on an ASP.NET Website is usually taking longer time, due to compilation, and creation of an AppDomain.
Whenever you deploy a site - make sure to use the "Publish Website" function in Visual Studio, to pre-compile your website. Then the "first hit" penalty is reduced. And remember to set the configuration to Release, and not Debug!
Recycle shuts down the process hosting the appdomain. You'll notice that the PID changes when you recycle it.
Unloading the AppDomin simply unloads all of the assemblies in the AppDomain, which can then be reused.
The important thing to remember is that once the CLR is loaded into a process, it can't be removed. So if you needed to do something as soon as the CLR is loaded, then simply unloading the AppDomain won't help, because the CLR won't be reloaded.
Also not that IIS isn't the only process which can host the AppDomain - any process can, and you don't always want to kill the whole process just to unload your assemblies.
If your pages are "updatable," they must be compiled before use. That means, yes, on first request the assemblies are loaded, compiled, and made ready for accessing. Whenever these files are changed (even some virus software can trigger this by changing the modified date of the files!), the appdomain gets recycled.
You can configure your web application to not be updatable. Everything gets compiled into DLLs, and you won't see any .ASPX or .CS files in the virtual directory. It makes your code harder to update (need to put some additional text on your webpage? Recompile time!), but it increases the availability of your web app.
However, this still won't prevent your web app from being recycled if any of the files are altered. For example, if you edit web.config, your appdomain will recycle even if its compiled.
Related
For regular assemblies one can use MEF to load assemblies dynamically. If a live update is required of those assemblies, the recommendation is to use AppDomains to host the dynamic assemblies (potentially one can use Managed Add-in Framework (MAF)). When requiring an update, the appdomain is stopped, the assemblies are updated and the appdomain is reloaded.
What about assemblies that are loaded by ASP .NET that contain that code behind classes? How can I update them without forcing a restart of the main appdomain. Is it possible to host some of my pages in a dynamic appdomain? How would you do that? Can this appdomain share login token and authentication stuff so the user doesn't have to re-login?
Thanks
MEF doesn't support AppDomain isolation, so unfortunately, even during recomposition, those assemblies that had previously been loaded are still loaded in the main web application AppDomain. There are two things you'd need to battle in ASP.NET:
Any changes to physical files (e.g. .aspx, .cshtml, etc), or any changes to configuration files (.config), or any changes to the \bin directory will cause the application to be recycled. This is due to two things, file monitoring of pages/configs, and file monitoring of the \bin directory (which is because by default ASP.NET uses shadow copying of files - this is recommended).
To use MEF in another AppDomain would require a hideous amount of cross-domain communication, either through serialisation or MarshalByRef, which I just don't think would ever be a clean implementation. Not sure how you would trigger BuildProvider instances used to dynamically compile your pages in another AppDomain either.
I'm wondering if you're thinking about this too much. Since IIS6, HTTP.SYS has managed the routing of incoming requests to the appropriate website, this is handled at the kernel level. Even if the main application did restart (which there are a variety of reasons why it could), no requests will be dropped, it would simply queue waiting for a new worker process before passing the request on. Sure, from the user's point of view, they may notice some idle time waiting for the new application to restart, but realistically, how often are you going to be making these changes?
A lot of application design suffers from over-engineering. You may want to design for every scenario, but realistically it is easier to maintain a system which is simple but extensible. In my opinion, wanting to do what you have specified would be classed as over-engineering. Keep it simple.
Using the session "StateServer" will preserve your authentication between app pool recycles (caused by file updates).
For your actual question:
Create a folder outside of your website that your app pool has access to.
Put your new assemblies in there
Have a Task/Thread/Web Service that reads the folder and loads the assemblies into the current App Domain
Assembly.LoadFrom(string) http://msdn.microsoft.com/en-us/library/1009fa28.aspx
The newer version of the assembly should take precedence when an instance is created
I guess your question is saying this method doesn't work? What error are you getting...
I'm using VS2010 and ASP.NET 4. I have a single, long-running background thread running in the application, which is designed to 'cleanup' the least recently used files in a folder. It uses an EventWaitHandle to eliminate uneeded CPU usage, but stays running for the life of the app.
After 24-40 deletions or so, the application restarts. This happens under both IIS Express and the WebDev server, with the debugger attached. No exceptions are thrown on the background thread, but a ThreadAbortException occurs on all threads, and the app restarts. No Redirect calls are made anywhere.
These files are located in an 'imagecache' folder in the root, not any folder that should cause a app restart. No folders are created or deleted.
The restart seems to occur a timed interval after a certain threshold of deletions occur.
Any idea why this is happening and how I can stop it? Restarting every 10 seconds ins't acceptable for me :)
Perhaps it's an IIS application pool recycle ? Have a look on the recycle settings to see if it might be something there.
Another option depends on how you start the background thread. If it's from an aspx page then it might be the Request thread timing out. If it's from the global.asax then this is not an option.
An asp.net application is to service client requests, not to run background tasks (although there are many kludges that allow this).
Can you put the thread into a service?
I am running an ASP.NET application on an IIS7 server. It has been running fine for a long time, but over the past week or so it has been discarding all users' sessions several times a day. I enabled all of the application pool recycle logging options as described in http://blogs.iis.net/ganekar/archive/2008/12/12/iis-7-0-application-pool-recycles-log-a-event-in-windows-event-log.aspx, but I didn't get anything in my event log.
There are no errors in the event log, and no visible symptoms except that all my users lose their sessions.
Are there any other reasons that IIS would recycle my application pool? Is there any other type of logging that I can enable to find out what is happening?
When you experience this behavior, how recently have you done a deployment of your files to the server?
There is a nasty configuration option called numRecompilesBeforeAppRestart on the compilation tag:
<system.web>
<compilation debug="true" numRecompilesBeforeAppRestart="15">
http://msdn.microsoft.com/en-us/library/system.web.configuration.compilationsection.numrecompilesbeforeapprestart.aspx
This value defaults to 15. I've been through an application killing all user sessions before and this was the culprit for me. For roughly a day after a lightly used web application was updated (new files copied to the server; this ended up overwriting EVERY file, numbering into the hundreds), we'd get constant AppDomain restarts evidenced by all Session values for all users disappearing.
I found this bug report listing the behavior I'm experiencing:
http://support.microsoft.com/kb/319947
Here is the really important relevant text to my scenario:
However, this problem occurs when you
load many new .aspx or .ascx files to
the server (for example, 61 files).
The server unloads the application
when the first 15 files are recompiled
and every time another 15 files are
recompiled until the server reaches
61. This results in four application restarts even though only one is
required.
I switched the value to 99999 and the problem went away. This means more memory will build up in my worker process, so I added a daily recycle (3am when my site has no users) to the IIS AppPool recycle settings.
You can set options in the metabase to log the different types of recycle events to the event log.
For IIS 6.0, see http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/87892589-4eda-4003-b4ac-3879eac4bf48.mspx
For example, to enable logging of recycle events due to exceeding the private memory limitation, execute this on your web server:
cd %systemroot%\inetpub\adminscripts
cscript.exe adsutil.vbs set w3svc/AppPools/YOUR_APP_POOL_NAME/AppPoolRecyclePrivateMemory true
Here is a link to [different] instructions for IIS 7.0: http://technet.microsoft.com/en-us/library/cc771318%28v=ws.10%29.aspx
I can understand Appdomain concept, but small doubt is
One Process -> many application domain,
ok now,
when a application domain is created ? while making request or at time of hosting in IIS.
Again created Appdomain is One to one relationship with asp.net web Application..?
Could you please clear this, I want to know when appdomain created by CLR?
Thanks
karthikeyan
I'd say an AppDomain is created per ASP.NET web application, and is launched when the first request comes in and there is no AppDomain already instantiated for the current path.
Obviously there are IIS configurable idle times for when AppDomains in an AppPool (many to one) are being shut down.
when a application domain is created ?
I suppose when starting up IIS after you have set up virtual directories and uploaded your project files. Or maybe during the first incoming request.
Another thing to remember is that an application domain can be destroyed and recreated during operation. If your application has consumed too much server resources (memory), the application domain can be recycled and then recreated again.
When IIS6 starts up, it starts the App Pools. Each App Pool is a w3wp.exe process. Each process then creates its AppDomains for each associated ASP.NET application and triggers the Application start events on each.
One AppPool is a w3wp process and in this it makes AppDomain for each application on various scenarios like the Application's resources are more consumed (restart of appdomain) or the files like web.config etc are altered or a version of DLL is added.
Scenario: I've an n-Tier enterprise ASP.NET application deployed using Web Deployment Projects. All tiers produce independent assemblies that is consumed by the ASP.NET application.
Problem: When I run the app. for the first time after deployment it takes lot of time to load dependent assemblies in memory. But once loaded its lighting fast app. In case if there are no users accessing the app, IIS unloads the assemblies from the memory and when a user tried to access the app on a later instance it goes on loading all the assemblies once again taking the same amount of time to load as it takes to do so for the first time.
I'm looking for a solution that enables me to keep my assemblies loaded into memory persistently overriding the volatile nature of assemblies towards memory residency.
Or any other solution that lets my users happily use the app resolving the mentioned problem.
In IIS 6, go to the Application Pools section, and right-click > Properties on the pool which hosts the ASP.NET application in question. Go to the Performance tab and uncheck "Shutdown worker processes after being idle for:"
In IIS 7, go to the Connections pane and find Application Pools, and select Advanced Settings for the pool which hosts your application. Find the "Idle Timeout" property and set it to "0" (this disables it).
The default is 20 minutes of inactivity. By unchecking the box, once your AppDomain is loaded by the worker process, it will never die (unless you kill the process or something of course). By default, IIS will recycle the process when it reaches some limit, such as a memory cap, but it will also start a new one and "phase over" all incoming requests until the old one is unused, so as to minimize disruption.
I've also written a small c# class which will keep your ASP.NET application alive (alternate archived version) under normal circumstances. Since it runs within the application, obviously it can't stop IIS or anything else from explicitly killing the process, but it will keep the application "hot", e.g. the app will never go idle long enough for IIS to decide to shut it off.
If you do not have direct control over your IIS configuration (shared host, for example) your best bet is to have a small application running on a separate system - say, an always-on workstation - which hits your site every x minutes to keep the application pool from timing out. Nothing fancy - a simple WebRequest and a while() loop in a console application will do.
One of the advantages of ASP .net is the posibility to create static (shared) instances of objects.
To avoid the necessity of an external process you can create an static timer in (per example) global.asax which calls for a page on the domain with a simple WebRequest. On this way the site keeps alive himself until a manual reset of the pool is done.
I wrote a little C# console application that keeps my 4 sites alive every 10 mins via windows task scheduler. Life is once again good. We do not run the app from 2-5am just so the serves can do any cleanups of memory, if it even matters. for our sites there is rarely anyone on at those hours anyway.