Artículo
· 28 oct, 2024 Lectura de 3 min

Soluciones para los Timeouts en Servicios SOAP

Hola a todos, hoy comentamos con un ejemplo cómo solucionar problemas relacionados con el TimeOut cuando se hacen llamadas a servicios SOAP.

Tomemos como ejemplo aplicaciones que proporcionen servicios SOAP que utilizan consultas SQL basadas en "DSTIME" para devolver registros que han sido añadidos o modificados recientemente. Como estos registros no cambian con frecuencia, estas consultas suelen devolver un número reducido de registros, lo cual implica un tiempo de procesamiento corto.

Sin embargo, en ocasiones realizamos cambios en una tabla que afectan a todos los registros en ella. Cuando eso ocurre, en la siguiente solicitud SOAP de un cliente, el servicio ejecutará su consulta, la cual tomará un tiempo adicionalmente largo porque incluirá todos los registros (en nuestras aplicaciones, las consultas devuelven cientos de miles de registros en este caso).

La cantidad de tiempo necesario para generar los resultados a veces supera el "timeout" predeterminado especificado en la conexión del gateway CSP para la instancia que aloja el servicio SOAP. Esto provoca que la conexión se cierre antes de que el cliente reciba los datos solicitados, y en su lugar, el cliente obtiene un mensaje de error como el siguiente:

ERROR #5002: ObjectScript error: InvokeClient+208^%SOAP.WebClient.1

El error se debe a un timeout. Esto podemos confirmarlo revisando los detalles del InterSystems IRIS SOAP Log.

En este caso, el log de mostraba esta información:

Input to Web client with SOAP action = http://www.intersystems.com/user/SOAPTest.SlowSOAPService.GetSlowService

ERROR #5922: Timed out waiting for response
string**** SOAP client return error. method=GetSlowService, action=http://www.intersystems.com/user/SOAPTest.SlowSOAPService.GetSlowService
     ERROR #5922: Timed out waiting for response

Para resolver este error, podemos añadir código para establecer un timeout de conexión en la instancia del cliente SOAP antes de llamar al método SOAP que utiliza esa consulta específica.

Habíamos ejecutado la consulta en la página SQL del Portal de Administración, exportando el resultado a un archivo CSV, y observamos que tardó más de 6 minutos en completarse. Por lo tanto, añadimos este código para aumentar el timeout a 10 minutos antes de llamar al servicio (los nombres se han cambiado para proteger a los inocentes 😊):

    #dim result As %XML.DataSet
    set wc = ##class(SlowSOAPService.WebClient.SlowSOAPServiceSoap).%New()
    set sc = wc.TimeoutSet(600)
    set sc = wc.GetSlowService(.result)

La clase `%SOAP.WebService` proporciona el método “TimeoutSet”, que solo cambia el valor de timeout de conexión para esa solicitud específica. No afecta el valor de timeout de la conexión del gateway CSP, que por defecto es un breve período de 30 segundos (para incentivar la escritura de código eficiente en el lado del servidor).

De hecho, para mantener ese incentivo, podemos asegurarnos de que el timeout extendido solo se utilice en los casos excepcionales en los que sea necesario, envolviendo el código del cliente en un condicional que verifique una variable global, de la siguiente manera:

    #dim result As %XML.DataSet
    set wc = ##class(SlowSOAPService.WebClient.SlowSOAPServiceSoap).%New()
    if (^reallySlowSvcExpectedTime > 0) {
        set sc = wc.TimeoutSet(^reallySlowSvcExpectedTime)
    }
    set sc = wc.GetSlowService(.result)

La global actúa tanto como un indicador (¿es mayor que 0? entonces establece el timeout) y como el número de segundos a esperar. Para el problema descrito al inicio de este artículo, notificaríamos a los clientes que deben configurar temporalmente una variable global utilizando un terminal IRIS conectado a su instancia de la siguiente manera:

    set ^reallySlowSvcExpectedTime = 600

Una vez que esperemos nuevamente a que el servicio devuelva rápidamente una pequeña cantidad de datos, los clientes pueden restablecerse para usar el timeout predeterminado configurando la variable global de nuevo a 0:

    set ^reallySlowSvcExpectedTime = 0
Comentarios (0)1
Inicie sesión o regístrese para continuar