PHP中RPC框架基於Redis實現流量控制系統
我們對專案模組進行了一定程度的微服務化改造,之前所有模組都放在一個專案裡(一個大資料夾),線上部署也一樣,這樣的缺點顯而易見。 後面我們按照業務功能拆分成一個個的子模組,然後子模組之間通過RPC框架進行訪問,各個子模組有各自獨立的線上機器集群、mysql及redis等存儲資源,這樣一個子模組出問題不會影響到其它模組,同時可維護性,擴展性更強。
但現實中每個子模組的服務能力是不同的, 如下圖按子模組分割之後的架構圖所示,假設到達A模組的QPS為100,A依賴B,同時每一個A模組到達B模組的請求QPS也為100, 但B模組所能提供的最大QPS能力為50, 如果不進行流量限制,則B模組因為超過負載而流量堆積導致整個系統不可用,我們的動態流量控制系統就是找到子模組的最佳服務能力,即限制A模組到達B模組的流量為50QPS,則至少保證一部分請求是能夠正常進行的,而不會因為一個子服務掛掉而拖跨整個系統。
我們的RPC框架是一個PHP實作的框架,主要支援http協定的存取。對於一個前端A模組來說,對於依賴的後端B模組, 需先對B模組進行服務化配置,再按服務名字進行引用訪問,服務配置一般形式如下:
[MODULE-B] ; 服务名字 protocol = "http" ;交互协议 lb_alg = "random" ; 负载均衡算法 conn_timeout_ms = 1000 ; 连接超时,所有协议使用, 单位为ms read_timeout_ms = 3000 ; 读超时 write_timeout_ms = 3000 ; 写超时 exe_timeout_ms = 3000 ; 执行超时 host.default[] = "127.0.0.1" ; ip或域名 host.default[] = "127.0.0.2" ; ip或域名 host.default[] = "127.0.0.3" ; ip或域名 port = 80 ; 端口 domain = 'api.abc.com' ; 域名配置,不作真正解析,作为header host字段传给后端
對於要存取的一個服務模組,部署上一般是一個集群,我們需要配置機器集群的所有IP,當然,如果有內部DNS服務,也可以配上集群的域名。
對於一個RPC框架來說,基本的功能有負載平衡、健康檢查、降級&限流等,我們的流量控制即針對降級&限流功能,在詳細介紹它之前,先說說負載平衡與健康檢查是如何實現的,這是流量控制實現的基礎。
負載平衡我們實現了隨機與輪詢演算法,隨機演算法透過在所有IP中隨機選一個即可,比較容易實現,對於輪詢演算法,我們是基於單機輪詢,將上一個選擇的IP序號利用apcu擴充記錄在本地記憶體中,以方便找到下一個要使用的IP序號。
被存取的機器可能會失敗,我們將失敗的請求IP記錄在redis中,同時分析記錄的失敗日誌來決定是否需要將一個機器IP摘除,即認為這個IP的機器已經掛掉,不能正常提供服務了,這就是健康檢查的功能,我們透過相關服務配置項來介紹下健康檢查的具體功能:
ip_fail_sample_ratio = 1 ; 采样比例 失败IP记录采样比例,我们将失败的请求记录在redis中,为防止太多的redis请求,我们可以配一个失败采样比例 ip_fail_cnt_threshold = 10; IP失败次数 ip_fail_delay_time_s = 2 ; 时间区间 ip_fail_client_cnt = 3 ; 失败的客户端数 不可能一个IP失败一次就将其从健康IP列表中去掉,只有在有效的ip_fail_delay_time_s 时间范围内,请求失败了 ip_fail_cnt_threshold 次,并且失败的客户端达到ip_fail_client_cnt 个, 才认为其是不健康的IP。 为什么要添加 ip_fail_client_cnt 这样一个配置,因为如果只是某一台机器访问后端某个服务IP失败,那不一定是服务IP的问题,也可能是访问客户端的问题,只有当大多数客户端都有失败记录时才认为是后端服务IP的问题 我们将失败日志记录在redis的list表中,并带上时间戳,就比较容易统计时间区间内的失败次数。 ip_retry_delay_time_s = 30 ; 检查失败IP是否恢复间隔时间 某个失败的IP有可能在一定时间内恢复,我们间隔 ip_retry_delay_time_s 长的时间去检查,如果请求成功,则从失败的IP列表中去除 ip_retry_fail_cnt = 10; 失败IP如果检查失败,记录的失败权重值 ip_log_ttl_s = 60000; 日志有效期时间 一般来说只有最近的失败日志才有意义,对于历史的日志我们将其自动删除。 ip_log_max_cnt = 10000; 记录的最大日志量 我们用redis记录失败日志,容量有限,我们要设定一个记录的最大日志数量,多余的日志自动删除。
在我們的程式碼實作中,除了正常的服務IP配置,我們也維護了一個失敗IP列表,這樣透過演算法選IP時先要去掉失敗IP,失敗IP記錄在一個文件中,同時利用apcu記憶體快取加速訪問,這樣我們所有的操作基本上是基於記憶體存取的,不會有效能問題。
我們只有在請求失敗時才會將日誌記錄在redis中,那在什麼時候將失敗的IP找出來呢,這涉及到查詢redis list列表中所有的失敗日誌,同時統計失敗個數,是一個較複雜的操作。我們的實作是多個PHP程序搶佔鎖的方式,誰搶到了就執行分析操作,記錄失敗的IP到檔案中。因為只有一個行程會執行分析操作,所以對正常請求不會有什麼影響。 同時只有在失敗時才會有搶佔鎖的動作,正常情況下基本上不會與redis有任何交互,沒有效能損耗。
我們的健康檢查依賴於一個中心化的redis服務,如果它掛了怎麼辦?如果判斷redis服務本身掛掉了,rpc框架會自動關閉健康檢查服務, 不再與redis交互,這樣至少不會影響正常的RPC功能。
在健康檢查實現的基礎上我們可以實現流量控制,即當我們發現大部分或全部IP失敗時,我們可以推斷是因為流量過大導致後端服務響應不過來而請求失敗,這時我們就應該以一定策略限流,一般的實現是直接將流量全部摘除,這有點粗暴,我們的實現是逐步減少流量,直至失敗的IP比例降到一定數值,後面又嘗試逐步增加流量,增加與減少可能是一個循環的過程,也就是動態的流量控制,最終我們會找到一個最佳的流量值。透過相關配置來介紹流量控制的功能:
degrade_ip_fail_ratio = 1 ; 服务开始降级时失败IP比例 即失败的IP比例达到多少时开始降级,即开始减少流量 degrade_dec_step = 0.1 ; 每次限流增加多少 即每次减少多少比例的流量 degrade_stop_ip_ratio = 0.5; 在失败的IP已降到多少比例时开始停止减少流量,并尝试增加流量 degrade_stop_ttl_s = 10; 停止等待多长时间开始尝试增加流量 degrade_step_ttl_s = 10 流量增加或减少需要等待的时间。 每一次流量增加或减少后,下一步如何做是根据当时失败的IP比例来决定的,而且会保持当前流量值一段时间,而不是立即做决定。 degrade_add_step = 0.1 每次增加流量增加的比例值 degrade_return = false ; 降级时返回值 降级时我们不会再去访问后端服务,而是直接给调用方返回一个配置的值。
流量控制的狀態圖描述如下:
如何實現控制流量在一定比例呢? 透過隨機選擇,例如獲得一個隨機數並判斷是否落在某個範圍內。 透過限制流量在一個最佳值,在影響最少的用戶情況下讓大部分請求能正常運作,同時流量控製配合監控警報,發現某個模組的流量控制比例在1以下,說明相關模組已是系統的瓶頸,下一步就應該增加硬體資源或優化我們的程式效能了。
相關推薦:
以上是PHP中RPC框架基於Redis實現流量控制系統的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

