-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTrafficShaper.php
More file actions
143 lines (127 loc) · 3.14 KB
/
TrafficShaper.php
File metadata and controls
143 lines (127 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<?php
/**
* php 基于Redis使用令牌桶算法实现流量控制
*
* @author fdipzone
* @DateTime 2023-03-28 14:58:33
*
* Description:
* php基于Redis使用令牌桶算法实现流量控制,使用redis的队列作为令牌桶容器,入队(lPush)出队(rPop)作为令牌的加入与消耗操作。
*
* Func:
* public add 加入令牌
* public get 获取令牌
* public reset 重设令牌桶
* private connect 创建redis连接
*/
class TrafficShaper{
/**
* redis连接设定
*
* @var array
*/
private $_config;
/**
* redis对象
*
* @var \Redis
*/
private $_redis;
/**
* 令牌桶名称
*
* @var string
*/
private $_queue;
/**
* 最大令牌数
*
* @var int
*/
private $_max;
/**
* 初始化
*
* @author fdipzone
* @DateTime 2023-03-28 16:12:13
*
* @param array $config redis连接设定
* @param string $queue 令牌桶名称
* @param int $max 最大令牌数
*/
public function __construct(array $config, string $queue, int $max){
$this->_config = $config;
$this->_queue = $queue;
$this->_max = $max;
$this->_redis = $this->connect();
}
/**
* 加入令牌
*
* @author fdipzone
* @DateTime 2023-03-28 16:17:29
*
* @param int $num 加入的令牌数量
* @return int
*/
public function add(int $num=0):int{
// 当前剩余令牌数
$cur_num = intval($this->_redis->lSize($this->_queue));
// 最大令牌数
$max_num = intval($this->_max);
// 计算最大可加入的令牌数量,不能超过最大令牌数
$num = $max_num>=$cur_num+$num? $num : $max_num-$cur_num;
// 加入令牌
if($num>0){
$token = array_fill(0, $num, 1);
$this->_redis->lPush($this->_queue, ...$token);
return $num;
}
return 0;
}
/**
* 获取令牌
*
* @author fdipzone
* @DateTime 2023-03-28 16:19:07
*
* @return boolean
*/
public function get():bool{
return $this->_redis->rPop($this->_queue)? true : false;
}
/**
* 重设令牌桶,填满令牌
*
* @author fdipzone
* @DateTime 2023-03-28 16:20:04
*
* @return void
*/
public function reset():void{
$this->_redis->delete($this->_queue);
$this->add($this->_max);
}
/**
* 创建redis连接
*
* @author fdipzone
* @DateTime 2023-03-28 17:37:57
*
* @return \Redis
*/
private function connect():\Redis{
try{
$redis = new \Redis();
$redis->connect($this->_config['host'],$this->_config['port'],$this->_config['timeout'],$this->_config['reserved'],$this->_config['retry_interval']);
if(empty($this->_config['auth'])){
$redis->auth($this->_config['auth']);
}
$redis->select($this->_config['index']);
}catch(\Throwable $e){
throw new \Exception($e->getMessage());
}
return $redis;
}
}
?>