在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
一,系统配置.env 中配置redis [REDIS0] TYPE = redis HOST = 127.0.0.1 PORT = 6379 PASSWORD = 说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest 对应的源码可以访问这里获取: https://github.com/liuhongdi/ 说明:作者:刘宏缔 邮箱: [email protected] 二,编写php代码1,controller/Goods.php
class Goods extends BaseController { /** * 商品详情 * * @return \think\Response */ public function Detail(){ $rate = new RedisLuaRate(); $res = $rate->setRate(); $log = new BusinessLog("admin"); $log->log("rate res:".$res.":"); if ($res == "1") { return Result::Success("成功"); } else { return Result::Error("1","超出访问频率限制"); } } } 说明:此处仅做演示,实际应用时应该把这个拦截限流的功能放到middleware中
2,lib/util/RedisLuaRate.php
<?php namespace app\lib\util; class RedisLuaRate { function setRate() { $lua = <<<SCRIPT local key = KEYS[1]; local limit = tonumber(KEYS[2]) local length = tonumber(KEYS[3]) --redis.log(redis.LOG_NOTICE,' length: '..length) local current = redis.call('GET', key) if current == false then --redis.log(redis.LOG_NOTICE,key..' is nil ') redis.call('SET', key,1) redis.call('EXPIRE',key,length) --redis.log(redis.LOG_NOTICE,' set expire end') return '1' else --redis.log(redis.LOG_NOTICE,key..' value: '..current) local num_current = tonumber(current) if num_current+1 > limit then return '0' else redis.call('INCRBY',key,1) return '1' end end SCRIPT; $redis = new \Redis(); $redis->connect(env('redis0.host', '127.0.0.1'),env('redis0.port', '6379')); $redis->select(0); $key = "ip".request()->ip(); $sequence = $redis->eval($lua, [$key,3,1], 3); $luaError = $redis->getLastError(); if (isset($luaError)) { // print_r($luaError); } return $sequence; } } 说明: eval函数的第3个参数为KEYS个数。 phpredis依据此值将KEYS和ARGV做区分 三,测试效果1,用ab做并发测试:
liuhongdi@lhdpc:/data/php/admapi/app$ ab -c 10 -n 10 http://192.168.219.6:8000/goods/detail?goodsid=12323 This is ApacheBench, Version 2.3 <$Revision: 1879490 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 192.168.219.6 (be patient).....done Server Software: nginx/1.18.0 Server Hostname: 192.168.219.6 Server Port: 8000 Document Path: /goods/detail?goodsid=12323 Document Length: 37 bytes Concurrency Level: 10 Time taken for tests: 0.059 seconds Complete requests: 10 Failed requests: 7 (Connect: 0, Receive: 0, Length: 7, Exceptions: 0) Total transferred: 2276 bytes HTML transferred: 496 bytes Requests per second: 169.79 [#/sec] (mean) Time per request: 58.897 [ms] (mean) Time per request: 5.890 [ms] (mean, across all concurrent requests) Transfer rate: 37.74 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 1 0.5 1 2 Processing: 12 26 11.0 25 44 Waiting: 11 26 11.2 25 44 Total: 13 27 10.9 26 45 Percentage of the requests served within a certain time (ms) 50% 26 66% 29 75% 37 80% 42 90% 45 95% 45 98% 45 99% 45 100% 45 (longest request) 2,查看代码在日志中写入的结果:
2022-01-24 16:37:50--192.168.219.6--rate res:1: 2022-01-24 16:37:50--192.168.219.6--rate res:1: 2022-01-24 16:37:50--192.168.219.6--rate res:0: 2022-01-24 16:37:50--192.168.219.6--rate res:0: 2022-01-24 16:37:50--192.168.219.6--rate res:1: 2022-01-24 16:37:50--192.168.219.6--rate res:0: 2022-01-24 16:37:50--192.168.219.6--rate res:0: 2022-01-24 16:37:50--192.168.219.6--rate res:0: 2022-01-24 16:37:50--192.168.219.6--rate res:0: 2022-01-24 16:37:50--192.168.219.6--rate res:0: 可以看到在同一秒钟内,有三次返回成功,其余是返回失败 四,查看php和thinkphp的版本php:
liuhongdi@lhdpc:/data/php/admapi$ php --version PHP 8.1.1 (cli) (built: Dec 20 2021 16:12:16) (NTS) Copyright (c) The PHP Group Zend Engine v4.1.1, Copyright (c) Zend Technologies with Zend OPcache v8.1.1, Copyright (c), by Zend Technologies thinkphp:
liuhongdi@lhdpc:/var/www/html$ cd /data/php/admapi/ liuhongdi@lhdpc:/data/php/admapi$ php think version v6.0.10LTS
|
请发表评论