无国籍的PHP(和Symfony)

时间:2017-03-13 10:59:22

标签: php node.js symfony asynchronous stateless

TL; DR:我不确定这个主题在StackOverflow上是否占有一席之地,但基本上它只是一个辩论和思考如何制作PHP应用程序的话题,就像我们用NodeJS做的那样(无状态)请求流,异步调用等。)

情况

我们知道NodeJS既可以用作网络服务器,也可以用作网络应用程序。

但是对于PHP,the internal web-server is not recommended for production(文档也是如此)。

但是,由于Symfony全栈基于处理Kernel个对象的Request,这意味着我们能够向同一内核发送大量请求,只有我们可以" bootstrap"通过在侦听HTTP请求之前创建内核来运行php web-server(而不是app)。我们的路由器只会创建一个Request对象并让内核处理它。

但为此,Symfony应用程序必须无状态,例如我们需要Doctrine在请求后有效清除其工作单元,或者我们可能需要排序隔离基于请求的一些组件(通过使用其唯一的PHP类引用标识来识别请求?或者通过使用其他php进程?),显然,我们需要PHP中的更多异步内容或我们使用的方式内部网络服务器。

我有时会问自己的主要问题,现在向社区提问

为了澄清这一点,我对PHP有一些疑问:

  1. 为什么完全是不推荐用于制作的内部PHP网络服务器? 我的意思是,如果我们可以配置服务器的运行方式和它的"路由器"文件,我们应该像任何PHP服务器一样使用它,是或否?
  2. 内部如何表现?两个请求之间是否共享内存? 通过使用路由器,我很明显变量不会被共享,否则我们可以创建类似nodejs的应用程序,但似乎PHP无法做到这样的事情。
  3. 是否真的可以使用Symfony进行完全无状态的应用程序?
    例如我向同一个内核对象发送两个不同的请求,在这种情况下,这两个请求是否有可能在Symfony核心组件中产生冲突?
  4. 实际上,"创建内核的想法 - >启动服务器 - >根据请求,让内核处理它" 行为会很棒,因为它与NodeJS非常相似,但实际上,PHP范例与此不兼容,因为我们需要每个请求以异步方式处理。但是,如果一个内核及其容器是无状态的,那么应该一种方法来做那样的事情,不应该吗?
  5. 一些想法

    我已经听说React PHPRatchet PHP用于Websocket集成,IciclePHP-PM但从未体验过它们,对我来说似乎有点过于复杂现在(我可能缺乏关于应用中异步性的一些概念,这就是为什么我的大脑在得到更多答案之前不会理解的原因:D)。

    有没有办法将这些库用作"包装"我们的内核请求处理?

    我的意思是,让我们创建这个reactphp / icicle /无论环境设置如何,像在任何Symfony应用程序中一样创建我们的内核,并将应用程序作为web服务器运行,并且当检索到请求时,我们将它异步发送到我们的内核,只要内核没有发送响应,客户端就会等待它,即使响应是异步发送(来自嵌套回调等,如同的NodeJS)。

    这会使任何现有的Symfony应用程序与此范例兼容,只要该应用程序显然是无状态的。 (如果应用配置根据请求进行更改,则应用程序本身存在范例问题...)

    甚至可能是PHP库的现实,而不是以另一种方式使用PHP内部Web服务器?

    为什么要问这些问题?

    实际上,如果PHP可以在内部实现真正的异步内容(如Javascript),那将是一场革命,但这也会对PHP的性能产生重大影响,因为我们的Web服务器,更少引导(需要自动加载器,实例化内核,从缓存文件中获取大量内容,解决路由等)。

    在我的想法中,只有$kernel->handleRaw($request);会消耗CPU,其余的(容器,参数,服务等)将已经存在于内存中,或者,对于服务的情况,"等待实例化#34;然后,性能提升,我认为。

    对于那些仍然认为PHP是一种非常糟糕和缓慢的语言的人来说,它可能会让人感到厌烦:D

    对于读者和响应者;)

    如果一个核心PHP贡献者读到我,那么即使使用基于函数或类的特定新内部API,内部PHP是否有任何方式可以更加异步?

    我不是所有这些概念的专家,我希望真正优秀的专家能够阅读并回答我!

    如果所有这些都可以以任何方式,那么它可能是PHP世界的一大进步。

2 个答案:

答案 0 :(得分:4)

  

为什么不建议使用内部PHP Web服务器   生产?我的意思是,如果我们可以配置服务器的运行方式及其运行方式   "路由器"文件,我们应该能够像任何PHP服务器一样使用它,是或   没有?

因为它没有被编写为在加载下表现良好,并且没有配置选项可以让您在到达PHP之前处理的HTTP请求处理。

基本上,如果将它与nginx进行比较,它就缺少功能。这相当于将滑板与兰博基尼进行比较。

它可以让你从AB但是......你得到了要点。

  

内部如何表现?两个请求之间是否共享内存?   通过使用路由器,我觉得变量不是很明显   共享,否则我们可以制作类似nodejs的应用程序,但似乎PHP不是   能够做这样的事情。

