Webservice con PHP + IIS y error 500

Se incorporó
21 Marzo 2022
Mensajes
115
Tengo un webservice simple desarrollado con PHP 7.4 corriendo bajo IIS 8.5 en un servidor Windows Server 2012 R2, dentro de una LAN. El webservice consume a su vez un webservice externo de facturacion electronica (Panama), y funciona todo bastante bien... excepto que dia por medio el servidor IIS cae en un estado de error 500 del que solo sale si se reinicia el IIS o el AppPool asociado al webservice (es un AppPool dedicado asi que ninguna otra app en el IIS corre ahi).

Antes era mas frecuente pero yo modifique el AppPool para que se reciclara automaticamente todos los dias en la madrugada y eso ayudo, pero ahora tengo que ver porque razon el webservice causa que el AppPool quede en estatus 500, y no tengo idea de por donde empezar a buscar para ver que es lo que puede estar pasando.

Alguna idea ? logs de PHP o IIS que pueda revisar ?

Gracias de antemano
 

buhoblue

Casi-gamer
Se incorporó
30 Septiembre 2020
Mensajes
677
  1. Revisión de los logs de PHP: Comienza por examinar los registros de PHP en busca de posibles errores durante el período en que ocurre el error 500. Estos registros suelen encontrarse en una ubicación como C:\php\logs\php_errors.log, aunque puede variar según la configuración de PHP.
  2. Logs de IIS: También es importante revisar los registros de IIS en C:\inetpub\logs\LogFiles, específicamente los correspondientes al sitio web donde está alojado tu webservice.
  3. Configuración de PHP: Verifica el archivo php.ini para asegurarte de que la configuración de PHP sea adecuada para tu servicio web.
  4. Monitoreo de recursos: Utiliza herramientas de monitoreo para verificar si el webservice está consumiendo una cantidad inusual de recursos como CPU o memoria, lo que podría provocar el error.
  5. Revisión del código: Analiza el código de tu webservice en busca de posibles errores, prestando especial atención a las llamadas al webservice externo y cómo se manejan los errores.
  6. Configuración de IIS: Asegúrate de que la configuración de IIS esté óptima para manejar el tráfico y las solicitudes del webservice.
  7. Actualizaciones y parches: Mantén actualizados tanto PHP como IIS con los últimos parches de seguridad y actualizaciones para prevenir problemas de estabilidad.
quizas podrias probar con algo de lo mencionado arriba.
 
Upvote 0

Kitsune

Fanático
Se incorporó
5 Mayo 2006
Mensajes
1.029
Si el iis te da el 500 mira su log ahi debe estar la causa. compartelo para mirar

(Y porque con IIS?)
si es un simple, no podrías servirlo con apache o ngnix?
 
Upvote 0
Se incorporó
21 Marzo 2022
Mensajes
115
Si el iis te da el 500 mira su log ahi debe estar la causa. compartelo para mirar

(Y porque con IIS?)
si es un simple, no podrías servirlo con apache o ngnix?
Y si. El tema es que ese servidor es del cliente y ellos tiene varios modulos Web hechos con .NET funcionando en ese IIS, entonces por simplicidad se decidio usar el IIS en lugar de tener que administrar un 2do webserver.
 
Upvote 0
Se incorporó
21 Marzo 2022
Mensajes
115
  1. Revisión de los logs de PHP: Comienza por examinar los registros de PHP en busca de posibles errores durante el período en que ocurre el error 500. Estos registros suelen encontrarse en una ubicación como C:\php\logs\php_errors.log, aunque puede variar según la configuración de PHP.
  2. Logs de IIS: También es importante revisar los registros de IIS en C:\inetpub\logs\LogFiles, específicamente los correspondientes al sitio web donde está alojado tu webservice.
  3. Configuración de PHP: Verifica el archivo php.ini para asegurarte de que la configuración de PHP sea adecuada para tu servicio web.
  4. Monitoreo de recursos: Utiliza herramientas de monitoreo para verificar si el webservice está consumiendo una cantidad inusual de recursos como CPU o memoria, lo que podría provocar el error.
  5. Revisión del código: Analiza el código de tu webservice en busca de posibles errores, prestando especial atención a las llamadas al webservice externo y cómo se manejan los errores.
  6. Configuración de IIS: Asegúrate de que la configuración de IIS esté óptima para manejar el tráfico y las solicitudes del webservice.
  7. Actualizaciones y parches: Mantén actualizados tanto PHP como IIS con los últimos parches de seguridad y actualizaciones para prevenir problemas de estabilidad.
quizas podrias probar con algo de lo mencionado arriba.
Gracias por tu respuesta. Me diste monton de cosas que verificar. Luego les comento lo que encuentre. Con respecto al punto 5, como dije el webservice es muy simple: expone unos 3 endpoints, cada uno de los cuales envia un request al webservice externo, maneja la respueta y devuelve una respuesta "curada y estandarizada" de vuelta al cliente original. En todo momento se usa TRY-CATCH para el manejo de errores de modo que los endpoints devuelvan siempre una respuesta consistente tanto si todo salio OK como si ocurrio un error local o remoto.
 
Upvote 0

freishner

Capo
Se incorporó
16 Noviembre 2021
Mensajes
303
En todo momento se usa TRY-CATCH para el manejo de errores de modo que los endpoints devuelvan siempre una respuesta consistente tanto si todo salio OK como si ocurrio un error local o remoto.
Una acotación: No todo en php es gestionable desde el bloque try-catch sin hacer algo mas, yo por lo general para asegurarme uso @función para esconder los warnings/notices y verifico que el result de lo que llamo si es que devuelve algo, sea distinto a lo que devolvería si hubiera un error.

