开放的编程资料库

当前位置:我爱分享网 > Python教程 > 正文

使用 Swoole 进行异步表达

你用过Node.js吗?

对于那些不熟悉Node.js的读者,它是一个服务器端JavaScript框架,提供创建网络服务等功能。为此,它提供了一个事件循环,允许诸如异步处理之类的事情。

在PHP生态系统中,一群中国开发人员一直在创建一个扩展,它提供许多与Node.js相同的功能。这个名为Swoole的扩展允许您创建具有异步功能的网络服务器。在许多情况下,异步功能是通过协程处理的,允许您编写仍然受益于系统事件循环的异步特性的正常同步代码,允许您的服务器在新请求进入时继续响应它们!

我们一直在逐渐添加和完善我们在Expressive中的Swoole支持,并且最近发布了一个稳定版本,可以与任何PSR-15请求处理程序一起使用。在这篇文章中,我将列举我认为在部署PHP中间件应用程序时考虑Swoole的原因。

我觉得Swoole以及任何asyncPHP运行时都具有三个关键优势:

  • 特定于应用程序的服务器
  • 性能
  • 异步处理

特定于应用程序的服务器

应用程序有几种通用架构:

  • 位于多个Web应用程序前面的单个Web服务器。
  • 位于单个Web应用程序前面的单个Web服务器。
  • 位于多个Web应用程序前面的负载均衡器许多服务器的前面。一些服务器可能服务于相同的应用程序,以提供冗余。(如今,这些甚至可能是相同的docker容器。)

第一种场景常见于内部网络和开发,以及许多共享主机场景。然而,它通常被认为不太安全,因为一个应用程序中的漏洞可能会升级以影响服务器上托管的所有应用程序。此外,这意味着对PHP版本的任何更新都必须在所有应用程序上进行测试,这通常意味着更新很少而且相隔很远——从安全角度来看,这也是一个问题。

当您想要隔离环境时,您将转移到单个Web服务器、单个PHP应用程序模型:

当您开始扩展时,它就变成了一个负载均衡器,位于许多这些Web服务器/PHP应用程序对的前面:

在最后两个场景中的每一个场景中,我都想指出一件事:您的应用程序至少包含两个不同的服务:PHP进程和Web服务器。

您可能还有其他服务,例如RDBMS或文档数据库、缓存、搜索等。但通常这些服务位于不同的服务器上并单独扩展。因此,他们不在讨论范围内。

您可能还有其他服务,例如RDBMS或文档数据库、缓存、搜索等。但通常这些服务位于不同的服务器上并单独扩展。因此,他们不在讨论范围内。

在这些场景中,这意味着每个“服务器”实际上是一个组合。当您向架构添加冗余时,这会显着增加复杂性。这是每个节点上的一个可能失败的进程,以及部署时需要的额外配置。

当我们开始考虑微服务时,这就变得更成问题了。微服务应该快速且易于部署;每个容器一项服务既典型又理想。

Swoole让我们做的是移除一层复杂性。

我们可以为每个容器提供一个服务,并且该容器可以仅使用PHP构建。我们启动SwooleHTTP服务器,它已准备就绪。然后我们告诉反向代理或负载均衡器如何路由到它,我们就完成了。

这在每种情况下都很有用,包括一个Web服务器/多个应用程序的情况,因为我们可以为每个应用程序使用不同的PHP运行时。我们的“Web服务器”变成了反向代理。

特定于应用程序的服务器使我们能够简化部署,并快速交付微服务。

性能

还记得PHP7发布时,它就像将您的应用程序的性能提高了一倍吗?

如果你能再做一次呢?

在我们对Expressive应用程序的初始基准测试中,我们发现它们在Swoole下的性能是传统nginx+php-fpmp对下的四倍。更有趣的是:当对大量并发请求进行基准测试时,我们还发现Swoole的失败请求更少。这意味着您将获得更好的性能和更好的弹性!

点击量不断增加:当我们启用Swoole的协程支持和使用由该协程支持支持的功能的基准端点时,我们观察到高达十倍的增长!

协程支持主要涵盖网络I/O操作。因此,命中缓存服务器、使用PDO或发出Web请求的操作会立即从中受益,而无需更改您的代码。

协程支持主要涵盖网络I/O操作。因此,命中缓存服务器、使用PDO或发出Web请求的操作会立即从中受益,而无需更改您的代码。

