首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多站点感知PSGI应用程序开发

多站点感知PSGI应用程序开发
EN

Stack Overflow用户
提问于 2016-03-26 01:21:41
回答 2查看 496关注 0票数 9

Plack::建筑工人允许挂载多个主机,例如,如下代码段所示:

代码语言:javascript
复制
my @sites = load_site_names();
my $apps;
for my $site (@sites) {
    $apps->{$site} = Some::PsgiFramework::MyApp->new( config => get_config($site) );
}

use Plack::Builder;
builder {
    for my $site (@sites) {
        mount "$site" => $apps->{$site};
    }
    mount '/' => sub { ... };
}

例如:

  • load_site_names返回一个站点列表,如http://example.comhttp://some.other.site.com,.
  • 每个“虚拟主机”都将使用相同的Some::PsgiFramework::MyApp
  • 只是它们的配置不一样

我需要上面的需求,开发一个简单的web应用程序,应该部署到不同的(低流量)网站,而不想设置一个不同的PSGI服务器为每个网站。

然而,Plack本身的作者说(在Plack::请求中)

请注意,这个模块是用于Plack中间件开发人员和web应用程序框架开发人员,而不是应用程序开发人员(最终用户)。 直接使用Plack::Request编写web应用程序当然是可能的,但不建议这样做:这就像使用mod_perl的Apache::Request:但级别太低一样。 如果您正在编写web应用程序,而不是框架,则鼓励您使用支持PSGI (http://plackperl.org/#frameworks)的web应用程序框架之一,或者查看像HTTP::Engine这样的模块,以便在PSGI基础上提供更高级别的请求和响应API。

这就是问题所在。

我在MetaCPAN中检查了许多不同的基于PSGI的框架。AFAIK每个都是基于单例的,例如不允许为同一app.psgi中的不同站点共享(挂载)多次的写应用程序。

所以问题是:

  • 在MetaCPAN (或文档中)中遗漏了一些东西,在这里,存在 any (轻量级)web框架,它允许在app.psgi中多次安装开发应用程序。
  • 还是我被迫开发Just Another My Own PSGI Framework?(老实说,我没有检查催化剂,因为它太重了)
  • 还是只是对“安装”理解得很差?
EN

回答 2

Stack Overflow用户

发布于 2017-02-10 01:23:59

在Plack中构建调度员

除了Plack::App::URLMap (名为Plack::App:HostMap ),还有一种替代方法,它可以更快地进行查找,因为它在内部使用哈希,而不是数组。所以没有迭代在进行。它只是进行哈希查找,在Perl中这些查找非常快。

交换条件是,现在您只能使用常量主机名。所以如果你的清单是这样的:

代码语言:javascript
复制
example.org
example.com
example.de
example.am
example.cx

或者具有以下的子域:

代码语言:javascript
复制
one.example.org
two.example.org
three.example.org
four.example.org
five.example.org
six.example.org

那就太完美了。另一方面,我不确定它是否支持具有常量路径部分的URL,比如http://foo.example.org/bar,其中有很多foo,但它们都共享安装应用程序的相同的/bar路径。这个模块根本没有任何测试,我也无法尝试。如果您查看这些更改,至少有一个人提出了其他特性,因此,除了作者之外,其他人也在使用它。

要使用它,您可以从Plack::Builder切换到使用Plack:: app ::HostMap作为调用方法的应用程序。

代码语言:javascript
复制
use Plack::App::HostMap;

# set up %apps (e.g. foo.example.org, bar.example.org)

my $host_map = Plack::App::HostMap->new;

for my $site (@sites) {
    $host_map->map( $site => $apps->{$site} );
}

您没有告诉我们/路由应该做什么,但本质上它也需要一个主机。如果您的服务器有很多主机名,那么所有主机名都会响应此请求。这就是你想要做的事情的全部想法。但是/的主机名是什么呢?因此,最好的做法是为sub { ... }斜杠-应用程序添加一行真正的主机名。也许那是控制面板什么的。因此,将其连接到实际的URL。

代码语言:javascript
复制
 $host_map->map( "example.org" => sub { ... } );

用一个web框架来完成这个任务

单身人士并不是真正的问题。似乎不可能让Dancer2用相同的信任或环境加载不同的信任或环境。我还没有尝试过这个用例的Mojo,Web::Simple或催化剂。

我在D2上做了很多尝试,我得到的最接近的是在MyApp中有一个/路径,以及这个PSGI应用程序。注意,这个不工作

代码语言:javascript
复制
use Plack::Builder;

my $builder = Plack::Builder->new;
foreach my $name (qw/development production/) {
    $builder->mount(
        "/$name" => builder {
            eval <<"APP";
package MyApp::$name {
    use Dancer2;
    use MyApp with => { environment => "$name" };
}
APP

            "MyApp::$name"->to_app;
        }
    );
}

$builder->to_app;

它使用使用dancer2 -a MyApp和未更改的环境文件生成的默认框架。Plack的调度工作正常,但是Dancer2会感到困惑。

代码语言:javascript
复制
HTTP::Server::PSGI: Accepting connections at http://0:5000/
[MyApp::production:4896] core @2017-02-10 02:14:42> looking for get / in /home/julien/perl5/perlbrew/perls/perl-5.20.1/lib/site_perl/5.20.1/Dancer2/Core/App.pm l. 35
[MyApp::production:4896] core @2017-02-10 02:14:42> Entering hook core.error.init in (eval 49) l. 1
[MyApp::production:4896] core @2017-02-10 02:14:42> Entering hook core.error.before in (eval 49) l. 1
[MyApp::production:4896] core @2017-02-10 02:14:42> Entering hook core.error.after in (eval 49) l. 1
127.0.0.1 - - [10/Feb/2017:02:14:42 +0100] "GET /production/ HTTP/1.1" 404 456 "-" "curl/7.47.0"
[MyApp::development:4896] core @2017-02-10 02:18:06> looking for get  in /home/julien/perl5/perlbrew/perls/perl-5.20.1/lib/site_perl/5.20.1/Dancer2/Core/App.pm l. 35
[MyApp::development:4896] core @2017-02-10 02:18:06> Entering hook core.error.init in (eval 49) l. 1
[MyApp::development:4896] core @2017-02-10 02:18:06> Entering hook core.error.before in (eval 49) l. 1
[MyApp::development:4896] core @2017-02-10 02:18:06> Entering hook core.error.after in (eval 49) l. 1
127.0.0.1 - - [10/Feb/2017:02:18:06 +0100] "GET /development HTTP/1.1" 404 457 "-" "curl/7.47.0"

这样做的目的是使用相同的包文件并将其子类化,以便通过with获得不同的配置。

然而,我们可以一次又一次地在循环中定义相同的应用程序。您可能可以使用像get '/' => \&main::get_slash这样的代码引用将路由处理程序移出,其中sub get_slash不在eval中。

代码语言:javascript
复制
use Plack::Builder;

my $builder = Plack::Builder->new;
foreach my $name (qw/development production/) {
    $builder->mount(
        "/$name" => builder {
            eval <<"APP";
package MyApp::$name {
use Dancer2;
    use Data::Printer;

    set environment => "$name";

    get "/" => sub { np(config) }
}
APP

            "MyApp::$name"->to_app;
        }
    );
}

$builder->to_app;

字符串eval并不像在这里看起来的那样邪恶,因为该代码只在启动时运行。D2将在内部跟踪您在这里以编程方式创建的所有应用程序。但我不知道这有多好。

票数 1
EN

Stack Overflow用户

发布于 2017-02-17 13:11:40

我相信引用的文档更适合Plack::Request,而不是Plack::Builder。

使用Plack::Builder挂载各种应用程序(例如,Dancer/催化剂/ mount /国产应用程序)是完全可以接受的,而且这是非常常见的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36230563

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档