2009-04-24 21 views
22

Tengo un montón de .NET Webservices ejecutándose en una aplicación IIS. Estos servicios web son consumidos por otra aplicación IIS (frontend). La primera llamada es bastante lenta, de 5 a 10 segundos. Después de eso solo son milisegundos. La primera llamada se considera un problema de rendimiento.ASMX Web Service slow first request

Hemos intentado una aplicación que llame a todos estos servicios web, pero esto obviamente no resuelve nada. Por lo tanto, este no es el reciclaje de aplicaciones predeterminado. Creé una aplicación que simplemente inicializa el servicio varias veces y mide el tiempo que lleva crear una instancia. Antes de ejecutar esta aplicación, me aseguro de que mi aplicación de servicio web se inicie/recicle, luego ejecuto la aplicación. La primera inicialización demora entre 2 y 4 segundos, todas las demás solo son milisegundos.

Otra idea es que creamos una página en la aplicación Frontend que inicia todos los servicios web y que llamamos a esta página antes de que entren los usuarios. No lo considero una solución elegante, ¿qué más puedo probar?

+0

¿Qué sucede en la inicialización del sitio? – jro

Respuesta

34

La demora que se experimenta cuando un cliente está llamando a un servicio web por primera vez es causada por el hecho de que por defecto se necesita compilar un archivo DLL de XmlSerializers para el servicio web. Esto está causando los 2-4 segundos para la llamada inicial. Por supuesto, este es el caso cuando la aplicación del servicio web ya se está ejecutando, si no es así, tendría que reciclar. En ese caso, las otras respuestas podrían ayudar.

Para acelerar la llamada inicial, puede crear el dll XmlSerializers en tiempo de compilación. Puede hacer esto configurando la creación del proyecto 'Generar ensamblaje de serialización' en on. Esto genera un MyApplication.XmlSerializers.dll que contiene la información del servicio web. Ahora la llamada inicial cayó a 300 ms, presumiblemente la carga del dll. Todas las llamadas allí después toman 0 ms.

En Visual Studio, haga clic derecho en su proyecto y seleccione 'Propiedades'. Ve a la pestaña 'Construir'. Allí tiene la opción 'Generar ensamblaje de serialización' en la sección 'Salida'. Si cambia el valor a 'Activado', el ensamblaje de serialización se generará durante el tiempo de compilación.

+1

Interesante. La configuración predeterminada de "Auto" debería hacer esto en tiempo de compilación según los documentos. Me pregunto si está precompilando alguno de los sitios. Precompilar tanto al cliente como al servidor debería resolver todos sus problemas de arranque, supongo. Ahora que entiendo que llamas a un servicio web desde otra aplicación web ... solo quería advertirte sobre eso. El rendimiento es terrible y no escala en absoluto. La serialización de objetos-> jabón sobre http y de objetos soap-> es áspera. –

+0

Entonces, si entiendo esto correctamente, será mejor que siempre generes un dll XmlSerializers para los servicios web que mejoran el rendimiento de la carga inicial sin ningún inconveniente, además de que ahora hay 2 dll's. – freggel

+0

Esto es perfecto, gracias. Para informar servicios específicamente, esto hará una gran diferencia. http://stackoverflow.com/questions/751762/slow-startup-of-sql-reporting-services-2008-in-native-mode – Praesagus

9

La primera vez que llama al servicio web, o la primera vez después de un largo retraso, el servicio web debe iniciarse. Aquí es donde estás viendo la demora. Después de eso, ya se inició y responderá muy rápido a las llamadas. Este es el comportamiento del servicio web estándar.

Puede configurar IIS para que tenga keepalive = true, lo que puede mejorar el rendimiento.

Más información solicitada.

Es posible que los ensamblados de serialización se creen en el tiempo de ejecución. Puede cambiar la configuración del conjunto de serialización utilizando el menú desplegable en la parte inferior del panel Generar de la ventana de propiedades del proyecto.

Podría ser que haya escrito su servicio web para realizar muchas operaciones al iniciar la aplicación, lo que ocurriría la primera vez que se llame a un método en el servicio.

Es posible que la operación sea muy lenta, pero luego está almacenando en caché la respuesta, lo que hace que las llamadas posteriores sean más rápidas.

+0

Esa es una muy buena sugerencia. Lamentablemente, los administradores del sistema tienen una política de reinicio diario. –

+1

@Smazy: ¿conoce su razonamiento para la política? Parece que aún tienen miedo a Win95/98. ¿Requieren que todas las computadoras estén formateadas y que su sistema operativo se reinstale cada 3 meses también? :-D – STW

+0

Hola Praesagus, más información agregada según lo solicitado. – Fenton

4

Eso es típico, ya que las aplicaciones ASP.NET compilan y cargan el directorio bin \ en la memoria al solicitarlo por primera vez.

Cosas que hacer primero:

Quitar todos innecesarios de DLL en el directorio bin. (He visto personas que envían nunit.dll)

Precompile su aplicación ASP.NET para que IIS no lo necesite. Consulte "VS 2008 Web Deployment Project Support Released"

