Laravel接口幂中间件

初始化

1. 新建中间件 app/Http/Middleware/UniqueLockMiddleware.php

<?php

declare(strict_types=1);

namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;

class UniqueLockMiddleware
{

    // 接口幂
    public function handle(Request $request, \Closure $next)
    {
        $lock = $request->route()->getAction('lock');
        if($lock === null){ // 未定义lock的属性 正常处理
            return $next($request);
        }
        $unique_value = $request[$lock['field']]; // 请求包的唯一标识 一般是id或者订单号
        if(empty($unique_value)){ // 唯一标识为空
            return $next($request);
        }
        $lock_key = sprintf("lock_%s_%s",$lock['prefix'],$unique_value);
        return Cache::lock($lock_key,10)->get(fn() => $next($request)); // 10秒超时
    }
}

注册全局路由中间件 app/Http/Kernel.php

'web' => [
....,
\App\Http\Middleware\UniqueLockMiddleware::class
]

使用例子

routes/web.php

...
Route::get('/order/{id}', [
   'uses' => \App\Http\Controllers\HelloController::class.'@test',
   'lock' => [
       'prefix' => 'order', // 路由唯一标识 不可重复 
       'field' => 'id' // 请求包的唯一字段 支持路由参数和请求包的参数
    ]
]);

原理

原子锁
注意:

注意:要想使用该特性,你的应用必须使用 memcached,dynamodb 或 redis 缓存驱动作为你应用的默认缓存驱动。此外,所有服务器必须与同一中央缓存服务器进行通信。

ps

是否可生产? 我生产环境就是这样的,不可用写他干嘛。

锁是否靠谱? 靠谱。 加了中间件后, 我用 wrkHTTP客户端 - 并发请求 测试,都锁住了。

(我cacheredis)

本作品采用《CC 协议》,转载必须注明作者和本文链接
专心学习不瞎搞
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 5

思路不错,虽然存在一定局限性。不过感觉 key 前缀可以用当前路径代替也不错。

9个月前 评论
Imuyu 9个月前

demo可以搞,生产不可用

9个月前 评论

如果是以id去锁的情况请求完成后应该把锁释放掉 避免影响下一次请求

9个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
87
粉丝
105
喜欢
480
收藏
717
排名:109
访问:8.7 万
私信
所有博文
社区赞助商