根据上下文,"部署"一词可以有两种含义.您还将Apache / Nginx的角色与其他组件的角色混淆.
Apache vs Nginx
Apache和Nginx都不能为Ruby Web应用程序提供开箱即用的服务,您需要使用Apache / Nginx与某种加载项结合使用,稍后再说.
Apache和Nginx也可以作为反向代理,这意味着他们可以接收传入的HTTP请求,并将其转发到另一个也是HTTP的服务器.当服务器使用HTTP响应进行响应时,Apache / Nginx会将响应转发回客户端;您稍后将了解为什么这是相关的.
Mongrel and other production app servers vs WEBrick
- Loads your Ruby app inside its own process space.
- Sets up a TCP socket, allowing it to communicate with the outside world (e.g. the Internet).
Mongrel listens for HTTP requests on this socket and passes the request data to the Ruby web app.
- The Ruby web app then returns an object, which describes what the HTTP response should look like, and Mongrel takes care of converting it to an actual HTTP response (the actual bytes) and sends it back over the socket.
- Phusion Passenger
- Trinidad (JRuby only)
- TorqueBox (JRuby only)
- WEBrick is not fit for production, unlike everything else that I mentioned before. WEBrick is written entirely in Ruby. Mongrel (and most other Ruby app servers) is part Ruby and part C (Mostly Ruby), but its HTTP parser is written in C for performance.
- WEBrick is slower and less robust. It has some known memory leaks and some known HTTP parsing problems.
- WEBrick is usually only used as the default server during development because WEBrick is included in Ruby by default. Mongrel and other app servers needs to be installed separately. It's not recommended to use WEBrick in production environments, though for some reason Heroku chose WEBrick as its default server. They were using Thin before, so I have no idea why they switched to WEBrick.
The app server and the world
- App servers that can be directly exposed to the Internet: Phusion Passenger, Rainbows
- App servers that may not be directly exposed to the Internet: Mongrel, Unicorn, Thin, Puma. These app servers must be put behind a reverse proxy web server like Apache and Nginx.
- I don't know enough about Trinidad and TorqueBox, so I've omitted them.
- Some app servers can only handle 1 request concurrently, per process. If you want to handle 2 requests concurrently you need to run multiple app server instances, each serving the same Ruby app. This set of app server processes is called an app server cluster (hence the name Mongrel Cluster, Thin Cluster, etc). You must then setup Apache or Nginx to reverse proxy to this cluster. Apache/Nginx will take care of distributing requests between the instances in the cluster (More on this in section "I/O concurrency models").
- The web server can buffer requests and responses, protecting the app server from "slow clients" - HTTP clients that don't send or accept data very quickly. You don't want your app server to do nothing while waiting for the client to send the full request or to receive the full response, because during that time the app server may not be able to do anything else. Apache and Nginx are very good at doing many things at the same time because they're either multithreaded or evented.
- Most app servers can serve static files, but are not particularly good at it. Apache and Nginx can do it faster.
- People typically set up Apache/Nginx to serve static files directly, but forward requests that don't correspond with static files to the app server, it's good security practice. Apache and Nginx are very mature and can shield the app server from (perhaps maliciously) corrupted requests.
- Phusion Passenger is a very different beast from all the other app servers. One of its unique features is that it integrates into the web server.
- The Rainbows author publicly stated that it's safe to directly expose it to the Internet. The author is fairly sure that there are no vulnerabilities in the HTTP parser (and similar). Still, the author provides no warranty and says that usage is at own risk.
Application servers compared
在本节中,我将比较我提到的大多数应用程序服务器,但不是Phusion Passenger. Phusion乘客是一个不同的野兽,我给了它一个专门的部分.我也省略了特立尼达和TorqueBox,因为我不太了解他们,但如果你使用JRuby,他们只是相关.
- Mongrel was pretty bare bones. As mentioned earlier, Mongrel is purely single-threaded multi-process, so it is only useful in a cluster. There is no process monitoring: if a process in the cluster crashes (e.g. because of a bug in the app) then it needs to be manually restarted. People tend to use external process monitoring tools such as Monit and God.
- Unicorn is a fork of Mongrel. It supports limited process monitoring: if a process crashes it is automatically restarted by the master process. It can make all processes listen on a single shared socket, instead of a separate socket for each process. This simplifies reverse proxy configuration. Like Mongrel, it is purely single-threaded multi-process.
- Thin uses the evented I/O model by utilizing the EventMachine library. Other than using the Mongrel HTTP parser, it is not based on Mongrel in any way. Its cluster mode has no process monitoring so you need to monitor crashes etc. There is no Unicorn-like shared socket, so each process listens on its own socket. In theory, Thin's I/O model allows high concurrency, but in most practical situations that Thin is used for, one Thin process can only handle 1 concurrent request, so you still need a cluster. More about this peculiar property in section "I/O concurrency models".
- Puma was also forked from Mongrel, but unlike Unicorn, Puma is designed to be purely multi-threaded. There is therefore currently no builtin cluster support. You need to take special care to ensure that you can utilize multiple cores (More about this in section "I/O concurrency models").
- Rainbows supports multiple concurrency models through the use of different libraries.
Phusion Passenger 的工作方式与所有其他工作方式截然不同. Phusion Passenger直接集成到Apache或Nginx中,因此可以与Apache的mod_php进行比较.就像mod_php允许Apache服务PHP应用程序一样,几乎神奇的是,Phusion Passenger允许Apache(和Nginx!)几乎神奇地服务Ruby应用程序. Phusion乘客的目标是使一切正常工作(tm)尽可能少的麻烦.
不要为您的应用程序启动一个进程或集群,而是配置Apache / Nginx为Phusion Passenger提供静态文件和/或反向代理请求到进程/集群,您只需要:
- You edit the web server config file and specify the location of your Ruby app's 'public' directory.
- There is no step 2.
所有配置都在Web服务器配置文件中完成. Phusion Passenger几乎自动化了一切.不需要启动集群和管理进程.启动/停止进程,当它们崩溃时重新启动它们等等 - 全部自动化.与其他应用服务器相比,Phusion Passenger的移动部件少得多.这种易用性是人们使用Phusion Passenger的主要原因之一.
与其他应用程序服务器不同,Phusion Passenger主要用C ++编写,因此速度非常快.
Phusion Passenger vs other app servers
- Dynamically adjusting the number of processes based on traffic. We run a ton of Rails apps on our resource-constrainted server that are not public-facing, and that people in our organization only use at most a few times a day. Things like Gitlab, Redmine, etc. Phusion Passenger can spin down those processes when they're not used, and spinning them up when they're used, allowing more resources to be available for more important apps. With other app servers, all your processes are turned on all the time.
- Some app servers are not good at certain workloads, by design. For example Unicorn is designed for fast-running requests only: See the Unicorn website section "Just Worse in Some Cases".
- Streaming workloads (e.g. Rails 4 live streaming or Rails 4 template streaming).
- Workloads in which the app performs HTTP API calls.
Phusion Passenger Enterprise 4 或更高版本中的混合I / O模型使其成为这些各种工作负载.
- Other app servers require the user to run at least one instance per application. By contrast, Phusion Passenger supports multiple applications in a single instance. This greatly reduces administration overhead.
- Automatic user switching, a convenient security feature.
- Phusion Passenger supports many MRI Ruby, JRuby and Rubinius. Mongrel, Unicorn and Thin only support MRI. Puma also supports all 3.
- Phusion Passenger actually supports more than just Ruby! It also supports Python WSGI, so it can for example also run Django and Flask apps. In fact Phusion Passenger is moving into the direction of becoming a polyglot server. Node.js support on the todo list.
- Out-of-band garbage collection. Phusion Passenger can run the Ruby garbage collector outside the normal request/response cycle, potentially reducing request times by hundreds of milliseconds. Unicorn also has a similar feature, but Phusion Passenger's version is more flexible because
1) it's not limited to GC and can be used for arbitrary work.
2) Phusion Passenger's version works well with multithreaded apps, while Unicorn's does not.
- Automated rolling restarts. Rolling restarts on Unicorn and other servers require some scripting work. Phusion Passenger Enterprise completely automates this way for you.
有更多的特点和优点,但列表真的很长.您应参阅全面的Phusion Passenger手册( Apache版本, Nginx版本)或 Phusion Passenger网站.
I/O concurrency models
- Single-threaded multi-process. This is traditionally the most popular I/O model for Ruby app servers, partially because multithreading support in the Ruby ecosystem was very bad. Each process can handle exactly 1 request at a time. The web server load balances between processes. This model is very robust and there is little chance for the programmer to introduce concurrency bugs. However, its I/O concurrency is extremely limited (limited by the number of processes). This model is very suitable for fast, short-running workloads. It is very unsuitable for slow, long-running blocking I/O workloads, e.g. workloads involving the calling of HTTP APIs.
- Purely multi-threaded. Nowadays the Ruby ecosystem has excellent multithreading support, so this I/O model has become very viable. Multithreading allows high I/O concurrency, making it suitable for both short-running and long-running blocking I/O workloads. The programmer is more likely to introduce concurrency bugs, but luckily most web frameworks are designed in such a way that this is still very unlikely. One thing to note however is that the MRI Ruby interpreter cannot leverage multiple CPU cores even when there are multiple threads, due to the use of the Global Interpreter Lock (GIL). You can work around this by using multiple multi-threaded processes, because each process can leverage a CPU core. JRuby and Rubinius have no GIL, so they can fully leverage multiple cores in a single process.
- Hybrid multi-threaded multi-process. Primarily implemented by Phusion Passenger Enterprise 4 and later. You can easily switch between single-threaded multi-process, purely multithreaded, or perhaps even multiple processes each with multiple threads. This model gives the best of both worlds.
- Evented. This model is completely different from the previously mentioned model. It allows very high I/O concurrency and is therefore excellent for long-running blocking I/O workloads. To utilize it, explicit support from the application and the framework is required. However all the major frameworks like Rails and Sinatra do not support evented code. This is why in practice a Thin process still cannot handle more than 1 request at a time, making it effectively behave the same as the single-threaded multi-process model. There are specialized frameworks that can take advantage of evented I/O, such as Cramp.
最近在Phusion博客上发布了一篇文章,介绍如何优化调整您的工作负载的进程和线程数.请参见调整Phusion Passenger的并发设置. / p>
- Uploading the Ruby app's code and files to the server machine.
- Installing libraries that your app depends on.
- Setting up or migrating the database.
- Starting and stopping any daemons that your app might rely on, such as Sidekiq/Resque workers or whatever.
- Any other things that need to be done when you're setting up your application.