Ruby解释器如何与Apache等HTTP服务器集成?

时间:2017-01-11 18:24:15

标签: ruby-on-rails ruby apache

我一直想知道Ruby如何与Apache等HTTP服务器集成。作为Java开发人员,我理解servlet容器的完整堆栈以及整个生命周期的工作方式以及如何使用servlet或过滤器将不同的Web框架集成到标准化的容器HTTP生命周期中。

话虽如此,我从未明白像Ruby这样的其他框架是如何设法挂钩到apache服务器的。是通过C api吗?其他一些标准?

3 个答案:

答案 0 :(得分:2)

Ruby不能单独使用Apache,Apache是​​一个Web服务器,Ruby需要一个应用服务器,因为它是一种解释语言。维基百科的“Interpreted language”页面提供了更多关于解释语言的信息。

Ruby与Apache一起使用,如Passenger这样的应用服务器。阅读Digital Ocean的"How To Deploy a Rails App with Passenger and Apache on Ubuntu 14.04"教程以获取更多信息。

我个人也使用Passenger Phusion + Nginx部署了Ruby应用程序。

答案 1 :(得分:2)

有很多不同的方法可以做到这一点。

CGI

最古老的方式是通用网关接口(CGI),它于1993年在NCSA网络服务器中引入,并且自那以后每个网络服务器都支持。这是一个非常简单的协议:Web服务器设置一组标准化的环境变量,其中包含有关请求的信息,调用程序,然后该程序可以检查环境变量并将其响应写入stdout,Web服务器只是将其发回。下一个请求将重新开始循环(和程序)。

这是Ruby中一个非常简单的CGI示例(我没有安装Apache,所以我无法对此进行测试):

#!/usr/bin/env ruby

# We need to send the header as well, the webserver won't do it for us
puts 'Content-type: text/html'
puts

puts <<~"HTML"
  <!DOCTYPE html>
  <html lang="en">
    <head>
      <meta charset="utf-8">
      <title>CGI Demo Script in Ruby</title>
    </head>
    <body>
      <p>
        My name is #{ENV['SCRIPT_NAME']} and you called me with the path #{ENV['PATH_INFO']} and query string #{ENV['QUERY_STRING']}.
     </p>
    </body>
  </html>
HTML

的FastCGI

由于CGI为每个请求启动一个新进程,并且通过环境变量和stdout的通信也不是很有效,FastCGI是在1996年创建的。这个想法类似于CGI,但是处理程序进程没有启动对于每个请求,而处理程序进程停留在内存中并在循环中处理请求,并且Web服务器和处理程序之间的通信使用有效的二进制协议。

通信使用Unix套接字或TCP。

SCGI

2006年出版的简单通用网关接口(SCGI)类似于FastCGI,但更简单并且使用基于文本的通信协议(基于网络串)而不是二进制通信协议。它还避免了为每个请求启动进程的开销,而是处理程序继续运行并简单地在循环中处理请求。

进程内模块

几乎每个网络服务器都有一个模块API,允许您将自己的代码添加到正在运行的Web服务器进程中。其中最早的一个是Netscape NSAPI,它出现在90年代中期,是CGI的直接竞争对手,FastCGI OTOH是作为对它的反应而开发的。 IIS,Apache,Nginx等也都有类似的API。这些与FastCGI和SCGI的不同之处主要在于它们不是作为单独的进程运行,而是在Web服务器进程中运行。这为他们提供了最大的性能和对Web服务器内部的最大访问权限,但也是最大的损坏可能性。

在Web服务器中运行Ruby执行引擎有几个模块。 mod_ruby是用于在Apache内部嵌入MRI的Apache模块,mod_rubinius为Rubinius做了同样的事情。 IronRuby可以作为插件在IIS内部运行。

这是PHP(mod_php)和Perl(mod_perl)经典使用的解决方案。还有mod_python,甚至是mod_monomod_java

Webserver接口

Webserver接口提供Web框架和Web服务器之间的标准化接口。实际上,Servlets可能被视为远房亲戚。

Ruby世界中最着名的界面是Rack,但在Ruby中使用Rack之前,已经有Python中的WSGI(Web服务器网关接口),Perl中的PSGI等等。这种接口背后的主要思想是它们提供了一个简单,简单的界面,可以分离web框架和Web服务器。例如。任何符合Rack标准的框架(Rails,Sinatra,Padrino,古巴,Lotus,Ramaze,NYNY,Nancy,Crepe,Hobbit,Grape,Roy,......)都可以与任何符合Rack标准的网络服务器(Mongrel,Thin,Unicorn,Puma,......)配合使用。例如,在有Rack之前,Rails在Lighttpd,SCGI,FastCGI,CGI和Webrick下运行的代码不同。现在,只有Rack。

对于不符合Rack标准的网络服务器(例如因为它们是在Rack之前创建的,或者因为它们与语言无关),有很多方法可以使用上述任何技术在其上实现Rack,例如: Apache和Nginx有一个mod_rack

Phusion Passenger

Phusion Passenger是一个特例。它是一个Rack(和Python WSGI)服务器,作为Apache和Nginx的扩展模块实现。

原生网络服务器

您也可以在语言中运行网络服务器,而不是在网络服务器中运行语言。 Webrick是一个用Ruby编写的可以运行Rails的Web服务器。

答案 2 :(得分:1)

与所有事情一样,有几种方法可以做到这一点。 Phusion Passenger提供了ApacheNGINX个模块,这些模块与mod_php和mod_perl。它也可以standalone模式使用,它包括自己的Web服务器(即不需要Apache或NGINX)。可以在三种模式之间进行良好比较here

分层Web架构将Passenger置于独立模式,并从reverse proxy后面提供服务,可以是NGINX或Apache之类的其他中间件,如HAProxy或Varnish。您可能熟悉此模型,因为它类似于Jetty,Tomcat等将Java应用程序提供给公共Internet(即从反向代理后面)。高级体系结构可以包括多个反向代理和应用服务器,每个代理服务器解决多层Web体系结构难题的不同部分(例如SSL终止,负载平衡,缓存,压缩,静态资产服务,动态内容)。

我实际上更喜欢Puma,这类似于Passenger独立版。在许多基准测试中,它更容易理解和(我上次检查)更快,更高效,更节省内存。它为您提供了混合分叉+线程模式的选项(再次,我上次检查)仅在Passenger Enterprise中可用。 Puma是Rails和Heroku以及其他托管平台上的默认Web服务器。