¿Dónde quedó el usuario ASPNET en Windows Vista? ¿Y qué $#!N&@2 es eso de los Application Pools?

viernes 25 de enero de 2008

Hoy aprendí algunas cosas más al continuar con mis aventuras de desarrollo ASP.NET en Windows Vista.  Muchas de estas cosas aparentemente no son nuevas, vienen desde IIS 6 que era la versión incluida con Windows Server 2003, pero yo nunca los usé, así que hasta ahora me vengo enterando.

La primer lección salió cuando andaba buscando el usuario ASPNET de mi máquina para asignarle permisos de escritura sobre un directorio donde mi aplicación permite que los usuarios suban archivos.  Después de un rato de jugar Where's Waldo con el usuario, me convencí que simplemente no existía.  Resulta que el ASP.NET Worker Process—el proceso bajo el cual se ejecuta el código de ASP.NET—corre ahora por default bajo la cuenta NETWORK SERVICE (aunque esto se puede cambiar fácilmente).  Ah, y por cierto, el Worker Process ahora se llama w3wp.exe, en lugar de aspnet_wp.exe.

La segunda lección vino cuando quise correr mi aplicación.  Resulta que si usas módulos HTTP (<httpModules>) en tu web.config, recibirás un mensaje de error porque IIS 7 intenta correr las aplicaciones por default en un Application Pool llamado—duh—DefaultAppPool, y éste tiene un Managed Pipeline Mode puesto a Integrated.

¿Güat?  A ver si me puedo explicar.  Si abres la consola administrativa de IIS y te vas a Application Pools, verás algo como esto:

De cajón, Vista traía los dos primeros—Classic .NET AppPool y DefaultAppPool.  El tercero fue creado cuando instalé SQL Server Reporting Services, así que por ahora ignóralo.

Lo primero que me pregunté fue ¿qué $#!N&@2 demonios es eso de los Application Pools?

Resulta que es una manera muy padre de segregar y asignar una aplicación Web—o más correctamente su Application Domain—a un Worker Process determinado.  Un Pool puede tener varios AppDomains, y estos estarán separados de los que corran en otros pools. Considera este ejemplo:

 

Aquí tenemos tres aplicaciones de ASP.NET, cada una con su directorio virtual.  Las primeras dos están asignadas al primer Application Pool, y la tercera aplicación está asignada al segundo.  Esto es EXCELENTE por varias razones:

¿Que pasaba antes si una falla en una de las aplicaciones web hacía que se reciclara el Worker Process?  Pues todas las aplicaciones se "reiniciaban"—botando posiblemente a las sesiones y todo el show—porque los Application Domains están corriendo en el mismo proceso ejecutable. Me ha pasado. Teníamos una applicación Web corriendo en el mismo servidor que un servicio Web (en una máquina con Windows 2000 si mal no recuerdo), y de vez en cuando la aplicación hacía que se reciclara el Worker Process—maldito Crystal Reports—llevándose entre las patas al Web Service.  Ahora es posible asilar ese tipo de fallas.

¿O qué pasaría si quiero correr una aplicación de ASP.NET v1.x en el mismo servidor que una de ASP.NET v2.x?  Un Worker Process solo puede correr una versión del .NET Framework, hasta donde sé, así que con Application Pools ahora puedes lograrlo.

Y más relevante para el problema que yo tenía, IIS 7 tiene una manera distinta de manejar los httpModules—llamado Managed Pipeline Mode. DefaultAppPool usa Integrated. Así que lo que tenía que hacer en mi caso era asignar el directorio virtual de mi aplicación al Classic .NET AppPool que utiliza el modo Classic, para no tener que cambiar la configuración (y posiblemente código) de mi aplicación.

Si inspeccionas las opciones avanzadas de un Application Pool te das cuenta que puedes configurar cosas interesantes. 

Las que me llamaron la atención fueron:

  • .NET Framework Version. Para seleccionar qué versión quieres utilizar para las aplicaciones Web que corren en el Pool, o si no quieres permitir que corra código administrado (p.ej. una aplicación de ASP clásico o PHP que no tenga nada que ver con .NET).
  • Managed Pipeline ModeIntegrated utiliza el modo IIS 7, donde la configuración de los httpModules están centralizados y supuestamente tiene varios beneficios que aún no conozco; Classic permite que cada aplicación web mantenga su configuración.
  • Identity.  La cuenta de usuario y bajo el cual corre el Worker Process. Esto afecta directamente los permisos de seguridad de las aplicaciones en el Pool.  Los valores posibles son: NetworkService, LocalService, LocalSystem, SpecificUser; este último por si quieres especificar una cuenta creada por ti.
  • Identity Specific User Credentials.  Para poner las "credenciales" (el password pues) del usuario si usas Identity=SpecificUser.
  • CPU Limit, Limit Interval y Limit Action.  Sirven para limitar el porcentaje de CPU que consume el Worker Process en un tiempo determinado y hacer algo si se excede, como por ejemplo, matarlo.
  • Private Memory Limit y Virtual Memory Limit.  Sirven para limitar la memoria real y virtual que utiliza el Worker Process. ¿Alguna vez le has pegado a un System.OutOfMemoryException? Yo si, y no es divertido.