PHP用於構建動態網站,其核心功能包括:1.生成動態內容,通過與數據庫對接實時生成網頁;2.處理用戶交互和表單提交,驗證輸入並響應操作;3.管理會話和用戶認證,提供個性化體驗;4.優化性能和遵循最佳實踐,提升網站效率和安全性。

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

PHP仍然具有活力,其在現代編程領域中依然佔據重要地位。 1)PHP的簡單易學和強大社區支持使其在Web開發中廣泛應用;2)其靈活性和穩定性使其在處理Web表單、數據庫操作和文件處理等方面表現出色;3)PHP不斷進化和優化,適用於初學者和經驗豐富的開發者。

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

PHP和Python各有優劣,選擇取決於項目需求和個人偏好。 1.PHP適合快速開發和維護大型Web應用。 2.Python在數據科學和機器學習領域佔據主導地位。

PHP在數據庫操作和服務器端邏輯處理中使用MySQLi和PDO擴展進行數據庫交互,並通過會話管理等功能處理服務器端邏輯。 1)使用MySQLi或PDO連接數據庫,執行SQL查詢。 2)通過會話管理等功能處理HTTP請求和用戶狀態。 3)使用事務確保數據庫操作的原子性。 4)防止SQL注入,使用異常處理和關閉連接來調試。 5)通過索引和緩存優化性能,編寫可讀性高的代碼並進行錯誤處理。

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。
