2010-09-01 103 views
3

我有一个需要由乘客模块nginx部署的rails应用程序。这个应用程序需要为上百个域名提供服务。我没有足够的内存来启动100个导轨实例。我不确定在少数情况下启动rails的正确方法。这是不同域名下的相同应用程序。多个域名的一个rails应用程序

server { 
    listen 80; 
    server_name www.a_domain.com; 
    root /webapps/mycook/public; 
    passenger_enabled on; 
} 
server { 
    listen 80; 
    server_name www.b_domain.com; 
    root /webapps/mycook/public; 
    passenger_enabled on; 
} 
server { 
    listen 80; 
    server_name www.c_domain.com; 
    root /webapps/mycook/public; 
    passenger_enabled on; 
} 

正如你可以上面的代码,它会启动三个rails实例。如果只启动实例在这3个域下进行服务将会很好。任何人都有一些建议?

回答

7

只需为该服务器条目设置多个域别名即可。

server { 
    listen 80; 
    server_name www.a_domain.com www.b_domain.com www.c_domain.com; 
    root /webapps/mycook/public; 
    passenger_enabled on; 
} 

这将为这些域中的每个域提供请求,并且所有域都会访问同一个应用程序池。

+1

+1设置多个别名并让你的Rails应用程序检测应执行哪一个检查主机变量。 – 2010-09-01 19:18:28

+0

感谢您的评论。 – Chamnap 2010-09-02 10:49:52

+0

我们完全按照克里斯描述的方式完成了Simone的建议,并且它工作正常。 – pjmorse 2010-10-18 11:55:10

0

我在Chris的回答中提到您可以在server_name中使用通配符和正则表达式,并且这些将会传递给您的rails实例。

server_name *; # handle requests from all domains 

有四种方法可以在你的Rails应用程序中使用它(我知道这一点)。

“内容的大包”方法

什么都不做

如果你让Nginx的把所有的域相同的Rails应用程序,他们都得到了相同的内容。在这种情况下,www.abc.com和www.xyz.com可以访问相同的数据。这是最容易做到的,因为你什么都不做。

此解决方案的局限性在于您希望让域具有不同的内容。例如,如果www.abc.com/about和www.xyz.com/about应该是不同的页面,那么它就会变得棘手。

的“幕后的那个人”方法

使用的Nginx的“改写”

在某些情况下,你可以让Nginx的重写域名成子域,并传递到您的Rails应用程序。例如:

server_name *; # handle requests from all domains 
rewrite ^(?:www.)?([^.]*)\..*$ $1.yourdomain.com last; 

该正则表达式需要一点解释。它只是说从任何这些获得xyz:www.xyz.com,xyz.com,xzy.co.uk,www.xyz.co.uk.重写将这些请求中的任何一个更改为xyz.yourdomain.com。

这样做的好处是Nginx很快就做到了这一点,rails应用程序直到以后才会涉及,并且请求的内容可以限制在子域。例如,Page.where(subdomain: request.subdomain, permalink: params[:permalink])

虽然这是相当严格的,因为它意味着子域名和域名必须相同。也许这对你的应用程序来说是一个问题,可能不是。但是,尽管我在此子域中使用了$1,但您可以轻松地将其作为url中的参数插入。例如,yourdomain.com/$1会将来自www.xyz.com的请求重写到yourdomain.com/xyz。

此问题的另一个问题是“幕后男子”。虽然用户访问www.xyz.com重写意味着他们会在地址栏中看到xyz.yourdomain.com。

的“Rails的路”法

在ApplicationController中

使用Rails的请求对象,你可以使用你的应用程序控制器范围使用Rails的request对象域名相关的内容。

在本例中,我们将使用ApplicationController来查找与域名关联的用户帐户。假设你有一个用户模型与domain_name属性:

def domain_user 
    @domain_user ||= User.where(domain_name: request.domain()).take 
end 

Redis的可用于如果附加命中你的数据库中创建一个性能障碍缓存这些查找。到目前为止,我的应用还没有达到这一点。

这个解决方案的弱点是,虽然查找可能会发现www.xyz.com,它会错过xyz.com。为了适应这种情况,我们可以使用一些正则表达式:

def domain_user 
    request.domain.match /(?:www.)?(.*)/ 
    @domain_user ||= User.where(domain_name: $1).take 
end 

这个正则表达式去掉www。如果它存在。剩下的就成了域名(我们在$1里为我们存储红宝石)。

与Nginx重写解决方案不同,如果用户访问www.xyz.com,那么他们在地址栏中仍然可以看到。

使用路由约束

的“对我不起作用”法

另外,Rails的3及以上的有约束的,存在于产生路由表半动态的路由文件的功能。我说“半动态”,因为路由表是在应用程序启动时生成的。如果用户模型(在我们的示例中)发生变化,则需要特别注意重建路由表。对于分布在多个服务器上的应用程序,这可能难以管理,尽管people have done it

到目前为止,我的所有应用程序最终(如果不是最初的话)都使用ApplicationController解决方案,因为它实际上是最干净和最容易实现的。从MCV的角度来看,这也很有意义。

相关问题