• Publicidad

Problema con tiempos ejecución CGI (timeout)

Todo lo relacionado con el desarrollo Web con Perl: desde CGI hasta Mojolicious

Problema con tiempos ejecución CGI (timeout)

Notapor Alfumao » 2013-06-21 07:05 @337

Hola a todos,

Tengo un problema: ejecuto un programa de Perl desde un cgi (es un cgi que entre otras cosas llama a un programa de Perl para ejecutarlo (ejecución típica: línea de comandos, con opciones y tal). El programa hace sus funciones y devuelve los resultados en los directorios esperados del servidor. El problema es que el CGI se queda colgado (la ejecución del programa depende de que éste a su vez descargue datos de un servidor de acceso público remoto, y eso tarda bastante tiempo) y no devuelve los resultados al usuario.

Mis preguntas son:

- ¿Puede influir el tiempo de ejecución del programa en que se cuelgue el CGI?
- De ser así, ¿cuál es la manera óptima o sino la más sencilla de evitar esto?
- ¿Se puede hacer que la página se refresque cada N segundos y conseguir evitar el susodicho problema del "cuelgue"?

Seguro que me he dejado muchas posibilidades de actuación para arreglar esto... os agradezco sugerencias.

Un saludo y gracias por adelantado.
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Publicidad

Re: Problema con tiempos ejecución CGI (timeout)

Notapor explorer » 2013-06-21 07:55 @371

El servidor web podría tener limitado el tiempo de ejecución.

Por ejemplo, en muchos proveedores de alojamiento, tienen configurado que el servidor web no debe permitir un tiempo máximo de funcionamiento de un proceso arrancado por él, de uno, tres o cinco minutos. Podrías hablar con el administrador, para que lo amplíe.

Lo que se suele hacer es dividir el problema en dos partes: la primera ejecución del CGI lanza el proceso lento, y regresa inmediatamente al usuario, con una página HTML equipado con un refresh (en la cabecera) o con un sistema Ajax, para hacer nuevas consultas al CGI (u otro CGI) para comprobar la resolución del primer proceso. Si no ha terminado, devuelve la misma página con el mismo refresh o un resultado negativo al Ajax. Cuando el proceso, en cambio, dice que ha terminado, entonces devolvemos una página con los resultados, o al Ajax le damos un resultado positivo, y entonces en la página actúa cargando nuevo contenido con el resultado.

No tiene por qué ser un solo CGI el que reciba todas las peticiones. Puedes dividir el problema en varios, según el paso en que se encuentre la petición. Y tener en cuenta los posibles causas de fallo.

En Perl, puedes usar CGI::Ajax por si quieres hacerlo de esa manera. Algo de programación de JavaScript también deberás poner.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Problema con tiempos ejecución CGI (timeout)

Notapor Alfumao » 2013-07-12 02:40 @152

Hola, explorer, a ver si me he enterado bien del asunto, porque es un poco complejo de entender para mí ;)

La forma más simple sería lanzar el proceso lento (con el CGI principal) y hacer el HTML con el Refresh que cada minuto se actualice y pregunte al servidor si ya están los resultados, ¿no?

Como el tema de Ajax me es totalmente desconocido, estuve mirando la información del módulo que me pasaste, pero sigo sin aclararme mucho. ¿Sería posible hacer el refresh de una forma muy simple sin necesidad de usar Ajax? Hay que tener en cuenta que el proceso puede tardar hasta una hora en hacerse por completo... ¿Cómo se haría para enviar un correo al usuario una vez que estén listos los resultados (a la vez que se deja la página con el CGI del refresh en pantalla)?

Gracias de nuevo por adelantado :D
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Re: Problema con tiempos ejecución CGI (timeout)

Notapor explorer » 2013-07-12 06:06 @296

El esquema sería:
  • El usuario pide un recurso CGI al servidor, que lanza el proceso largo. Este cgi lo que hace es devolver una página de información al usuario, con el texto de que se ha iniciado el proceso. En la cabecera del HTML también pone algo como esto:
    Sintáxis: [ Descargar ] [ Ocultar ]
    Using html4strict Syntax Highlighting
    1. <meta http-equiv="refresh" content="30;URL=http://servidor/cgi-bin/ya_esta.pl" />
    Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
    A continuación, cierra (close) las salida y entrada estándar (STDIN, STDERR y STDOUT) y lanza el proceso largo (con un system() o con un exec()). Supondremos que el proceso largo deja algún archivo temporal o algún archivo que indique su progreso. O que podamos medir de alguna manera cómo va.
  • El HTML llega al navegador del usuario. El usuario ve el mensaje de que se ha iniciado. El propio navegador, a los 30 segundos, ejecuta la llamada al recurso /cgi-bin/ya_esta.pl, que es otro cgi que se encargará de ver el estado del progreso del proceso largo.
  • Si el proceso largo no ha terminado, ya_esta.pl devolverá un HTML con el mismo encabezado <meta> anterior (para que sea llamado de nuevo dentro de 30 segundos), y con un contenido que informe al usuario de cómo va el proceso.
  • Si el proceso ha terminado, ya_esta.pl devuelve una sencilla página HTML informando al usuario de que ha terminado todo, incluso puede sacar los resultados, envía el correo de aviso, y termina (no envía el <meta> porque ya no hace falta refrescar más).
Para enviar correo se puede usar alguno de los módulos para enviar correo. Por ejemplo, Mail::Send:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. use Mail::Send;
  2.  
  3. my $msg = Mail::Send->new(
  4.     To       => '[email protected]',
  5.     Subject  => 'Fin proceso largo',
  6. );
  7.  
  8. $msg->add('From', 'administrador <root@servidor>');
  9. $msg->add('Content-Type', 'text/plain; charset=UTF-8');
  10.  
  11. my $fh = $msg->open;
  12. print $fh "Se ha terminado el proceso largo.";
  13. $fh->close;
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
(Naturalmente, depende del medio de transporte de correo disponible en tu máquina. En el ejemplo, sí que está instalado un servidor local, así que Mail::Send le envía a él el correo a transportar).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Problema con tiempos ejecución CGI (timeout)

Notapor Alfumao » 2013-07-17 06:36 @317

Gracias explorer,

Ha funcionado de maravilla, ¡eres la leche!

Ahora tenemos un problema con las ejecuciones simultáneas...

¿Hay alguna forma de que podamos crear una cola de procesos para evitar que interfieran entre sí?

Muchas gracias una vez más.
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Re: Problema con tiempos ejecución CGI (timeout)

Notapor explorer » 2013-07-17 07:57 @373

Puedes hacer que los nuevos trabajos entren en una cola, por ejemplo en una base de datos, o en un simple directorio de trabajo. Y luego, un proceso monitor, se encarga de coger un trabajo desde la cola, y mandarlo procesar. O procesar tantos como núcleos de procesamiento existan. El proceso monitor lo puedes ejecutar de forma periódica, por ejemplo colgándolo del cron, para que se ejecute cada minuto o cada cinco minutos.

Gestión de colas, en Perl, hay unos cuantos módulos que pueden ayudar en esto, como por ejemplo la familia de módulos Queue::Q. Async::Queue es otro gestor de colas, donde se puede indicar el número de procesos simultáneos.

Si esto no es suficiente, habrá que pensar en otro tipo de herramienta de gestión de colas, fuera de Perl.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Web

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 2 invitados

cron