# 知識學習 - 直播每秒百萬按讚：直播影片上的即時互動

介紹人是 LinkedIn 的工程師在介紹他們怎麼處理在直播影片上的即時互動。演講上使用幾個不同階段的挑戰來說明技術上的選擇和處理。

## 挑戰 1：傳輸管道

一開始的需求很簡單，因為需要持續的互動。所以需要選擇一個可以長時間連線的手段，而這邊選擇使用了 Server-Sent Event 來做處理。因為其就跟常規的 HTTP 一樣只是給予不同的 `Accept` Header

## 挑戰 2：連線管理

有了連線的手段後，再來的挑戰就是有上千萬的連線而這些連線該怎麼管理呢？這邊採用的是 [Akka](https://akka.io/) ，每個連線 Akka 都會指派一個 Thread 來做處理，這邊專門處理當接收到 Message 的時候要怎麼處理。這邊選擇使用 [Play 框架](https://www.playframework.com/) 來做處理。Play 將其轉換成持久的連線，被分配一個隨機的 `connectionId`。然後會將其 `connectionId` 和處理 EventSource  的部分實例化一個 Akka Actor 來管理這些連線。

所以現在流程上，每個 Client 的連線都會有一個對應的 Akka Actor 管理，然後所有的 Akka Actor 又會由 Akka Supervisor Actor 來管理。當有使用者送出 Like 的 HTTP 請求時，會將其送到 Akka Supervisor Actor，然後 Supervisor Actor 會在廣播給所有的 Akka Actor，而 Akka Actor 就只需要將其收到的訊息透過 EventSource 送到該 Client。

## 挑戰 3：多個直播影片

因為要導入訂閱的概念，所以需要管理發送的訊息要給正確的使用者。而這些訂閱的關係儲存在記憶體資料庫中。所以當使用者送出 HTTP 請求後，Supervisor Actor 需要去記憶體資料庫中找出要發送給誰。

## 挑戰 4：10k 併發觀眾

這邊開始就要邁向伺服器的擴展挑戰，今天這邊在前端節點的後面再加上一個 dispatcher。現在每個前端節點（Supervisor Actor）需要將目前有的連線發送到 Dispatcher。所以當有按讚請求發生時，將會先經過 Dispatcher -> 多個 Supervisor Actor -> 多個 Akka Actor -> 所有有訂閱的 Client。

## 挑戰 5：每秒 100 個讚

因為請求變高了，當然可以就很偷懶的在增加 Dispatcher 來乘載更多的請求。但是這邊就會有問題，因為每個 Dispatcher 都會需要每個前端節點發送連線狀態，而且一旦節點消失，就會丟失資料。所以需要將其提取出來成一個獨立的記憶體資料庫。任何的節點都可以隨時訪問。來解決擴充上和資料儲存的問題

## 挑戰 6：每秒 100 個讚、10k 觀看者總共發佈每秒 100 萬個讚

(重新展示前面的所有過程)

## 額外挑戰：另一個資料中心

當今天不只一個資料中心的時候怎麼處理。再討論是要以跨資料中心方式訂閱還是以跨資料中心方式發布之後，認為以後者方式在此處是更好的選擇。第一個資料中心的 Dispatcher 收到請求後，會像其他資料中心的 Dispatcher 發送通知，各資料中心的 Dispatcher 在各自查詢連線並發送給 Client。

## 成效 & 擴展

有做過一些嘗試，每一台機器都可以處理 100,000 個連線。所以已有處理得過的案例，英國皇家婚禮，有 1800 萬個觀眾，只需要 180 台機器就可以處理。但是當然沒有說的那麼容易，因為也還是有遇到一些額外的問題，例如 file descriptor limits, port exhaustion, even memory limits。在[這裡](tiny.cc/linkedinscaling)都有記錄這些內容。

然後這些架構下每個 Dispatcher 節點可以接收每秒 5000 個事件。而延遲的話 p90 之下只有 75 毫秒。

## 問答

Q：對於不支援 Server-Sent Event 的 Client 有什麼備案嗎？
A：因為 SSE 是一個常規的 HTTP，所以這跟一般的 HTTP 沒有差別。而且事實上 WebSockets 有時會在一些系統上被防火牆擋住。我們也沒遇過 SSE 不起作用的情況，大多數的防火牆也不會擋住。

Q：基本上，如何將直播跟喜歡的時間同步
A：您是想知道確保下次有人觀賞時點讚會同時出現嗎？
Q：是的，因為直播在不同的伺服器上會有延遲，按讚發生的時間點可能不同
A：延遲是一定的，但是因為我們的延遲時間很短，對於使用者幾乎是沒有差別的

Q：如何保證一致性，尤其考慮到 Dispatcher 會跨資料中心的故障狀況
A：答案是我們沒有保證，因為我們追求的是速度，我們不保證其一定會完成。雖然這麼說但不表示我們會不管，我們依舊會監控前端發送的請求和實際被 Client 接受的比例，如果下降會找出原因並修正

可能有些人會說怎麼不用 Kafka，但問題在於你不知道直播何時會發起，也不知道何時會有人發送請求。這在於要讓我們發送和刪除事件時是很不容易的。


## 結語

是一篇看完頭有點痛的文章呢，好多英文想吐了


## Reference

- [Streaming a Million Likes/Second: Real-Time Interactions on Live Video](https://www.infoq.com/presentations/linkedin-play-akka-distributed-systems/)
