PHP:在多个请求中保持与 API 的 HTTPS 连接打开

PHP: Keep HTTPS Connection to API open throughout multiple requests

我正在为 wordpress 编写一个插件,需要为用户发出的每个请求调用 API。

这些 API 调用是使用 HTTPS 协议完成的。 目前,对于每个新用户请求,我都需要重新打开 HTTPS 连接。

是的,curl 允许持久连接(重复使用句柄或使用多句柄),但我想在多个用户请求中保持连接。

因此:是否可以通过多个 PHP 进程保持 HTTPS 连接打开并重新使用它?另一种方法是让用户的浏览器与 API-对话。但如果可能的话,我想避免这种情况。

虽然很多人会告诉您 PHP 不是为此设计的(并且它们在技术上是正确的),但此类问题已经通过使用持久事件循环得到解决。例如服务器端并发是通过 JavaScript 通过使用 node.js 实现的,它在侦听事件的单个线程上启动循环 运行ning。不同于典型的 PHP 设置,它在每次从网络服务器收到请求时启动一个新线程,您可以使用类似的架构(不幸的是命名) ReactPHP.

您的概念最大的障碍是它 运行宁作为 WordPress 插件。 WordPress 往往是 非常 最低公分母,所以如果你想让它工作,你将需要排除一些安装。最大的技巧是您将无法(轻松地)使用您的 WordPress 路由页面从这个 ReactPHP 循环加载。我知道您正在尝试避免额外的连接,但您可以通过连接到本地 ReactPHP 服务器以更低的延迟获得此 运行ning,而不是每次都获取远程连接。

如果您的服务器允许您打开一些本地端口,您可以像这样创建一个新的 ReactPHP 服务器:

$socket = new React\Socket\Server(8080, $loop);

如果您没有端口访问权限,您可以通过本地套接字设置连接。这可能需要更多的时间来设置,并且在进行常规安装时会更棘手:

$socket = new React\Socket\Server('unix://path/to/unix/socket', $loop);

我还没有完成设置的步骤,但是 如果 你可以让它工作,我认为这将是 WordPress 最可靠的方法,因为你将始终在您的插件中访问一些文件系统。

你应该能够看到如何断开你的持久连接,或者使用你构建服务器的 Closure,或者一些静态的 class 方法(首选,从那时起 class 可以负责在掉线时重新连接)。

use React\Http\Server;
use Psr\Http\Message\ServerRequestInterface as Request;
use React\Http\Response;
use MyNamespace\Api\ExternalService;

$server = new Server(function (Request $request) {
    $ch = ExternalService::getConnectionHandle();
    // Do something with your $ch based on the $request here

    return new Response(
        200,
        ['Content-Type' => 'application/json'],
        json_encode(/* some data from your request */)
    );
});

我将把 ExternalService 部分留给您,因为我确定您已经在此处进行了一些设置。

对于您的 WordPress 页面,他们现在可以向您的极低延迟本地 React 发出请求PHP。如果你想使用套接字,你可以尝试 fsockopen,或者如果你通过 TCP 使用简单的卷曲。

另一个难点是初始化服务器。如果它是您拥有的服务器,可以 shell 访问,可以 运行 cron 工作,或者有 exec(),这很简单:只需 运行 您的服务器脚本。否则,您将需要花几个小时将您的服务器配置为 运行 这个脚本在新请求时不会超时。

另一种选择是翻转它:如果你可以让整个应用程序在 ReactPHP 下提供服务(而不是先点击 WP 调度程序),你可以在没有所有本地连接的情况下做到这一点,并且直接跳转到持久连接。当然,这将使它无法作为 WordPress 插件分发。

说完一切后,您应该问问自己,节省这些请求的延迟是否真的值得付出努力。我不是你,所以我不能说,但如果你真的需要继续使用 WordPress 或 PHP,这就是你可以做到的。如果您可以删除 WordPress 部分(也许 //mydomain.com/blog 转到 WP,其他所有内容都由您的 ReactPHP 应用程序提供),您会发现这是一个指数级简单的问题。如果你可以摆脱 PHP,那么配置持久连接比没有配置更简单,因为这是 node 或 Go 中的标准方法。在架构上,它与在服务器启动时连接到您的数据库没有太大区别,而不是在每次连接时。

我最终通过浏览器发出了这些请求。 浏览器在服务器要求时保持 HTTP(S) 连接打开。

唉,这个解决方案有一些缺点:

  • 认证难度较大
  • 服务器负载增加,因为必须维护更多连接
  • 解决方案需要额外的 JavaScript

但是请求速度要快得多(大约 3 倍)并且 WordPress 运行 服务器上的负载最小化。