Questa è un’interessante domanda che di tanto in tanto ritorna, ed una versione ancora migliore è: quante istanze di w3wp.exe possono essere gestite dal Sistema Operativo? Come spesso succede, la risposta è: dipendeWinking smile

Per prima cosa, ecco il problema dal quale sono poi partite le altre considerazioni: si tratta di una Compagnia di Hosting quindi ogni loro server ospita un elevato numero di siti (circa 450), ognuno dei quali ospitato nel proprio application pool, ogni app pool configurato per motivi di sicurezza per girare con un proprio specifico account e aspExecuteInMTA impostato ad “1” in ogni server. In alcune circostanze avevamo errori simili a questo:

Server error 'ASP 0177 : 80070057'
Error in Server.CreateObject
/site/page.asp, line 338
80070057

Riciclando i 2-3 application pool con il maggiore consumo di memoria (anche se i valori non erano comunque tali da far pensare ad un leak), threads e handles: importante da notare che il sito colpito dal problema non era mai lo stesso, e soprattutto non era mai lui la causa dell’errore, era semplicemente quello che ne subiva le conseguenze.

La prima cosa che viene alla mente è che 450 application pool sono veramente tanti (forse troppi?), senza contare il fatto che il problema veniva almeno temporaneamente risolto riciclando i pool con il consumo più alto di thread e handle… questo suggerisce un problema con il Desktop Heap Nerd smile

Un po’ di teoria

Desktop Heap overview spiega bene cosa sia il Desktop Heap ed a quali problemi si può andare incontro quando il Sistema si trova a corto di Desktop Heap Storage, ed ha anche qualche passo interessante proprio relativo ad IIS:

Regarding non-ASP.NET applications, IIS 6.0 has been tested on a well-configured mainframe server running up to 2,000 concurrent worker processes, each serving one application pool, but not using unique identities. In practice, a design of up to 500 simultaneous application pools is achievable, depending on the application requirements and assuming hardware resources are not a significant constraint. It is important to configure the UseSharedWPDesktop registry setting mentioned above when using more than 60 application pools with unique identities

Anche il mio collega Nicolas ha scritto un post interessante (in inglese) sull’argomento qui. Avere solamente uno shared desktop in teoria può portare a problemi di sicurezza, ma David Wang spiega bene lo scenario:

"we should use a common desktop when the number of application pools with unique identities configured on a server is greater than 60". In other words, IIS does not have a problem running >60 application pools which uses <60 unique identities. The limitation in question is the number of user desktops associated with each unique application pool identity that Windows simultaneously supports.

The following are the interesting combinations and consequences:

  1. If UseSharedWPDesktop=0 and all application pools launch as Network Service, then there is exactly one Desktop (of Network Service) shared by all the application pools. You have no isolation of desktop nor process identity between application pools.
  2. If UseSharedWPDesktop=0 and all application pools launch as unique user identity, then there is a unique Desktop for each user identity, which is obviously not shared. This is limited to a number around 60 due to Desktop heap limit in Windows Server 2003. This means that you can only have ~60 application pools perfectly isolated by desktop and process identity simultaneously running.
  3. If UseSharedWPDesktop=1 and all application pools launch as unique user identity, then there is one Desktop that is shared by all the user identities. This removes the limit of 60 at the cost of not perfectly isolated application pools. You have no desktop isolation but retain process identity isolation between application pools.
  4. UseSharedWPDesktop=1 and all application pools launch as Network Service is pretty much a degenerate case that is not interesting. :-)

Torniamo al problema

Il cliente in questione era già a conoscenza di questi post e stava già utilizzando UseSharedWPDesktop=1 (in caso contrario molto difficilmente sarebbero stati in grado di far girare più di 50 application pool sullo stesso server), avevano impostato sessionViewSize a 64 Mb ed il valore di default per la chiave HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SubSystems\Windows.

Per saperne di più circa lo stato del Desktop Heap sul server è possibile utilizzare Desktop Heap Monitor, ecco qualche veloce indicazione per cominciare ad usarlo (maggiori dettagli si possono trovare direttamente nell’help del tool):

    1. Log in with an account that has Administrator privilege. Note that you must either do this at the physical interactive console (i.e. not through Terminal Services) OR connect to the console session using mstsc /console (only possible on XP or Server 2003)
    2. Open a command prompt and change to "c:\kktools\dheapmon8.0"
    3. For uni-processor systems run
      • DHEAPINST -f
    4. For multi-processor systems (including single processor hyper-threaded systems) run
      • SET _NT_SYMBOL_PATH=symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols
      • DHEAPINST
      • You will be prompted to agree to the symbol server terms of use. You must accept these for the tool to work
        The server in question must be able to make an outgoing connection to the Internet for this to work
    5. For either 3. or 4. you should see
      • dheapinst - Desktop Heap Monitor installed successfully
    6. DHEAPMON uses a driver in order to read information from the kernel memory. This must be loaded by the following command:
      • DHEAPMON –l
      • You should see this confirmation message: Dheapmon - Driver loaded successfully
    7. You are now ready to run the tool and capture the desktop heap information. Run the following command:
      • DHEAPMON -v > desktopheap.txt
      • Important: if the output text file does not contain a line like this: “Windowstation: (Service-0x0-3e7$) SessionID: 0” (without quotation marks) then it is almost certain that you did not connect to the server using Terminal Services Client using the /console switch. You must connect using /console to get the full information required

