在 PHP 中获取唯一的工作线程/线程/进程/请求 ID


Get unique worker/thread/process/request ID in PHP

在多线程环境中(如大多数Web平台(,我经常在应用程序的日志中包含某种线程ID。这让我能够准确地告诉哪个日志条目来自哪个请求/线程,当同时有多个请求同时写入同一日志时。

在 .NET/C# 中,这可以通过 log4net 的格式化程序来完成,默认情况下,格式化程序包括当前线程的ManagedThreadId(数字(或Name(给定名称(。这些属性唯一标识线程(例如:如何使用 log4net 记录线程池线程的正确上下文?

在PHP

中,我没有找到类似的东西(我问了Google,PHP文档和SO(。它存在吗?

直到

最近,我还使用apache_getenv("UNIQUE_ID"(,它与crc32或其他哈希函数完美配合。

现在我只是使用以下方法,以消除对 Apache 和这个 mod 的依赖。

$uniqueid = sprintf("%08x", abs(crc32($_SERVER['REMOTE_ADDR'] . $_SERVER['REQUEST_TIME'] . $_SERVER['REMOTE_PORT'])));

它足够独特,可以了解哪些日志属于哪个请求。如果需要更高的精度,可以使用其他哈希函数。

希望这有帮助。

zend_thread_id()

int zend_thread_id ( void ) 

此函数返回当前线程的唯一标识符。

虽然:

仅当PHP构建了ZTS(Zend Thread Safety(支持和调试模式(--enable-debug(时,此函数才可用。


您也可以尝试调用mysql_thread_id(),当您使用该API进行数据库访问时(或使用mysqli时mysqli::$thread_id(。

PHP 似乎没有可用的函数,但您的 Web 服务器可能能够通过环境变量传递标识符。例如,有一个名为"mod_unique_id"[1]的Apache模块,它为每个请求生成一个唯一标识符,并将其存储为环境变量。如果变量存在,它应该可以通过 $_SERVER['unique_id'] [2] 可见

">

纯PHP"解决方案可以是编写一个脚本来生成合适的随机标识符,通过define("unique_id",val(存储它,然后在php中使用auto_prepend_file[3]选项.ini将其包含在每个执行的脚本中。这样,唯一 id 将在请求开始处理时创建,并且在处理请求期间可用。

  • [1] http://httpd.apache.org/docs/current/mod/mod_unique_id.html
  • [2] http://forums.devshed.com/php-development-5/server-unique-id-questions-163269.html
  • [3] http://www.php.net/manual/en/ini.core.php#ini.auto-prepend-file

我已经看到 getmypid(( 用于此目的,但它在不同的系统上的行为似乎不同。在某些情况下,ID 对于每个请求都是唯一的,但在其他情况下,它是共享的。

因此,您可能最好使用其他答案之一来确保可移植性。

分配 ID 以识别为请求提供服务的记录数据可能就像创建 UUID 版本 4(随机(并将其写入日志的每一行一样简单。

甚至还有软件可以帮助解决这个问题:ramsey/uuid,php-middleware/request-id

使用 log4php 时,通过将 UUID 放入 LoggerMDC 数据并使用适当的 LogFormatter,可以轻松地将其添加到每一行日志记录中。使用PSR-3记录器,它可能有点复杂,YMMV。

随机创建的 UUID 将适合标识单个请求,通过在子请求的 HTTP 标头和响应中使用该 UUID,甚至可以跨服务器场内的多个系统和平台跟踪一个请求。但是,将其作为标头不是我提到的任何包的任务。