+0

su perfil de persona tiene un mal enlace –

+1

Francamente, ¿y qué? –

2

No estoy seguro de si esto solucionará el giro lento del WS en la "primera vez", ya que supongo que hay una carga de DLL de compilación y .NET cargándose, pero puede eliminar casi cualquier el frío futuro comienza asegurándose de que el grupo de aplicaciones en el que se encuentra WS esté configurado correctamente.

De forma predeterminada, IIS6 ha "reaparecido" en reposo, después de varios minutos o eventos de "reciclaje" que reinician el WS cada vez. Si su feliz el servicio es estable, entonces estos no son necesarios.

Asegurar que el WS tenga su propio grupo de aplicaciones dedicado (no comparte un grupo inapropiado) es también una recomendación sólida.

5

Recientemente descubrí que en nuestros archivos ASMX solo nos referíamos al nombre de la clase. Obtuvimos la implementación del servicio en un ensamblaje diferente para cada archivo ASMX. Esto hace que .NET framework explore todo el bin-folder buscando el ensamblado que contiene la implementación. A medida que su aplicación de servicio web crezca, esto consumirá más tiempo. Esto se puede resolver no solo incluyendo el nombre de clase en su definición ASMX sino también el nombre del ensamblado.

Nuestra ASMX veía así:

<%@ WebService Language=”C#” CodeBehind=”MyService.cs” Class=”MyWebservice” %>

Si lo cambia para incluir el conjunto que contiene la aplicación que se vería así. Esto nos ahorró alrededor del 10% de nuestra carga inicial de la aplicación del servicio web.

<%@ WebService Language=”C#” CodeBehind=”MyService.cs” Class=”MyWebservice, MyWebservice.Implementation.Assembly” %>

+0

¡Gracias por la actualización de esto! –

1

Después de varias horas de pruebas loco, i ha sido capaz de reducir el servicio web primero a ejecutar tiempo de ejecución para desnudar mínimo de dos de host en la misma clase IP (por debajo de 300 ms) ....

Experimenté al principio un retraso inicial de 2-3 segundos en la primera llamada al servicio web, que cualquier llamada posterior del mismo proceso para ser muy rápido.

La clave para entender el retraso en mi caso fue cómo el cliente maneja WEB PROXY !!

Ésta es mi nueva unión en el archivo app.config:

<basicHttpBinding> 
    <binding name="CreateContextSoap" closeTimeout="00:01:00" openTimeout="00:01:00" 
     receiveTimeout="01:00:00" sendTimeout="01:00:00" allowCookies="false" 
     bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" 
     maxBufferSize="16777216" maxBufferPoolSize="524288" maxReceivedMessageSize="16777216" 
     messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" 
     useDefaultWebProxy="false"> 
     <readerQuotas maxDepth="32" maxStringContentLength="1048576" maxArrayLength="16384" 
      maxBytesPerRead="65536" maxNameTableCharCount="16384" /> 
     <security mode="None"> 
     <transport clientCredentialType="None" proxyCredentialType="None" 
      realm="" /> 
     <message clientCredentialType="UserName" algorithmSuite="Default" /> 
     </security> 
    </binding> 
    </basicHttpBinding> 

La primera ejecución WebCall i supone que debe ser mucho más lento debido a canal de transporte necesita para descubrir la configuración del proxy en la inicialización, con el fin de conectar de forma transparente a internet . Esto por lo general no es necesaria en el entorno de intranet, por lo tanto he cambiado estos valores vinculantes para evitar el uso del proxy predeterminado (descubrí automáticamente de la configuración del explorador):

bypassProxyOnLocal = "false"

useDefaultWebProxy = "false "

El tiempo de conexión de la primera llamada ahora se reduce en gran cantidad. Espero que esto ayude.

0

Disculpe el necro agregar, pero esta ha sido una lucha constante para mí también, y quería agregar algo de información a la imagen. VisualStudio en sí mismo agrega un componente bastante grande al tiempo. Aquí está la prueba básica, que implica una aplicación escueto formas y un servicio web ya se encuentra corriendo alojado internamente en un servidor de la empresa (con Generar ensamblado de serialización establece en true para todas las pruebas):

Running in VS, Debug: 
    First Call: 400 ms to set up client object, 450 to call function 
    Second Call: 1 ms to set up client object, 14 to call function 
Running as .exe, Release: 
    First Call: 20 ms to set up client object, 70 to call function 
    Second call: 1 ms to set up client object, 4 to call function 
Running the Debug's .exe file outside of vs: 
    First Call: 20 ms to set up client object, 80 to call function 
    Second call: 1 ms to set up client object, 4 to call function 
Running as Release within VS: 
    Similar results to Debug in VS -- very slow 

Breve historia? Visual Studio está agregando un gran pedazo de tiempo a la imagen. En lugar de ~ 90 ms, tarda casi un segundo. Por lo tanto, si está afinando el rendimiento, asegúrese de realizar las pruebas fuera del entorno de VisualStudio.