Как узнать, на каком сервере запущен процесс app.psgi?

Есть ли способ узнать на каком сервере app.psgi бежит?

Например, я ищу идею, как решить следующий фрагмент кода из app.psgi:

#app.psgi
use Modern::Perl;
use Plack::Builder;
my $app = sub { ... };

my $server = MyApp::GetServerType(); # <--- I need some idea for how to write this...

given($server) {
    when (/plackup/) { ... do something ... };
    when (/Starman/) { ... do something other ... };
    default { die "Unknown" };
}

$app;

Проверка PLACK_ENV Переменная окружения не является решением...

1 ответ

Решение

Короткий ответ, осмотрите звонящего:

#app.psgi
# use Modern::Perl;
use feature qw(switch say);
use Carp qw(longmess);
use Plack::Builder;

my $app = sub {
    return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello World' ] ];
};

# This hack gets what we need out of the call stack
my $stack = longmess("Stack:");

# say STDERR $stack;

given($stack) {
    when (/plackup/) { say STDERR "Server: plackup" };
    when (/Starman/) { say STDERR "Server: starman" };
    default { die "Server: Unknown" };
}
return $app;

Однако выполнение этого в app.psgi сделает ваш код менее переносимым. Если вы умрете на неизвестном сервере, люди не смогут запустить ваш код в неизвестном месте.

Также имейте в виду, что этот код может выполняться несколько раз в зависимости от того, как реализован сервер, поэтому любые побочные эффекты могут возникать несколько раз.

Например, вот вывод для plackup:

plackup --app /usr/lusers/bburnett/dev/trunk/getserver.psgi
Server: plackup
HTTP::Server::PSGI: Accepting connections at http://0:5000/

Все идет нормально. Но вот выход для starman:

starman --app /usr/lusers/bburnett/dev/trunk/getserver.psgi
2014/02/21-16:09:46 Starman::Server (type Net::Server::PreFork) starting! pid(27365)
Resolved [*]:5000 to [0.0.0.0]:5000, IPv4
Binding to TCP port 5000 on host 0.0.0.0 with IPv4
Setting gid to "15 15 0 0 15 20920 20921 20927"
Server: starman
Server: starman
Server: starman
Server: starman
Server: starman

Здесь он запускается один раз для мастера и один раз для каждого ребенка (по умолчанию четыре ребенка).

Если вы действительно хотите, чтобы на этих разных серверах происходило что-то другое, более надежным способом может быть создание их подкласса самостоятельно и размещение кода в каждой передаче подкласса. -s My::Starman::Wrapper чтобы заложить и звездный по мере необходимости.

Если вы действительно хотите использовать оператор switch и поместить код в одном месте, вы можете написать код, который вызывает Plack:: Loader или Plack:: Runner. Посмотрите на источник для plackup, и вы увидите, как он оборачивает Plack:: Runner. Взгляните на исходный код Plack:: Loader, и вы увидите, как он запускает серверную часть, а затем загружает соответствующий класс сервера.

Другие вопросы по тегам