雖然這篇polling機制鄉民發文沒有被收入到精華區:在polling機制這個話題中,我們另外找到其它相關的精選爆讚文章
在 polling機制產品中有7篇Facebook貼文,粉絲數超過2,850的網紅矽谷牛的耕田筆記,也在其Facebook貼文中提到, 本文延續前篇效能校正的經驗談,上篇文章探討了關於系統呼叫, iptables 可以最佳化的部分,。本篇文章將繼續剩下最佳化步驟的探討。 Perfect Locality 預設情況下, Linux Kernel 會盡量平均地將請求給分配到所有的處理佇列,譬如 network queues, proc...
polling機制 在 矽谷牛的耕田筆記 Facebook 的最佳貼文
本文延續前篇效能校正的經驗談,上篇文章探討了關於系統呼叫, iptables 可以最佳化的部分,。本篇文章將繼續剩下最佳化步驟的探討。
Perfect Locality
預設情況下, Linux Kernel 會盡量平均地將請求給分配到所有的處理佇列,譬如 network queues, processes, CPUS. 大部分情況下這種機制運作良好不會有太多問題,不過如果今天要追求的不單單只是好的效能,而是極致的效能,則 locality 這個概念就要特別的去注意。
這篇文章中提到很多不同的方式,包含了 CPU Pinning, Receive Side Scaling(RSS), Transmit Packet Sterring(XPS)等,其實用比較簡單的介紹方式就是,希望可以使用固定的 CPU 來處理一條連線上的所有封包(進出),這樣帶來的好處有
1. CPU Cache 可以盡可能的去使用,減少各種 miss 產生的成本
2. 減少 context switch 帶來的成本
3. 減少跨 CPU 之間交換資料帶來的成本
4. 減少 lock 之間帶來的成本
除了 CPU Pin, RSS, XPS 外,還有 irqbalance, smp_affinity_list 等相關的概念需要一併學習,對於這個概念有興趣的讀者非常歡迎去找尋這類型的資料
接者是 SO_REUSEPORT 這個參數,創建 Socket 時使用這個參數能夠使得多個 Process 共用一個連接埠,底層 Kernel 會針對 src/dst{ip/port} 來產生對應的 Hash,並且決定當前封包要送給哪一個 Process。
這個方式搭配前述各種 CPU Pin, 中斷的最佳化則會遇到問題,因為可能底層將該封包送到 CPU2 結果這個函式又把封包重新分配到 CPU0, 這樣就導致該連線要跨 CPU 處理了。
為了解決這個問題, Linux Kernel 4.6 後有新的參數 SO_ATTACH_REUSEPORT_CBPF,使用者可以自行撰寫 BPF 的程式來決定如何分配封包。作者根據這過想法撰寫了一個 BPF 的程式,來確保這個機制可以與前述的最佳化穩定運作。
這次的最佳化帶來的 38% 的成長,這時候的封包處理能力從 603k req/s 提升到 834k req/s
原文中關於這次的最佳化還有一些後續探討,有興趣的可以閱讀
Interrupt Optimizations
當封包透過網路送到網卡後,網卡必須要通知 OS 讓它知道有封包來了,要記得處理。一切處理完畢後網卡就可以繼續等待新的封包過來並且再次發送中斷給 OS 處理封包。這個流程大部分情況也是運作良好,不過當有大量的封包不停傳送來時,頻繁的中斷其實也是會造成不小的額外成本。
為了解決這個問題,目前比較嶄新的網卡都有支援中斷聚合等功能,透過這個功能可以延後中斷一個小週期,而該週期內收到的所有封包只需要透過一次的中斷就可以來處理,藉此降低中斷的次數。更為進階的網卡甚至支援動態自行調整該週期的時間,譬如當網路空閒時,減少週期使得每個封包能夠盡快的發送中斷被處理,而當網路流量很大時則會加大該該週期時間來更有效地處理封包。
註: AWS ENA 有支持這種動態調整的機制
作者基於 AWS 開啟動態調整收端中斷時間的功能,整個效能提升了 14%,從 834k req/s 提升到 955k req/s。作者說這次的調整可以說是整篇文章中幾個非常強的改動,改動的地方少,效能提升明顯,同時背後的隱憂與限制也少。
除了上述中斷的方式外,另外一種則是透過 Busy Polling 這種針對低延遲性的方式。預設情況下其允訓設定為 blocked 的 socket 能夠消耗額外的 CPU Cycle 來讀取接下來的封包,可以將其想成一成一種混合體,當底層網卡告訴我有資料要讀取時,我預期接下來還會有更多的資料,因此我就透過輪詢的方式去多問幾個封包。
由於作者的應用程式是使用 non-blocking 的方式去讀寫封包,所以預設的方式是沒有辦法使用的。而該應用程式又是使用 epoll 來進行底層封包的讀寫。 epoll 於 kenel 4.12 後正式支援 busy polling 的方式,所以這部分就沒有太大的問題。文章中有滿多關於 busy_poll 的一些參數調整。
將這兩個機制給整合後,整體的效能提升達到 28%,從 834k req/s 到達 1060k req/s,同時 99%的 latency 也從 361μs 下降到 292μs.
同時這兩個機制導入後,整個系統每秒產生的硬體中斷數量也從 183k 降到 16k。 Context switches 的數字也從 6k 下降到 1k 左右。
下篇文章會繼續從剩下的三個最佳化策略繼續介紹
https://talawah.io/blog/extreme-http-performance-tuning-one-point-two-million/
polling機制 在 Kewang 的資訊進化論 Facebook 的最讚貼文
Funliday 最近做了大改版,其中一項功能就是把去年中因為 Google 要開始收費而暫時拿掉的「推薦景點」加回來,這個功能就是提供使用者指定區域附近評價較高的景點。
大家現在在使用景點瀏覽時,應該有時候會發現資料出來的速度不一致,慢的時候 (超過 5 秒,有時候會落在 10 秒以上) 代表可能有其他使用者正在查詢這個區域的「推薦景點」,思考邏輯就是在同一區域只要有一個使用者查詢過這個區域的「推薦景點」,其他同區域的使用者就會因為已經查詢過這份資料 (如熱門景點:台北 101、東京晴空塔...等) 而受惠。
在目前小編能力還無法將查詢效能大幅改善的狀況之下 Orz,若同一個區域有多個使用者同時查詢,每個查詢都要花費 10 秒的話,這樣子資料庫會浪費超多時間在不必要的查詢上面。
像這類無法避免的使用者行為,但又要減少資料庫無謂的同樣操作時,小編突然想到之前 Triton Ho 在上課時提到的 exclusive lock。
Advisory lock 是 PostgreSQL 的一種 lock 機制,可以在 application 層操作 exclusive lock (以下稱為 X lock) 或是 shared lock (以下稱為 S lock)。當使用 X lock 時,若非同一個 session 是無法將它 unlock,而 S lock 則是任何一個 session 都可以用 S lock 拿取 (acquire) 相同的 lock,但不可以用 X lock 拿取 S lock。
依小編的這個使用情境,可以在查詢「推薦景點」之前先問一次 Redis 有沒有這個區域的資料,有的話直接從 Redis 取得,沒有的話就先到 PostgreSQL acquire 一次 X lock,如果可以成功的話,則表示還沒有其他 session 正在查詢這個區域的資料,所以可以在 acquire 之後直接查詢,接著再 unlock 這個 X lock;但如果無法 acquire 的話,則表示目前有其他 session 正在查,所以直接回 client 查詢中的訊息,可以等一下再查。
所以小編使用 PostgreSQL 的 advisory lock 及 Redis 就可以達成不會有同一時間查詢相同耗時的查詢了。
其實再好一點的作法可能是把這類耗時的查詢丟到 MQ 裡面,讓 response 先回 client,等到 MQ 做完這個 job 之後,再用 push notification 通知 client 到 Redis 取得已經計算完的資料。或是用 polling 固定 n 秒鐘查詢一次,這都要視你的基礎設施而定。小編現在是先用 polling 的方式簡單處理,雖然方法有點笨,但在沒多餘心力 (Elasticsearch 太博大精深了 Orz) 的狀態之下就先這樣做了。
#funliday #postgresql #lock #advisorylock
polling機制 在 Kewang 的資訊進化論 Facebook 的最佳貼文
感謝 JCConf.tw,今年是小編連續第三年投稿有上,也有可能是小編最後一年在這裡分享。因為小編從 Java-based 的三竹資訊,轉進了目前是以 nodejs-based 的 Funliday-旅遊規劃。之後有機會的話可能就會在 JSDC Taiwan 上分享了 XDDD
Cache-Control 是 HTTP Protocol 眾多的 Header 之一,主要是在 client 及 server 的頻繁溝通下,可以利用 Cache-Control 將不必要的網路請求消除。之前因為小編做的產品是以 polling 為主,以 polling 為主的網路模型,就比較需要利用 Cache-Control 來消除不必要的網路請求。
所以這次的 talk 就是來分享一下如何在 JAX-RS 框架下加上 Guava Cache 替 Web Server 實作 Cache-Control 機制。也利用 ZooKeeper 在 multi-node 的情境下,如何將失效的 command 通知到所有的 node 並且執行。
這次也做了一個 PoC,讓大家可以直接來感受一下執行的效果。下一篇再來分享一下是如何運作的好了。
#jcconf #java #cachecontrol #guava #zookeeper