Fiabilidad de integración del 100%

Este tema analiza las razones por las que es posible que no pueda conectarse a Zencoder y cómo garantizar una integración confiable.

Resumen

Zencoder es una dependencia de software esencial para la mayoría de nuestros clientes. Y aunque nuestro objetivo es lograr un tiempo de actividad del 100%, puede haber ocasiones en las que no pueda conectarse a Zencoder:

Cuando esto sucede y Zencoder está inactivo, su aplicación generalmente recibirá una respuesta de '503 Servicio no disponible' de Zencoder, pero podría obtener un error diferente (como un 500). Si ha excedido su límite de tasa de API, obtendrá una respuesta de '403 Rate Limit Exceeded'.

La buena noticia: dado que la codificación de video es un proceso asincrónico, puede crear su aplicación para que nunca experimente tiempo de inactividad o problemas relacionados con nuestra disponibilidad. Si hace esto, el peor de los casos es que sus trabajos tarden un poco más. Pero no se producen errores. Le recomendamos encarecidamente que haga esto.

Para decirlo con más fuerza, si le preocupa la confiabilidad, debe seguir este enfoque de integración - para Zencoder, o para cualquier API crítica con la que se integre.

  • Nuestro servicio puede verse afectado por problemas en un proveedor ascendente (por ejemplo, Amazon Web Services)
  • Ocasionalmente necesitamos realizar un mantenimiento del sistema que requiere un tiempo de inactividad temporal.
  • Has excedido tu Límite de tasa de API
  • etc.

Integración confiable de aplicaciones

  1. Incluir un URL secundaria como copia de seguridad en caso de que falle la carga a su ubicación principal.
  2. Si obtiene un código de respuesta no exitoso de Zencoder, básicamente, algo que no sea 200 o 201, no falles en el trabajo. Un código de respuesta 503 no significa que su video no se pueda procesar. Simplemente significa que Zencoder no está disponible temporalmente.
  3. Si obtienes un error de conexión cuando intente conectarse a Zencoder, haga lo mismo.
  4. Similar, envuelve tus solicitudes de API en un tiempo de espera. Recomendamos un tiempo de espera de 30 segundos; Zencoder generalmente responde en menos de un segundo, por lo que 30 segundos suele ser mucho tiempo.
  5. En los tres casos, si obtiene un código de respuesta incorrecto, no puede conectarse o se agota el tiempo de espera de la solicitud de la API, marcar el trabajo como 'pendiente'.
  6. Periódicamente volver a enviar cualquier trabajo en el estado 'pendiente'. Podrías usar cron para hacer esto cada minuto, por ejemplo.

Una vez que se vuelven a enviar los trabajos, todo se comporta con normalidad. De esta manera, un envío de trabajo fallido solo hace que el trabajo demore un poco más en lugar de causar problemas a su aplicación o sus usuarios.

Pseudocódigo

Bien, esto no es Pseudocódigo, es Ruby. Pero Ruby es bastante fácil de leer.

  1. Imagine una tabla de videos que incluye estas columnas. (Obviamente tendrá más, incluidas columnas para almacenar una ID de trabajo de Zencoder y una ID de archivo de salida de Zencoder).
    create_table :videos do |t|
    t.string  :state
    t.integer :lock_version
    t.index   :state
    end
  2. Un video debe incluir una máquina de estado con los siguientes estados:
    • pendiente (aún no enviado a Zencoder)
    • sometiendo (actualmente enviando a Zencoder)
    • transcodificación (enviado con éxito a Zencoder)
    • terminado (Zencoder terminó la transcodificación y el trabajo está hecho)
    • falló (Zencoder no pudo transcodificar el video)
  3. Cuando se ingiera un nuevo video, guarde el video en el estado de 'envío' y active un trabajo en segundo plano para enviar el video a Zencoder.
    # got a new video!
    video = Video.new(params)
    video.state = "submitting"
    video.save!
    submit_to_zencoder(video)

    Realmente debería poner en segundo plano el método submit_to_zencoder. En Ruby, usando DelayedJob, esto podría verse así:

    delay.submit_to_zencoder(video)

    Pero nos quedaremos con nuestro submit_to_zencoder(video) método para fines de ejemplo.

  4. La submit_to_zencoder La función se parece a esto. Esto debe ejecutarse de forma asincrónica, en segundo plano.
    def submit_to_zencoder(video)
    begin
    response = Zencoder::Job.create(attributes, :timeout => 30_000)
    if response.code == 201
    video.state = "transcoding"
    else
    video.state = "pending"
    end
    
    video.save!
    
    # Rescue any connection error. Our plugin abstracts these as
    # Zencoder::HTTPError.
    #
    # If you're not using the Zencoder plugin, this includes things
    # like Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::ECONNREFUSED,
    # Errno::EHOSTDOWN, and SocketError.
    
    rescue Timeout::Error, Zencoder::HTTPError
    video.state = "pending"
    video.save!
    end
    end
  5. De vez en cuando, por ejemplo, cada minuto, intente volver a enviar los trabajos que están en estado "pendiente".
    def resubmit_pending_jobs
    Video.where(:state => "pending").find_each do |video|
    begin
    video.state = "submitting"
    video.save!
    
    submit_to_zencoder(video)
    rescue ActiveRecord::StaleObjectError
    end
    end
    end
    

    Además, al agregar una columna 'lock_version' a la tabla de videos, introducimos un bloqueo optimista. Esto significa que si el registro se actualiza entre la Video.find consulta y video.save, no enviará el trabajo a Zencoder. Esto evitará que el trabajo se envíe a Zencoder dos veces accidentalmente. Puede usar un bloqueo pesimista o de base de datos o algún otro método de bloqueo para lograr lo mismo.

    Es fácil…

    A fin de cuentas, este es un enfoque bastante simple para garantizar una confiabilidad de integración del 100% entre Zencoder y su aplicación. Son unos pocos pasos más que enviar ingenuamente un trabajo; pero garantiza que no importa lo que suceda, ya sea un tiempo de espera ocasional, un tiempo de inactividad inesperado en Zencoder o un mantenimiento programado, su aplicación se ejecuta de manera confiable.