搜尋
首頁後端開發php教程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 ; 降级时返回值

降级时我们不会再去访问后端服务,而是直接给调用方返回一个配置的值。

流量控制的狀態圖描述如下:
PHP中RPC框架基於Redis實現流量控制系統

如何實現控制流量在一定比例呢? 透過隨機選擇,例如獲得一個隨機數並判斷是否落在某個範圍內。 透過限制流量在一個最佳值,在影響最少的用戶情況下讓大部分請求能正常運作,同時流量控製配合監控警報,發現某個模組的流量控制比例在1以下,說明相關模組已是系統的瓶頸,下一步就應該增加硬體資源或優化我們的程式效能了。

相關推薦:

RPC框架的實例詳解

#PHP遠端呼叫以及RPC框架的程式碼詳解(圖)

PHPRPC的簡單使用

以上是PHP中RPC框架基於Redis實現流量控制系統的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
es和redis区别es和redis区别Jul 06, 2019 pm 01:45 PM

Redis是现在最热门的key-value数据库,Redis的最大特点是key-value存储所带来的简单和高性能;相较于MongoDB和Redis,晚一年发布的ES可能知名度要低一些,ES的特点是搜索,ES是围绕搜索设计的。

一起来聊聊Redis有什么优势和特点一起来聊聊Redis有什么优势和特点May 16, 2022 pm 06:04 PM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了关于redis的一些优势和特点,Redis 是一个开源的使用ANSI C语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式存储数据库,下面一起来看一下,希望对大家有帮助。

实例详解Redis Cluster集群收缩主从节点实例详解Redis Cluster集群收缩主从节点Apr 21, 2022 pm 06:23 PM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了Redis Cluster集群收缩主从节点的相关问题,包括了Cluster集群收缩概念、将6390主节点从集群中收缩、验证数据迁移过程是否导致数据异常等,希望对大家有帮助。

Redis实现排行榜及相同积分按时间排序功能的实现Redis实现排行榜及相同积分按时间排序功能的实现Aug 22, 2022 pm 05:51 PM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了Redis实现排行榜及相同积分按时间排序,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,希望对大家有帮助。

详细解析Redis中命令的原子性详细解析Redis中命令的原子性Jun 01, 2022 am 11:58 AM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了关于原子操作中命令原子性的相关问题,包括了处理并发的方案、编程模型、多IO线程以及单命令的相关内容,下面一起看一下,希望对大家有帮助。

实例详解Redis实现排行榜及相同积分按时间排序功能的实现实例详解Redis实现排行榜及相同积分按时间排序功能的实现Aug 26, 2022 pm 02:09 PM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了Redis实现排行榜及相同积分按时间排序,本文通过实例代码给大家介绍的非常详细,下面一起来看一下,希望对大家有帮助。

一文搞懂redis的bitmap一文搞懂redis的bitmapApr 27, 2022 pm 07:48 PM

本篇文章给大家带来了关于redis的相关知识,其中主要介绍了bitmap问题,Redis 为我们提供了位图这一数据结构,位图数据结构其实并不是一个全新的玩意,我们可以简单的认为就是个数组,只是里面的内容只能为0或1而已,希望对大家有帮助。

redis error什么意思redis error什么意思Jun 17, 2019 am 11:07 AM

redis error就是redis数据库和其组合使用的部件出现错误,这个出现的错误有很多种,例如Redis被配置为保存数据库快照,但它不能持久化到硬盘,用来修改集合数据的命令不能用。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具