我想在服务提供者中生成唯一的请求ID,请问这么写有问题吗?

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        define('REQUIRED_ID', (string) \Illuminate\Support\Str::uuid());
    }
}
让PHP再次伟大
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 18

这个写日志官方不是给了你很好的示例吗 日志《Laravel 10 中文文档》

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response;

class AssignRequestId
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        $requestId = (string) Str::uuid();

        Log::withContext([
            'request-id' => $requestId
        ]);

        return $next($request)->header('Request-Id', $requestId);
    }
}
10个月前 评论
勇敢的心 (楼主) 10个月前

如果是在我前几年经常加班的时候,这么写我是认为毫无问题的,因为代码能跑就好了。

现在我不会这样写了,define是定义常量,在计算机科学中常量意味着是不会改变的量。例如周二的数字形态是2 ,我会这样写。

            const Tuesday = 2;//or define(Tuesday,2);

我觉得不妥,是因为这是编码的基础。这里不是说在laravel中在php中这样使用不妥,而是编码不应该这样,尽管基于fpm架构下可以这样写。

但如果用常量来表示变量的写法让你获得了某些收益,也不是未尝不可。

10个月前 评论
勇敢的心 (楼主) 10个月前

其实就是trace id的概念;不是强依赖唯一性,偶尔重复问题应该也不大;uuid 、雪花算法、 php自带的 uniqid; 我觉得都没问题;

不过在service provider里设置 trace id的地方是有待争议的;准确的来讲 trace id是跟随 request 产生的,你应该写在 index.php 里设置成request的属性


if (!$request->headers->has('X-TRACE-ID')) {
    $request->headers->set('X-TRACE-ID', genTraceId());
}

或者写一个 event listener, 监听request事件;在监听者里写上述代码;

10个月前 评论
FatTiger 10个月前

应该在中间件中做,不应该在服务提供者中做,服务提供者是用来注册服务的

10个月前 评论
勇敢的心 (楼主) 10个月前

没什么问题吧,有跨应用的需要吗,有就做一下“承上启下”

10个月前 评论
勇敢的心 (楼主) 10个月前

如果用octane的話 就有問題

10个月前 评论
勇敢的心 (楼主) 10个月前

能有什么问题?

10个月前 评论

这个不应该是前端请求的时候放在请求头里面吗

10个月前 评论
勇敢的心 (楼主) 10个月前
sanders

和楼主不同,我们除了定时脚本都是常驻内存的,所以单独进行了封装,并通过监听器和基类方法重写的方式将数据存到各个地方,以便于跟踪。

<?php

namespace App\Services\Trace;

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

/**
 * 生成跟踪数据
 */
class GenerateService
{
    /**
     * 生成跟踪数据
     *
     * @param string $referer
     * @return void
     */
    public function handle(string $referer): void
    {
        $id = Str::uuid()->toString();
        $this->handleById($id,$referer);
    }

    /**
     * 根据依赖注册的值还原跟踪数据并绑定日志
     *
     * @param string $id
     * @param string $referer
     * @return void
     */
    public function handleById(string $id, string $referer): void
    {
        $this->bind($id, $referer);
        Log::shareContext([
            config('trace.idName')  => $id,
            config('trace.referer') => $referer,
        ]);
    }

    /**
     * 绑定数据
     *
     * @param string $id 跟踪ID
     * @param string $referer 跟踪来源
     * @return void
     */
    public function bind(string $id, string $referer): void
    {
        app()->bind(config('trace.idName'), fn () => $id);
        app()->bind(config('trace.referer'), fn () => $referer);
    }

    /**
     * 解析数据
     *
     * @return array
     */
    public function resolveTraceData(): array
    {
        return  [
            config('trace.idName')  => app(config('trace.idName')),
            config('trace.referer') => app(config('trace.referer')),
        ];
    }
}

以上代码会根据 handle() 方法的调用将跟踪上下文混合到日志数据中去。

为了解决诸如请求出发队列这种问题,我们还将重写了 Illuminate\Queue\SerializesModels 的 __serialize() 方法 和 __unserialize() 方法,用来在队列中额外传递跟踪数据。

10个月前 评论
勇敢的心 (楼主) 10个月前
CodingHePing

只要不常驻内存就没毛病

10个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!