Jump to content

Error 503 Service Unavailable


Recommended Posts

Hola a todos. He creado una tarea cron para insertar productos desde una API a mi tienda, la tarea funciona perfectamente, se conecta con la api y luego por codigo inserta los productos con sus respectivas combinaciones. La API devuelve 12784 productos, de los cuales se han insertado 5870 a la tienda, la tarea esta programada cada 10 min por SSH en el servidor. Sin embargo a medida que crece la cantidad de productos en la tienda han comenzado los problemas. Lo primero es que cada vez que se ejecuta la tarea se insertan menos productos.(A veces ninguno cuando en realidad deberían insertarse todos de una vez), lo segundo es que el frontend de la tienda se ha vuelto demasiado pesado de hecho a veces no cargan las pagina y dice error 503 servicio temporalmente no disponible. Igual pasa cuando ejecuto la tarea, me devuelve el mismo mensaje. He estado leyendo y entiendo que se trata de un problema de consumo de recursos en el servidor. Según lo que entiendo. Por lo cual he incrementado alguno paramétros en el servidor como memory-limited, pero nada siguen los problemas.

image.thumb.png.695392eb0f6107714e50b9d1e6f56443.pngAlguno de ustedes ha tenido este problema anteriormente? Tienen alguna idea de que esta pasando? el backend de la tienda funciona de vez en cuando me arroja el mismo error pero funciona, pero el frontend no. Me da ese error. Ayuda @Prestafan33 

Link to comment
Share on other sites

Entiendo por tus explicaciones que cada 10 minutos se insertan UNA PARTE de los productos, y no el total de los disponibles. No sé si esto es intencionado, o es porque el servidor interrumpe el script PHP antes de que haya terminado. En cualquier caso, por lo que dices, parece que en la siguiente sincronización se vuelve a empezar por el principio y se insertan los mismos productos que ya estaban de la vez anterior, interrumpiendose entonces más o menos en el mismo sitio. Es lo que entiendo del comportamiento que describes.

Supongo que sabes que los scripts PHP tienen un tiempo de vida, superado el cual son interrumpidos por el servidor, para evitar consumo excesivo de recursos y bloqueos (precisamente lo que te está ocurriendo). Ese tiempo depende de como este establecido en la configuración del servidor PHP, pero lo habitual es que oscile entre 30 y 120 segundos. Lo normal es que insertar cada producto pueda consumir menos de un segundo, pero aun así dudo que en 120 segundos se puedan insertar todos los productos que tú quieres.

De todos modos, como dice juanrojas, yo tampoco entiendo la finalidad de insertar 13.000 productos cada 10 minutos. Lo normal sería insertarlos una sola vez y, si es necesario mantenerlos sincronizados, utilizar hooks o el equivalente que tenga el programa del cual utilizas la API, para sincronizar la información de aquellos que hayan sido modificados en el momento que cambien. Tal como lo tienes planteado me parece un consumo innecesario de recursos, que es lo que está provocando que tu web se bloquee y no funcione como debería. Si tienes al servidor ocupado creando productos es normal que no responda a otras tareas, aparte de que si borras los productos y los creas de nuevo es normal que dé errores si se intenta acceder a ellos durante ese proceso.

Edited by Prestafan33 (see edit history)
Link to comment
Share on other sites

2 hours ago, Prestafan33 said:

Entiendo por tus explicaciones que cada 10 minutos se insertan UNA PARTE de los productos, y no el total de los disponibles. No sé si esto es intencionado, o es porque el servidor interrumpe el script PHP antes de que haya terminado. En cualquier caso, por lo que dices, parece que en la siguiente sincronización se vuelve a empezar por el principio y se insertan los mismos productos que ya estaban de la vez anterior, interrumpiendose entonces más o menos en el mismo sitio. Es lo que entiendo del comportamiento que describes.

Supongo que sabes que los scripts PHP tienen un tiempo de vida, superado el cual son interrumpidos por el servidor, para evitar consumo excesivo de recursos y bloqueos (precisamente lo que te está ocurriendo). Ese tiempo depende de como este establecido en la configuración del servidor PHP, pero lo habitual es que oscile entre 30 y 120 segundos. Lo normal es que insertar cada producto pueda consumir menos de un segundo, pero aun así dudo que en 120 segundos se puedan insertar todos los productos que tú quieres.

De todos modos, como dice juanrojas, yo tampoco entiendo la finalidad de insertar 13.000 productos cada 10 minutos. Lo normal sería insertarlos una sola vez y, si es necesario mantenerlos sincronizados, utilizar hooks o el equivalente que tenga el programa del cual utilizas la API, para sincronizar la información de aquellos que hayan sido modificados en el momento que cambien. Tal como lo tienes planteado me parece un consumo innecesario de recursos, que es lo que está provocando que tu web se bloquee y no funcione como debería. Si tienes al servidor ocupado creando productos es normal que no responda a otras tareas, aparte de que si borras los productos y los creas de nuevo es normal que dé errores si se intenta acceder a ellos durante ese proceso.

