1

我对分叉后每个孩子的构造函数有疑问。例如:

warn "INIT : Parent : ".$$;
my $stash;
sub {
    unless($stash) {
        warn "init : Child : ".$$;
        $stash = {
            dbh => {}
        };
    }
    return [ 200, ['Content-Type' => 'text/plain'], ['Hello World'] ];
}

此代码有效,但这是不好的做法。我想创造类似的东西

package Myapp;
sub new {
    my $class=shift;
    my $self=bless {
        dbh =>{},
    }, $class;

}
sub call {
    my ($self, $env) = @_;
    # body
    return [ 200, ['Content-Type' => 'text/plain'], ['Hello World'] ];    }

我希望有人向我解释它如何通过像 Starman 或 Feersum 这样的 prefork-server 工作(但是一个人“Audrey Tang”告诉我 Feersum 这不是一个好主意)

所以 - 谢谢你的回答

4

1 回答 1

1

您的 .psgi 可以像这样简单:

my $obj = Myapp->new;

my $app = sub {
    my $env = shift;

    return $obj->call($env);
};

如果使用starman,Myapp将在每次 Starman 分叉时实例化,并且您的实例的call方法将在每个请求上被调用。这是因为默认情况下,您的 .psgi 文件由子进程加载。

如果使用starman --preload-app,Myapp将仅实例化一次(在父级中),并且所有子级将共享同一个实例。这样做可能会节省内存,但您的应用程序需要注意不要通过使用共享连接来干扰其他兄弟姐妹。有关更多信息,请参阅https://metacpan.org/pod/distribution/Starman/script/starman#preload-app

这是您的 .psgi 的另一个想法:

my %objects;

my $app = sub {
    my $env = shift;
    my $obj;

    if ($objects{$$}) {
        $obj = $objects{$$};
    }
    else {
        $obj = Myapp->new;
        %objects = ($$ => $obj);
    }

    return $obj->call($env);
};

使用这种方法,Myapp在收到请求之前不会实例化,但每个子进程只实例化一次。无论是否--preload-app使用,此行为都是一致的。

于 2016-08-11T16:54:23.783 回答