文档说明它是单线程的,因此看起来它的行为与您编写while(true) { // all your processing here }的行为相同。

如果您在尝试编写代码之前无法设置正确的网络服务器,那么它就是一种可以快速检查一些内容的游戏。

  

是否真的可以使用完整的无状态应用程序   Symfony的?例如我向同一个内核对象发送两个不同的请求,   在这种情况下,这两个请求是否有可能创建一个   Symfony核心组件中的冲突?

为什么会转到同一个内核对象?为什么不以这样的方式设计您的应用哪个对象甚至处理服务器获取请求?为什么不设计冗余和高可用性?默认情况下,HTTP =无状态。您的任务=使处理请求的内容无关紧要。如果你避免与实际的处理服务器耦合(例如:不要将会话存储到本地文件系统等),这并不困难。

  

实际上,"创建内核的想法 - >启动服务器 - >根据要求,   让内核处理它"行为会很棒,因为它会   与NodeJS非常相似,但实际上是PHP范例   与此不兼容,因为我们需要每个请求   异步处理。但是如果内核及其容器是   无国籍,然后,应该有办法做这样的事情,   不应该吗?

实际上,nginx + php-fpm的行为几乎与node.js相同。

nginx使用reactor来处理同一线程上的所有连接。 Node.js完全相同。你所做的是创建一个闭包/回调,它被提供给Node的库,I / O在一个线程环境中处理。多线程是从您身上抽象出来的(与I / O相关,而不是CPU)。这就是为什么当您被要求执行CPU密集型任务时,您可以体验Node.js块。

nginx实现了完全相同的概念,除了这个回调不是用javascript编写的闭包。它是一个回调,需要在php-fpm秒内得到<timeout>的答案。 Nginx为您处理异步。你的任务是在PHP中编写你想要的东西。现在,如果您正在阅读一个巨大的文件,那么PHP中的异步代码是有意义的,除非它并不是真的需要。

使用nginx并向fastcgi工作人员发送处理请求,缩放变得微不足道。例如,让我们假设1台PHP机器不足以处理您正在处理的请求数量。没问题,可以在nginx池中添加更多机器。

这取自nginx docs:

upstream backend {
    server backend1.example.com       weight=5;
    server backend2.example.com:8080;
    server unix:/tmp/backend3;

    server backup1.example.com:8080   backup;
    server backup2.example.com:8080   backup;
}

server {
    location / {
        proxy_pass http://backend;
    }
}

您定义一个服务器池,然后分配与平衡请求处理方式相关的各种权重/代理选项。

但是,重要的是您可以添加更多服务器以应对可用性要求。

这就是为什么nginx + php-fpm堆栈具有吸引力的原因。由于nginx充当代理,它也可以将请求代理到node.js,让您在node.js中处理与Web套接字相关的操作(反过来,它可以执行对...的HTTP请求) PHP端点,允许您在PHP中包含整个应用程序逻辑。

我知道这个答案可能不是你所追求的,但我想强调的是node.js的工作方式(概念上)与nginx的工作方式相同处理传入的请求。你可以让php像节点那样工作,但是没有必要这样做。

答案 1 :(得分:2)

您的问题可以概括为:

&#34; PHP可能更像Node吗?&#34;

答案当然是&#34;是的。&#34;但这引出了另一个问题:

&#34; PHP应该更像Node吗?&#34;

现在答案并不那么明显。

当然,理论上PHP可以更像Node - 甚至可以使它完全相同。只需使用下一版本的Node并将其称为PHP 6.0或其他版本。

我认为它对Node和PHP都有害。出于某种原因,运行时环境存在多样性。其中一个变体是在给定环境中使用的并发模型。制作一个像另一个会对程序员来说意味着更少的选择。较少的选择是较少的言论自由。

PHP和Node是在不同时间创建的,原因各不相同。

PHP于1995年开发,名称代表Personal Home Page。用例是为HTML添加一些服务器端动态功能。那时我们已经有了SSI和CGI,但是人们希望能够同步注入HTML - 因为它没有多大意义 - 数据库查询和其他计算的结果。即使在今天,这项工作的好处也不足为奇。

另一方面,节点是在2009年开发的 - 大约15年后 - 用于创建高性能网络服务器。因此,在Node中编写这样的服务器很容易并且它们具有很好的性能特征不应该让我们感到惊讶。这就是Node首先创建的原因。它必须做出的选择之一是100%无阻塞的单线程异步事件循环环境。

现在,单线程并发在概念上比多线程更难。但是如果你想要I / O重型操作的性能,那么目前你没有其他选择。您将无法创建10,000个线程,但您可以在单个线程中轻松处理10,000个与Node的连接。 nginx是单线程的原因和为什么Redis是单线程的。 nginx和Redis的一个共同特征是惊人的性能 - 但这两者都很难写。

现在,就Node和PHP而言,这些技术相距甚远,甚至难以理解它们的融合效果。它提醒我the old April Fool's joke about unifying Perl and Python有这么多人相信。

PHP有其优势,Node具有优势。就像很难想象Node有阻塞I / O一样,用非阻塞I / O来设想PHP同样很难。

总结一下:有可能让PHP像Node一样,但我不希望它很快发生 - 如果有的话。