2016-06-30 11 views
1

У меня есть вопрос о конструкторе для каждого ребенка после форкирования. Например:PSGI - конструктор для каждого дочернего ребенка

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'] ]; } 

я надеюсь, что кого-нибудь объяснить мне, как это может работать на PreFork-сервере, как Starman или Feersum (Но один парень «Одри Тан» скажи мне, что Feersum это не хорошая идея для этого)

так что - спасибо за твои ответы

+0

Ваша цель не совсем ясна. Вы хотите, чтобы ваше приложение было объектом? –

+0

объект - это просто правильный тип кодирования. Но моя цель - найти место, где функция init вызывается один раз и после разветвления –

ответ

1

Ваш .psgi может быть столь же просто, как это:

my $obj = Myapp->new; 

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

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

Если вы запускаете с starman, то при каждом вызове Starman будут создаваться экземпляры Myapp, и ваш метод вызова 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.