È possibile automatizzare la raccolta delle informazioni con questo script (create un semplice file .bat da eseguire sulla macchina in questione):

@echo off
rem vars C B A are day month year in the for line below, change them to change date
for /F "tokens=2,3,4 delims=/- " %%A in ('date /T') do set DT=%%C_%%B_%%A
for /F "tokens=1,2 delims=/: " %%A in ('time /T') do set TM=%%A-%%B
echo %DT%
echo %TM%
Dheapmon -v > dheapmon_out_%DT%_%TM%.txt

Questo creerà un file con un nome univoco che include data e ora del log, è anche possibile schedulare questo batch per essere eseguito ad intervalli regolari, ad esempio ogni ora. Una volta ottenuti i dati che ci servono, occorre scaricare il device driver con il comando

dheapmon –u

Mentre per disinstallarlo si deve eseguire

dheapmon –r

Dal report ottenuto era chiaro che stavamo già utilizzando solamente 1 desktop (IIS WinSTA): dal momento che IIS WinSTA non è interattivo, la dimensione di questo desktop è 512 Kb e nel nostro caso era esaurito al 99,2% al momento della riproduzione del problema:

Windowstation: (WP_WINSTA-054f77ac-6ece-4080-b3a2-b0bf08dacaab) SessionID: 0
Desktop: (Default) Addr: bbc30000
Desktop Heap          524288 (0x   80000) Bytes
Committed             520192 (0x   7f000) Bytes
Uncommitted             4096 (0x    1000) Bytes
Allocated             520072 (0x   7ef88) Bytes
Total Freed              120 (0x      78) Bytes
Unused                  4216 (0x    1078) Bytes
Used Rate                    (      99.2) %

Per calcolare la dimensione del SessionViewState si può fare qualcosa del tipo:

312Kb (Winsta0/Default) +
64Kb (Winsta0/Disconnect) +
128Kb (Winsta0/Winlogon) + 
7 * 512Kb (all other non interactive winsta) +
512Kb (IIS non interactive winsta WP_WINSTA-xxx)
== 4600 Kb  (< 5 Mb)

Quindi apparentemente il problema non sta nel SessionViewSize ma piuttosto nella dimensione del Dekstop Heap non interattivo; inoltre impostare questo valore a 64 Mb come fatto originariamente in questa situazione dal cliente non è necessario dal momento che in realtà ne stavano utilizzando circa 4 Mb, quindi anche il default (20 Mb) era già più che sufficiente per i loro bisogni. Aumentando troppo questo valore si rischia di impattare anche altri aspetti del Sistema Operativo, quindi abbiamo provato partendo da 1024 Kb:

312 + 64 + 128 + 7 * 1024 = 7672 Kb (< 7 Mb)

Che ci ha portato a questa situazione (da notare che sui server non era abilitato il /3gb):

  • UseSharedDesktop abilitato
  • Eliminata la chiave SessionViewSize per tornare ad valore di default di 20 Mb
  • SharedSection=1024,3072,1024

Con questo primo tentativo il server è riuscito a funzionare correttamente più a lungo del solito ma il problema alla fine è tornato: con dheapmon abbiamo visto che il sistema era ancora a corto di desktop heap quindi abbiamo fatto un nuovo tentativo (questa volta risolutivo Smile) con:

SharedSection=1024,3072,2048 (312 + 64 + 128 + 7 * 1024 = 14840 Kb (< 15 Mb)

Come potete ben immaginare bisogna stare attenti quando si modifica la configurazione del Desktop Heap, se avete delle incertezze vi consiglio di contattare il Supporto Microsoft per discuterne direttamente con noi! Smile

 

Conclusione

In conclusione, ecco alcune raccomandazioni generali:

  • Se avete necessità di supportare quantità così elevate di application pool (nell’ordine delle centinaia) dovreste veramente considerare di muovervi su una piattaforma a 64 bit, ed in ogni caso è necessario tenere ben presente problemi che possono derivare dal content switching
  • In Windows 2008 con Dynamic Session Space rimuove il limite imposto da SessionViewSize, ma i limiti relativi al Desktop Heap continuano ad essere validi
  • 450 process identity è in ogni caso un numero veramente molto alto anche perchè le logon session e tocken cache potrebbero contenere valori duplicati (con conseguente spreco di risorse)
  • Siate sempre molto attenti e cauti quando modificate questi valori, dal momento che queste modifiche possono avere un impatto anche su altre quote a livello kernel

Il punto conclusivo è che su sistemi a 32 bit prima o poi incontreremo limitazioni che non è possibile aggirare, e questa dei 450 application pool è una di esse…

 

Carlo Cardella
Senior Support Engineer
EMEA IIS and Web Developer Support