Hola @Prestafan33 lo que me pide el cliente es que cada 10 minutos se sincronice la tienda con la api, es decir se ejecute la tarea cron y si hay nuevos productos se inserten, el problema se ha presentado en la primera carga de productos donde pretendía vaciar los 12000 que tiene la api, ya luego que se ejecute la tarea no tendrá que vaciar 12000 productos nuevamente, solo actualizar el catalogo si hay un nuevo producto en la api. Cuando la tarea se interrumpe NO comienza desde el principio, sino desde el punto donde quedo, porque el script tiene una validación para evitar que se inserten productos cuyas referencias ya existan en la tienda y todas las referencias son distintas. 

Efectivamente como tu bien dices el servidor esta interrumpiendo el script antes de que haya terminado arrojando los siguientes logs:

PDOException(code: HY000): SQLSTATE[HY000]: General error: 2013 Lost connection to MySQL server during query 

already has more than 'max_user_connections' active connections at line 127 in file classes/db/DbPDO.php

He considerado colocar en cero los siguientes parametros de mysql  max_user_connections y mysql.connect_timeout esto según lo que he leido en la documentación. No se que piensas al respecto? 

Pero hay otro problema, una vez se cargaron los primeros 6000 productos a la tienda el frontend esta lento y arroja también error 503. Crees que sea correcto colocar estos valores como ilimitados aunque sea para la primera carga de productos? Esto podria estar causando las fallas en el frontend tambien?

Edited by ruthcast (see edit history)
Link to comment
Share on other sites

Por lo que dices entonces el problema no es la duración del proceso PHP, sino que se satura el número de conexiones abiertas con la base de datos. Si lo que haces es comprobar, para cada producto, si ya existe en la base de datos, seguramente el problema esté ahí, cada comprobación abre una conexión nueva con la base de datos, y llega un momento en que el número de ellas disponibles se agota.

No sé cómo estás haciendo exactamente el proceso de inserción masiva de productos, pero te cuento cómo he afrontado yo los problemas de timeout al generar un feed de productos de Prestashop con varios miles de productos:

Lo que hago básicamente es, para evitar agotar el tiempo de los scripts PHP, ir contando el número de productos que proceso. Cuando llego a una cantidad establecida (por ejemplo, 500 productos), lo que hago es que el controlador se vuelva a llamar a sí mismo pasando el número del último producto que se ha procesado. De este modo, cuando esa variable está presente en la llamada, se salta directamente a ese último producto y se continúa desde ahí, sin tener que hacer más comprobaciones ni consultas a la base de datos. Lo explico con un poco de código:

public function initContent() {
  if (Tools::isSubmit('action')) {
    $action = Tools::getValue('action');
    switch ($action) {
      case 'generateFeed':
        $continue = 0;
        if (Tools::isSubmit('continue') && ctype_digit(Tools::getValue('continue'))) {
          $continue = (int)Tools::getValue('continue');
        }
        $this->generateFeed($continue);
        break;
    }
  }
}

[...]

// Procesando los productos...
protected function generateFeed($continueFrom=0) {
  $products = $this->getAllProductsInDatabase($continueFrom, $this->numberProductsToProcess);
  /* Aquí recupero los productos a procesar, A PARTIR DEL NÚMERO DE PRODUCTO RECIBIDO EN LA ÚLTIMA LLAMADA ($continueFrom).
  En "numberProductsToProcess" tengo el número de productos a procesar en cada llamada (por ejemplo, 500).*/
  $numberProductsProcessed = 0;
  foreach($products as $p) {
    $this->processProduct($p);
    if ($this->numberProductsToProcess <= ++$numberProductsProcessed) {
      $this->makeContinueAsyncronousCall($continueFrom + $numberProductsProcessed + 1);
    }
  }
}
      
[...]
      
// Finalmente, uso CURL para llamar de nuevo al controlador y que continúe la importación a partir del último producto procesado
protected function makeContinueAsyncronousCall($nextProductToProcess){
  $url = Tools::getHttpHost(true).__PS_BASE_URI__.'module/'.$this->module->name.'/feed?action=generateFeed&key='.$this->module->secret_key;
  $url.= '&continue='.$nextProductToProcess;  // Aquí uso la URL de mi módulo y le paso por GET la variable "continue" con el número del siguiente producto a procesar
  $curl = curl_init();                
  curl_setopt($curl, CURLOPT_URL, $url);
  curl_setopt($curl, CURLOPT_USERAGENT, 'api');
  curl_setopt($curl, CURLOPT_TIMEOUT, 2); 
  curl_setopt($curl, CURLOPT_HEADER, 0);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);
  curl_setopt($curl, CURLOPT_FORBID_REUSE, true);
  curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 2);
  curl_setopt($curl, CURLOPT_DNS_CACHE_TIMEOUT, 10); 
  curl_setopt($curl, CURLOPT_FRESH_CONNECT, true);
  curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    
  curl_exec($curl);
  $result = curl_getinfo($curl);
  curl_close($curl);
}

 

Edited by Prestafan33 (see edit history)
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...