Swoole通过多种方式实现了这一点。首先,因为你只启动一个服务器一次,你就失去了启动你的应用程序的代价,而你通常在每次请求时都会产生这种代价;从您开始接受请求的那一刻起,您的应用程序就会启动。引导通常占应用程序中最大的单次资源使用量。

其次,Swoole作为事件循环运行,就像Node.js一样,允许它推迟处理长时间运行的请求,以便响应新的传入请求。这就引出了我的最后一点。

异步处理

Swoole的事件循环为PHP应用程序提供异步功能。虽然在过去五年左右的时间里出现了许多为PHP提供异步功能的用户空间库,但Swoole是作为原生C扩展完成的,并且可以在任何操作系统上运行。

当你有一个事件循环时,你可以推迟处理,这允许服务器响应额外的请求。通常,延期可以是明确的:

public function handle(ServerRequestInterface $request) : ResponseInterface
{
    $ts = new DateTimeImmutable();
    \Swoole\Event::defer($this->createCacheDeferment($ts));
    return new EmptyResponse(202);
}

public function createCacheDeferment(DateTimeImmutable $ts) : callable
{
    return function () use ($ts) {
        sleep(5);
        $now = new DateTimeImmutable();
        $item = $this->cache->getItem('ts');
        $item->set(sprintf(
            "Started: %s\nEnded: %s",
            $ts->format('r'),
            $now->format('r')
        ));
        $this->cache->save($item);
    };
}

在这个例子中,我们计算要返回的内容,延迟缓存,并立即返回响应。这意味着您的用户无需等待您完成缓存内容。

日志记录是另一个用例。在ExpressiveSwoole绑定中,我们在将响应标记为完成后进行访问日志记录。这可确保日志记录不会影响响应时间。

另一个用例是webhook。您的应用程序可以立即接受负载,但在将响应发送回客户端后完成处理。

Swoole还提供了通用文件系统操作、Mysql、Redis和HTTP客户端的异步版本。在每一个中,您都提供一个回调,指示操作完成后应该做什么:

use Swoole\Http\Client as HttpClient;

$client = new HttpClient('https://example.com');
$client->setHeaders([
    'Accept' => 'application/json',
    'Authorization' => sprintf('Bearer %s', $token),
]);

// Make the request, telling it what code to execute once
// it is complete:
$client->get('/api/resource', function ($response) {
    // process the response 
});

// This code executes before the request completes:
$counter++;

当你有许多相互依赖的延迟时,像上面这样的代码导致了术语“回调地狱”。那么,如果你希望你的代码是“非阻塞的”,又不想一直写回调怎么办呢?好吧,最近版本的Swoole允许你为大多数I/O操作启用协程支持。这意味着您可以像在同步环境中一样编写代码,但是每当触发协程的代码出现时,服务器将推进事件循环,允许它在当前的工作完成之前回答额外的请求,然后继续执行一次。

// This spawns a coroutine:
$statement = $pdo->query($sql);

异步功能可能不会直接提高应用程序的性能,但它会让让您的应用程序响应更多请求,让您能够处理更大的流量!

zend-expressive-swoole

两周前我们发布了zendframework/zend-expressive-swoole1.0.0。这个库充当zend-httphandlerrunnerRequestHandlerRunner实现,这意味着:

  • 它可以与任何PSR-15应用程序一起使用。
  • 它可以与任何PSR-7实现一起使用。

换句话说,如果您想将Swoole与即将推出的Slim4或withequip/dispatch或withnorthwoods/broker或任何现有的无数PSR-15调度系统一起使用,您可以。

该库为用户提供了一些有趣的功能:

  • 使用HTTP客户端缓存标头提供静态资源。
  • 可配置的日志记录。
  • 能够重新启动工作进程。

过去两个月我一直在它的版本上运行应用程序,并注意到它一直稳定可靠。我绝对认为值得试一试!

我对Swoole和其他异步系统的可能性感到非常兴奋,因为我认为它们为我们提供了更好的性能、更好的可靠性,以及在我们响应客户端之前推迟不需要完成的功能的能力。不过,我很想听听您的经历,尤其是以博客文章的形式!通过评论或推特atme向我发送指向博客文章的链接,我会将其添加到采埃孚时事通讯中。

更新

  • 2018-10-17:修复了第一句中的拼写错误。
未经允许不得转载:我爱分享网 » 使用 Swoole 进行异步表达

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