我正在开发一个 Web 应用。我有一个用 ElasticSearch 编制索引的图书数据库和用 PHP 编写的 REST API。
在应用程序中,有一个搜索框,我在其中输入书名,然后 JS 脚本调用搜索请求,然后使用搜索查询向 ElasticSearch 运行 curl 请求。
问题是,当用户快速输入时,请求太多。它开始变慢,尽管通常单个请求持续约 200 毫秒,但它会长达 5-10 秒,这太长了。我可以运行更少的请求,但我想要即时反馈。
所以我问 - 是不是因为我的服务器上的 curl 核心每次只运行一个请求,即使它们是在单独的 PHP 请求中调用的,还是其他原因?
答案1
简短的回答是“不是,它不是异步的”。较长的回答是“除非您自己编写后端来实现它。”
如果您使用 XHR,则每个请求在后端都会有不同的工作线程,这意味着任何请求都不应阻止其他请求,除非达到进程和内存限制。虽然 XHR 提供了一个基于事件的界面,但它仍然是一个由浏览器同步处理的实时 HTTP 请求(您在 js 中只有 1 个线程)。php 后端也在同步进行 curl 调用,直到 curl 调用完成才会返回 XHR 的 http 请求的结果。现在,您可以将 javascript 设置为轮询结果,但由于您的生存时间小于 3-5 秒,所以不值得这样做。
如果您使用 websocket,则必须告诉我们。给定的 websocket 与后端的一个进程绑定,但您可以在该进程中分叉/线程/执行任何操作。它还允许您直接将事件推送到浏览器,而无需客户端发起请求。这可以是异步的,但如果速度变慢是出现在后端,那么更改为异步设计也无济于事。
实际上,您应该让客户端 JavaScript 等待上一次搜索返回后再发出下一次搜索。在后端,为了防止 DOS,如果单个客户端开始向您发送过多的完成搜索请求,请开始丢弃 HTTP 429 请求,并在 JS 中处理 429 响应以进行增量退避,并在适当的情况下稍后重试。
您绝对应该做的另一件事是将 curl 中的请求超时设置为更低的值,以便它能够适当地超时。如果搜索数据仅在 2-3 秒内有用,那么您的 curl 请求超时应该大致相同。如果您的后端足够智能,它会将关闭的连接解释为“停止搜索”,并且希望您能够及时停止资源损失,以便另一个进程使用它们。
答案2
我的理解是,您有一个 Web 服务器,它运行一些可用于自动完成的脚本。此脚本使用 cURL 对另一台服务器运行查询。
首先,回答你的问题:你的网络服务器很可能可以并行运行多个 PHP 进程,而且由于 PHP 调用了 cURL,因此它也将并行运行。你没有说明你运行的是哪个网络服务器,但大多数都支持这一点。
但是,您的设置似乎非常依赖网络:每次按下键盘都会向您的服务器发出请求,而这又会向另一台服务器发出请求。如果您的服务器资源不足,或者另一台服务器设置了速率限制器,那么您的性能就会很差。也许可以将结果缓存在您的 Web 服务器上(这样您就不必经常使用 cURL),或者让您的 Javascript 等待几毫秒,这样人们就不会触发太多请求。