100% 整合可靠性

本主題討論您可能無法連接到 Zencoder 的原因以及如何確保可靠的集成。

概覽

Zencoder 是我們大多數客戶必不可少的軟件依賴項。雖然我們的目標是 100% 的正常運行時間,但有時您可能無法連接到 Zencoder:

當發生這種情況並且 Zencoder 關閉時,您的應用程序通常會從 Zencoder 收到“503 服務不可用”響應,但您可能會收到不同的錯誤(如 500)。如果您超出了 API 速率限制,您將收到“403 超出速率限制”響應。

好消息:由於視頻編碼是一個異步過程,您可以構建您的應用程序,永遠不會遇到停機或與我們的可用性相關的問題。如果你這樣做,最壞的情況是你的工作需要更長的時間。但是沒有錯誤發生。我們強烈建議您這樣做。

更強烈地說, 如果您關心可靠性,您應該遵循這種集成方法 ——對於 Zencoder 或您集成的任何關鍵 API。

  • 我們的服務可能會受到上游提供商(例如亞馬遜網絡服務)問題的影響
  • 我們偶爾需要執行需要臨時停機的系統維護
  • 您已超出 API 速率限制
  • ETC。

可靠的應用程序集成

  1. 包括 輔助 URL 作為備份,以防上傳到您的主要位置失敗。
  2. 如果您從 Zencoder 得到一個不成功的響應代碼——基本上,除了 200 或 201 之外的其他代碼—— 不要讓工作失敗。響應代碼 503 並不意味著您的視頻無法處理。這只是意味著 Zencoder 暫時不可用。
  3. 如果您在嘗試連接到 Zencoder 時遇到 連接錯誤 ,請執行相同的操作。
  4. 同樣, 將您的 API 請求包裝在 timeout 中。我們建議超時 30 秒; Zencoder 通常會在不到一秒內做出響應,因此 30 秒通常足夠了。
  5. 在所有這三種情況下 - 如果您收到不成功的響應代碼、無法連接或 API 請求超時 - 將作業標記為“待處理”。
  6. 定期 重新提交任何處於“待處理”狀態的作業。例如,您可以使用 cron 每分鐘執行一次。

重新提交作業後,一切都會正常進行。這樣,失敗的作業提交只會使作業花費更長的時間,而不會給您的應用程序或用戶帶來麻煩。

偽代碼

好的,所以這不是偽代碼——它是 Ruby。但是 Ruby 非常容易閱讀。

  1. 想像一個包含這些列的視頻表。(它顯然會有更多,包括存儲 Zencoder 作業 ID 和 Zencoder 輸出文件 ID 的列。)
    create_table :videos do |t|
    t.string  :state
    t.integer :lock_version
    t.index   :state
    end
  2. 視頻應包含具有以下狀態的狀態機:
    • 待定(尚未提交給 Zencoder)
    • 提交(目前正在提交給 Zencoder)
    • 轉碼(成功提交到Zencoder)
    • 完成(Zencoder 完成轉碼,工作完成)
    • 失敗(Zencoder 無法轉碼視頻)
  3. 攝取新視頻時,將視頻保存為“正在提交”狀態並觸發後台作業以將視頻提交給 Zencoder。
    # got a new video!
    video = Video.new(params)
    video.state = "submitting"
    video.save!
    submit_to_zencoder(video)

    您真的應該為 submit_to_zencoder 方法設置背景。在 Ruby 中,使用 DelayedJob,這可能看起來像這樣:

    delay.submit_to_zencoder(video)

    但是我們會堅持使用我們的submit_to_zencoder(video)方法,例如目的。

  4. submit_to_zencoder功能看起來像這樣。這應該在後台異步運行。
    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. 每隔一段時間 - 例如每分鐘 - 嘗試重新提交處於“待定”狀態的作業。
    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
    

    此外,通過向視頻表添加“lock_version”列,我們引入了樂觀鎖定。這意味著,如果記錄在Video.find查詢和之間更新video.save,它不會將作業提交給 Zencoder。這將防止作業被意外提交到 Zencoder 兩次。您可以使用悲觀鎖定或數據庫鎖定或其他一些鎖定方法來完成同樣的事情。

    就這麼簡單……

    綜合考慮,這是確保 Zencoder 和您的應用程序之間 100% 集成可靠性的非常簡單的方法。這比天真地提交工作要多一些步驟;但它確保無論發生什麼情況——無論是偶爾的超時,還是 Zencoder 的意外停機,或者定期維護——你的應用程序都能可靠地運行。