Una vez que comencé a entender este rollo, asignar mi aplicación al Pool correcto fue súper sencillo.  Simplemente te vas a las opciones avanzadas de tu directorio virtual y lo cambias.

 

Enjoy smile_shades

categorías: , , ,

11 comentarios:

  1. Anónimo dijo:

    hey que ondas gracias x tu explicacion me sirvio de musho de verdad he aprendido mucho de vs mira crees q no nos podemos contactar x msn o correo electronica para sacar unas dudas en cuanto a asp.net y windows vista si t parece mi correo es iori_lfm747@hotmail.com

  2. Carlos Rubalcava dijo:

    Qué onda Anónimo... Sabes que no uso messenger, pero en lo que pueda ayudarte por e-mail con gusto lo haré.

    Quizá también podrías considerar poner tus preguntas en el foro de la Comunidad .NET.
    http://comunidadnetjuarez.org/forums/

    Ahí hay más personas que podrían contestar (muchas veces ando ocupado y tardo en responder correos x que me llegan un chorro)

    :-)

  3. francisco dijo:

    hola carlos, una pregunta antes de todo, la explicacion que estas dando para que version de widonws vista es? veras que cuando reviso mi administrador de tareas no encuentro w3wp.exe, y por otro lado cuando reviso las configuraciones avanzadas no encuentro el tag Behavior donde esta el cambio del Application Pool... por favor me podrias ayudar en esto... gracias

  4. Carlos Rubalcava dijo:

    Qué tal Francisco--Yo uso la versión Enterprise, pero hasta donde sé debe también funcionar en la versión Business y Ultimate (no creo que la Home traiga IIS, pero no estoy seguro).

    Asumiendo que instalaste todos los componentes requeridos (tengo este otro artículo al respecto), el Worker Process (w3wp.exe) sólo lo verías después de que está al menos una aplicación de ASP.NET corriendo (es decir después del primer request a cualquier sitio ASP.NET que esté corriendo en la máquina).

    Finalmente, para acceder a esa opción de cambiar el App Pool, la manera más sencilla que conozco es: (usando el IIS 7 manager que viene con Vista, no el viejito para IIS 6) dar clic derecho a mi virtual directory en el arbol de connections que aparece del lado izquierdo y seleccionar Advanced Settings.

    Espero te ayude

  5. k dijo:

    jajaj si.. cuando monte una aplicacion que funcionaba con Freamework 1.x me volví chango hasta que encontre mi amante sin rostro llamado "clasic dot net"

  6. pablo dijo:

    Hola,
    Mi duda no tiene mucho que ver con el hilo actual, pero de todas formas ahí va!.
    Tengo claro que el ASP.NET Worker Process (aspnet_wp.exe IIS 5) es el proceso bajo el cual se ejecuta el código de ASP.NET.
    1.-HILOS:
    Cuando se lanza una página ASP.NET se consume un subproceso del grupo de Subprocesos del ASP.NET Worker Process. ¿Es esto correcto?. ¿Es el aspnet_wp.exe quién administra los subprocesos?...si esto es así...(suponiendo que este en lo cierto)....¿Cuantos subprocesos dispone el aspnet_wp.exe para suministrar por servidor, no por aplicación?. Quiero significar que puede haber varias aplicaciones Web corriendo bajo el mismo aspnet_wp.exe.

  7. pablo dijo:

    2.-PÁGINAS ASINCRÓNAS:
    Se está ejecutando una página ASP.NET (por lo tanto estamos consumiendo un subproceso del grupo de subprocesos). 1ª caso: Realizamos una llamada a SQLSERVER de forma asíncrona mediante el atributo ASYNC=TRUE. Se libera el subproceso de la página, que retorna al grupo de subprocesos mientras dure la llamada a base de datos. ¿Quién gestiona el proceso de SQLSERVER?, es un proceso fuera del aspnet_wp.exe?; entiendo que aspnet_wp.exe no suministra un subproceso de su grupo de subprocesos al SQLSERVER. 2ª caso: llamamos a un método que realiza una simulación de Montecarlo (o cualquier tarea muy pesada pero que, por defecto, no tenga soporte asíncrono-véase SQLSERVER o WebServices). Como no hay soporte asíncrono “por defecto”, creamos nosotros esa funcionalidad para lanzar este método asincrónicamente utilizando System.Threading. Cuando la página ASP.NET llega al punto donde se lanza este método asíncrono, se libera el subproceso de la página ASP.NET que retorna al grupo de subprocesos. Pero, Quién gestiona el nuevo subproceso lanzado?. Entiendo que en este caso es aspnet_wp.exe quien suministra un subproceso (que realiza la simulación de montecarlo) de su grupo de subprocesos. Realmente, en este caso, no estamos liberando ningún subproceso, porque el subproceso que liberamos de la página ASP.NET lo estamos utilizando el lanzar el nuevo Thread (Esto restaría escalabilidad a la aplicación ASP.NET). ¿Cómo solventar este problema? Como lanzar una tarea pesada sin consumir un subproceso del grupo de suprocesos de aspnet_wp.exe.

  8. Carlos Rubalcava dijo:

    Pablo--
    ¡Qué buenas preguntas!

    Sobre la primera: sí, esos "subprocesos" (AppDomains) son administrados por el Worker Process y puedes tener tantos, como te alcance la memoria del servidor. No son "procesos" en el sentido tradicional, es decir, no los verías en el task manager. En IIS 5 no había los App Pools, había un solo WP (que es lo que intenté explicar con este post). El concepto de AppDomain no es exclusivo a aplicaciones Web, es un concepto básico del Framework. Puedes ver este otro artículo que escribí al respecto.

    Respecto a la segunda pregunta: No estoy completamente seguro. Cada Worker Process o AppDomain tiene un Pool de hilos, es decir, una cantidad X de hilos disponibles. Cuando recibe un request, utiliza uno de ellos para procesarlo y luego de completar el ciclo de ejecución de la página lo regresa al Pool. En el caso de las llamadas asíncronas, lo que acaba sucediendo por debajo del agua (me imagino) es que le da un callback a donde le regresa la "llamada". Así que no hay necesidad de bloquear el thread (digo, ese es el propósito, ¿no?). El mismo Framework se encarga de los mecanismos para activar un thread que atienda ese callback (como tú mencionaste, eso también podrías hacerlo a mano con las clases de System.Threading, pero en este caso no hay necesidad de hacerlo, hasta donde sé).

  9. Diego Pallares dijo:

    Muy bueno el articulo, pero lo descubri algo tarde y ya experimente con todo ello. Pero ahora te planteo una cuestion, tengo una aplicacion de tipo webservice, la publico en un XP y funciona de maravilla, la publico en un vista ultimate, y aun poniendo lo que comentas y asignado el NETWORK SERVICE, me da error en la libreria system.security.permissions.StorePermision debo creer que es porque el usuario utilizado en XP es el ASPNET y con la herramiente winhttpcert instalo el certificado en el usuario ASPNET, pero en vista esa herramienta ya no existe y se debe usar la MMC con el complemento de certificados para instalarlo en la machine.local Pero donde va el usuario NETWORK SERVICE a buscar el certificado? tiene los permisos necesarios para que la ACL le deje usar el Etore de certificados?

    VEnga a ver si este reto lo superamos.

    y gracias

  10. Carlos Rubalcava dijo:

    Diego--
    Pues aún no se me ha ofrecido, pero parece que hay de dos sopas.

    La primera y más sencilla sería cambiarle el usuario (Identity) a ese Application Pool para que corra bajo System y no como NetworkService (en una de las imágenes del artículo se ve esa sección). Sin embargo esto potencialmente sería un riesgo de seguridad (lo cual para desarrollo en tu máquina puede que no sea gran riesgo, pero si lo quieres poner en un servidor pues es otro boleto).

    La segunda involucra bajar una herramienta llamada WinHttpCertCfg.exe (parte del Windows 2003 Resource Kit, pero puedes bajarlo por separado) y utilizarla para darle los permisos apropiados al usuario NetworkService. Este es un proceso no-trivial, pero Rick Strahl lo cubrió hace rato en un excelente post al respecto (ve la sección que dice "IIS Permission Requirements - Adding NETWORK SERVICE").

    Espero te ayude.

  11. Mario dijo:

    Buenisimo, muchas gracias!