Un ejemplo de un error
PHP:
try {
    $data = brotli_uncompress("test");
} catch (Exception $e) {
    var_dump($e);
}

PHP Warning:  brotli_uncompress(): Brotli decompress failed
 in php shell code on line 1

Warning: brotli_uncompress(): Brotli decompress failed
 in php shell code on line 1

var_dump($data); // -> bool(false)

Como es un error gestionado intencionalmente y no funciona el bloque try-catch, antepongo el @ para ocultar los mensajes y evitar la contaminación innecesaria del log de errores. Luego en el if lanzo la excepción manualmente.

PHP:
try {
    // Un error cualquiera
    $data = @brotli_uncompress("test");
    if ($data == false)
        throw new Exception("excepción custom para gestionar");
} catch (Exception $e) {
    // volvemos acá como se quería originalmente
    var_dump($e);
}

Así me he solucionado un montón de dolores de cabeza, y me ahorro harto tiempo, porque por una parte, sabes que algo va a fallar de antemano y por otra, cuando llegues al log de errores, solo verás lo que importa.
 
Upvote 0
Se incorporó
21 Marzo 2022
Mensajes
115
Una acotación: No todo en php es gestionable desde el bloque try-catch sin hacer algo mas, yo por lo general para asegurarme uso @función para esconder los warnings/notices y verifico que el result de lo que llamo si es que devuelve algo, sea distinto a lo que devolvería si hubiera un error.

Un ejemplo de un error
PHP:
try {
    $data = brotli_uncompress("test");
} catch (Exception $e) {
    var_dump($e);
}

PHP Warning:  brotli_uncompress(): Brotli decompress failed
 in php shell code on line 1

Warning: brotli_uncompress(): Brotli decompress failed
 in php shell code on line 1

var_dump($data); // -> bool(false)

Como es un error gestionado intencionalmente y no funciona el bloque try-catch, antepongo el @ para ocultar los mensajes y evitar la contaminación innecesaria del log de errores. Luego en el if lanzo la excepción manualmente.

PHP:
try {
    // Un error cualquiera
    $data = @brotli_uncompress("test");
    if ($data == false)
        throw new Exception("excepción custom para gestionar");
} catch (Exception $e) {
    // volvemos acá como se quería originalmente
    var_dump($e);
}

Así me he solucionado un montón de dolores de cabeza, y me ahorro harto tiempo, porque por una parte, sabes que algo va a fallar de antemano y por otra, cuando llegues al log de errores, solo verás lo que importa.
Veo que usas Exception en el catch, pero yo uso Throwable porque alguna vez me paso que Exception no capturaba ciertos errores. Es correcto esto ? o deberia cambiar de nuevo a Exception ? Yo no trabajo con PHP permanentemente sino solo cuando el cliente lo pide o resulta lo mas conveniente para lo que se quiere hacer en un momento dado.
 
Upvote 0

freishner

Capo
Se incorporó
16 Noviembre 2021
Mensajes
303
Veo que usas Exception en el catch, pero yo uso Throwable

Es mas una costumbre legacy de la era PHP 5.x, Throwable no existía antes de PHP 7. Pero desde 7 en adelante Throwable es la clase base para cualquier tipo de clase lanzable como una excepción vía throw. (Tal y como explica la página de Throwable).

No obstante, para efectos de gestión de errores, en el caso anterior la excepción seguiría sin saltar.

PHP:
try {
    $data = brotli_compress();
} catch (Throwable $t) {
    var_dump($t);
}
PHP Warning:  brotli_compress() expects at least 1 parameter, 0 given in php shell code on line 1

Warning: brotli_compress() expects at least 1 parameter, 0 given in php shell code on line 1
var_dump($data); // -> bool(false)

Acá te puedes ver un árbol con las excepción que heredan de Throwable. Pero el tema en PHP no va mucho por lo que puedas o no lanzar como excepción, si no por evaluar el tipado que tu esperabas. Lo que no significa que el control de errores no lo puedas gestionar manualmente con una excepción.

En desarrollo pudieras jugar con las asersiones, pero hay que toquetear el apartado "[Assertion]" en el php.ini respectivo al uso que les estés dando. Si en local trabajas con php a secas, el php.ini de cli es el que debes tocar y dejarlo así para que lanze excepciones sin warnings. (Si miraste el árbol, habrás visto una excepción llamada "AssertionError" que es la que saltará cuando la aserción no se cumpla).

INI:
zend.assertions = 1
assert.active = On
assert.exception
assert.warning = Off

De éste modo, para validar los tipos y valores de todo lo que tengas que validar, en desarrollo (zend.assertions por defecto viene en -1, el valor de producción), se traduciría en ésto:

PHP:
try {
    $data = @brotli_compress();
    assert(is_string($data));
} catch (Throwable $t) {
    var_dump($t);
}

En producción, para ahorrarte código pudieras tener algo así para gestionar validaciones y lanzar excepciones

PHP:
define('T_TYPES_FN', ['is_string', 'is_int', ...]);
define('T_STRING', 0);
define('T_INT', 1);
// define('T_ ...
function val_type($expected_type, $var, $throwable) {
    // validaciones respectivas ...

    $fn = T_TYPES_FN[$expected_type];

    if ( $fn($var) )
        // throw new $throwable("test") ...
}

// Siguiendo el ejemplo del bloque anterior
try {
    $data = @brotli_compress();
    val_type(T_STRING, $data), "Throwable");
} catch (Throwable $t) {
    var_dump($t);
}

Para las clases es mas o menos lo mismo, pero la mayoría de funciones en php, suelen devolver un bool, int o null en caso de error. Aunque lo puedes extender todo lo que quieras.
 
Upvote 0
Subir