我可以在 Prefork MPM 下使用 Apache mod_proxy 作为连接池吗?
摘要/问题:
我有 Apache 与 Prefork MPM 一起运行,运行 php。我正在尝试使用 Apache mod_proxy 创建一个反向代理,我可以通过它重新路由我的请求,以便我可以使用 Apache 进行连接池。示例 impl:
在 httpd.conf 中:
SSLProxyEngine On
ProxyPass /test_proxy/ https://destination.server.com/ min=1 keepalive=On ttl=120
但是当我运行测试时,这是循环中的以下命令:
curl -G 'http://localhost:80/test_proxy/testpage'
它似乎没有重新使用连接。
经过进一步阅读后,听起来我没有获得连接池功能,因为我使用的是 Prefork MPM 而不是 Worker MPM。因此,每次我向代理发出请求时,它都会使用自己的连接池(大小为 1)启动一个新进程,而不是使用维护自己的连接池的单个工作进程。这样的解释对吗?
背景信息:
有一个外部服务器,我通过 https 向我运行的网站上点击的每个页面发出请求。
协商 SSL 握手的成本越来越高,因为我使用 php,而且它似乎不支持连接池 - 如果我的网站收到 300 个页面请求,他们必须与外部服务器进行 300 次 SSL 握手,因为连接会关闭每个脚本运行完毕后。
因此,我尝试在 Apache 下使用反向代理作为连接池,在 php 进程之间保持连接,这样我就不必经常进行 SSL 握手。
给我这个想法的来源:
Summary/Quesiton:
I have Apache running with Prefork MPM, running php. I'm trying to use Apache mod_proxy to create a reverse proxy that I can re-route my requests through, so that I can use Apache to do connection pooling. Example impl:
in httpd.conf:
SSLProxyEngine On
ProxyPass /test_proxy/ https://destination.server.com/ min=1 keepalive=On ttl=120
but when I run my test, which is the following command in a loop:
curl -G 'http://localhost:80/test_proxy/testpage'
it doesn't seem to re-use the connections.
After some further reading, it sounds like I'm not getting connection pool functionality because I'm using the Prefork MPM rather than the Worker MPM. So each time I make a request to the proxy, it spins up a new process with its own connection pool (of size one), instead of using the single worker that maintains its own pool. Is that interpretation right?
Background info:
There's an external server that I make requests to, over https, for every page hit on a site that I run.
Negotiating the SSL handshake is getting costly, because I use php and it doesn't seem to support connection pooling - if I get 300 page requests to my site, they have to do 300 SSL handshakes to the external server, because the connections get closed after each script finishes running.
So I'm attempting to use a reverse proxy under Apache to function as a connection pool, to persist the connections across php processes so I don't have to do the SSL handshake as often.
Sources that gave me this idea:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,您的测试方法无法演示连接池,因为对于每次调用,curl 客户端都会诞生然后消亡。就像死人不会说话一样,死进程也无法保持连接。
您的客户端会干扰您的代理服务器。
我们将此连接称为 A。您的代理服务器不执行任何操作,它只是一种炫耀。帅气又勤劳的服务员谦虚得躲在后面。
在这里,如果我没记错的话,安全连接是 A,而不是 B,对吗?
重复我的第一点,在您的测试中,您将为每个请求创建一个单独的客户端。每个客户端都需要一个单独的连接。连接是至少发生在两方之间的事情。一侧离开,连接丢失。
好吧,现在让我们忘记curl,一起看看我们真正想做的事情。
我们希望 A 端具有 SSL,并且希望 A 端的流量尽可能快。为了这个目的,我们已经把B面分开了,不会让A面更慢吧?
连接池? A 处不存在连接池这样的东西。每个客户端的来来往往都会产生很多噪音。唯一可以帮助您减少这种噪音的是“保持活动”,这意味着,在短时间内保持来自客户端的连接处于活动状态,以便该客户端可以请求其他文件,这些文件将应此请求的要求。当我们完成时,我们就完成了。
对于B上的连接,连接将被池化;但这不会给您带来任何性能,因为在单服务器设置上您没有这部分噪音产生。
我们如何帮助这个系统运行得更快?
如果这两个服务器在同一台机器上,我们应该摆脱炫耀的服务器并继续使用我们辛勤工作的网络服务器。给系统增加了很多不必要的工作。
如果这些是单独的机器,那么您至少可以从这个可怜的家伙那里获取加密(对于 ssl)负载,从而对 Web 服务器表示友善。然而,你可以变得更好。
如果您想继续使用 Apache,请从 mpm_prefork 切换到 mpm_worker。如果并发请求超过 300 个,这会效果更好。我真的不知道你们的硬件容量;但如果处理 300 个请求很困难,我相信这个小小的改变会对你的系统有很大帮助。
如果您想要一个更轻量级的系统,请考虑使用 nginx 作为 Apache 的替代品。使用 PHP 设置起来非常简单,而且性能会更好。
除了前端方面之外,还可以考虑检查您的数据库服务器。连接池将在这里发挥真正的作用。确保您的 PHP 安装配置为重用数据库连接。
此外,如果您在同一系统上托管静态文件,则可以将它们移至另一台 Web 服务器上,或者通过将静态文件移至具有 CDN(如 AWS 的 S3+CloudFront 或 <一个href="http://www.rackspace.com/cloud/cloud_hosting_products/files/" rel="nofollow">Rackspace 的 CloudFiles。即使没有 CloudFront,S3 也会让您满意。 Akamai 附带 Rackspace 的解决方案!
取出静态文件会让你的网络服务器“哦,发生了什么事,这沉默是什么?哦天哪!”因为您提到这是一个网站,并且网页大多数时候每个动态生成的 html 页面都有许多静态文件。
我希望你能把这个可怜的家伙从凶杀案中拯救出来。
First of all, your test method cannot demonstrate connection pooling since for every call, a curl client is born and then it dies. Like dead people don't talk a lot, a dead process cannot keep a connection alive.
You have clients that bothers your proxy server.
Let's call this connection A. Your proxy server does nothing, it is just a show off. The handsome and hardworking server is so humble that he hides behind.
Here, if I am not wrong, the secured connection is A, not B, right?
Repeating my first point, on your test, you are creating a separate client for each request. Every client needs a separate connection. Connection is something that happens between at least two parties. One side leaves and connection is lost.
Okay, let's forget curl now and look together at what we really want to do.
We want to have SSL on A and we want A side of traffic to be as fast as possible. For this aim, we have already separated side B so it will not make A even slower, right?
Connection pooling? There is no such thing as connection pooling at A. Every client comes and goes making a lot of noise. Only thing that can help you to reduce this noise is "Keep-Alive" which means, keeping connection alive from a client for some short period of time so this very same client can ask for other files that will be required by this request. When we are done, we are done.
For connections on B, connections will be pooled; but this will not bring you any performance since on one-server setup you did not have this part of the noise production.
How do we help this system run faster?
If these two servers are on the same machine, we should get rid of the show-off server and continue with our hardworking webserver. It adds a lot of unnecessary work to the system.
If these are separate machines, then you are being nice to web server by taking at least encyrption (for ssl) load from this poor guy. However, you can be even nicer.
If you want to continue on Apache, switch to mpm_worker from mpm_prefork. In case of 300+ concurrent requests, this will work much better. I really have no idea about the capacity of your hardware; but if handling 300 requests is difficult, I believe this little change will help your system a lot.
If you want to have an even more lightweight system, consider nginx as an alternative to Apache. It is very easy to setup to work with PHP and it will have a better performance.
Other than front-end side of things, also consider checking your database server. Connection pooling will make real difference here. Be sure if your PHP installation is configured to reuse connections to database.
In addition, if you are hosting static files on the same system, then move them out either on another web server or do even better by moving static files to a cloud system with CDN like AWS's S3+CloudFront or Rackspace's CloudFiles. Even without CloudFront, S3 will make you happy. Rackspace's solution comes with Akamai!
Taking out static files will make your web server "oh what happened, what is this silence? ohhh heaven!" since you mentioned this is a website and web pages have many static files for each dynamically generated html page most of the time.
I hope you can save the poor guy from the killer work.
Prefork 仍然可以为每个进程的每个后端服务器池 1 个连接。
Prefork 不一定为每个前端请求创建一个新进程,服务器进程本身是“池化”的,其行为取决于 MinSpareServers/MaxSpareServers 等。
为了最大限度地提高预派生进程为您提供后端连接的频率,请避免过高或过低的 maxspareservers 或过高的 minspareservers,因为这些将导致“新”进程接受新连接。
您可以在 LogFormat 指令中记录 %P,以帮助了解进程重用的频率。
Prefork can still pool 1 connection per backend server per process.
Prefork doesn't necessarily create a new process for each frontend request, the server processes are "pooled" themselves and the behavior depends on e.g. MinSpareServers/MaxSpareServers and friends.
To maximise how often a prefork process will have a backend connection for you, avoid very high or low maxspareservers or very high minspareservers as these will result in "fresh" processes acceptin new connections.
You can log %P in your LogFormat directive to help get an idea if how often processes are being reused.
我的例子中的问题是,反向代理和后端服务器之间的连接池没有发生,因为后端服务器 Apache 在每个 HTTPS 请求结束时关闭了 SSL 连接。
后端 Apache 服务器之所以这样做,是因为
httpd.conf
中存在以下指令:当后端服务器通过反向代理连接时,该指令没有意义,可以从后端服务器配置。
The Problem in my case was, the the connection pooling between reverse proxy and backend server was not taking place because of the Backend Server Apache closing the SSL connection at the end of each HTTPS request.
The backend Apache Server was doing this becuse of the following Directive being present in the
httpd.conf
:This directive does not make sense when the backend server is connected via a reverse proxy and this can be removed from the backend server config.