Web 服务器范式的差异(Apache 与反向代理 + Web 服务器)

Difference in web server paradigms (Apache vs. Reverse proxy + Web server)

我在 Rails 上开始使用 Ruby 进行开发,当它出现时我遇到了被描述为 a different paradigm 的情况到网络服务器。

Old paradigm (apache)
=====================

                +--- web process fork
                |
[requests] -----+--- web process fork
                |
                +--- web process fork


New paradigm (Puma + Nginx)
===========================
                                           +---> web app process 1 --> threads
                                           |
[requests] <-->  [reverse proxy server]  --+---> web app process 2 --> threads
                                           |
                                           +---> web app process 3 --> threads

在我正在阅读的文章中,它并没有试图解释这两种范式之间的差异,以及一种范式相对于另一种范式的优势。这就是我感兴趣的。

Ruby 在 Rails 应用程序上使用这种新范例有何意义?与旧的 HTTP 守护进程方式相比有什么优势?它有什么缺点?

应用服务器架构具有以下特点:

Across the board, I’m in favor of running Web applications as app servers and reverse-proxying to them. It takes minimal effort to set this up, and the benefits are plenty: you can manage your web server and app separately, you can run as many or few app processes on as many machines as you want without needing more web servers, you can run the app as a different user with zero effort, you can switch web servers, you can take down the app without touching the web server, you can do seamless deployment by just switching where a fifo points, etc. Welding your application to your web server is absurd and there’s no good reason to do it any more.

与经典款相比:

PHP is naturally tied to Apache. Running it separately, or with any other webserver, requires just as much mucking around (possibly more) as deploying any other language. php.ini applies to every PHP application run anywhere. There is only one php.ini file, and it applies globally; if you’re on a shared server and need to change it, or if you run two applications that need different settings, you’re out of luck; you have to apply the union of all necessary settings and pare them down from inside the apps themselves using ini_set or in Apache’s configuration file or in .htaccess. If you can. Also wow that is a lot of places you need to check to figure out how a setting is getting its value. Similarly, there is no easy way to “insulate” a PHP application and its dependencies from the rest of a system. Running two applications that require different versions of a library, or even PHP itself? Start by building a second copy of Apache. The “bunch of files” approach, besides making routing a huge pain in the ass, also means you have to carefully whitelist or blacklist what stuff is actually available, because your URL hierarchy is also your entire code tree. Configuration files and other “partials” need C-like guards to prevent them from being loaded directly. Version control noise (e.g., .svn) needs protecting. With mod_php, everything on your filesystem is a potential entry point; with an app server, there’s only one entry point, and only the URL controls whether it’s invoked. You can’t seamlessly upgrade a bunch of files that run CGI-style, unless you want crashes and undefined behavior as users hit your site halfway through the upgrade.

其他范例包括:

  • Web应用是一个Web服务器,可以直接接受HTTP请求。此模型的示例:

  • Web 应用程序不直接使用 HTTP,而是通过一些通信适配器直接连接到 Web 服务器。 CGI、FastCGI 和 SCGI 就是很好的例子。 (web.py, flask, sinatra)

            start()
  -----------------------------
  |                           |
  | init()                    |
 NEW ->-- INITIALIZING        |
 | |           |              |     -------------------- STARTING_PREP -->- STARTING -->- STARTED -->---  |
 | |         |                                                            |  |
 | |destroy()|                                                            |  |
 | -->--------- STOPPING ------>----- STOPPED ----->-----
 |    \|/                               ^                     |  ^
 |     |               stop()           |                     |  |
 |     |       --------------------------                     |  |
 |     |       |                                              |  |
 |     |       |    destroy()                       destroy() |  |
 |     |    FAILED ---->------ DESTROYING --------------------    \|/                         |
 |                                 DESTROYED                     |
 |                                                               |
 |                            stop()                             |
 --->------------------------------>------------------------------

On Heroku, apps are completely self-contained and do not rely on runtime injection of a webserver into the execution environment to create a web-facing service. Each web process simply binds to a port, and listens for requests coming in on that port. The port to bind to is assigned by Heroku as the PORT environment variable.

参考资料