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
- Incluir un URL secundaria como copia de seguridad en caso de que falle la carga a su ubicación principal.
- 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.
- Si obtienes un error de conexión cuando intente conectarse a Zencoder, haga lo mismo.
- 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.
- 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'.
- 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.
- 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
- 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)
- 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. - 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
- 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 yvideo.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.