POD2-RU-PSGI
view release on metacpan or search on metacpan
lib/POD2/RU/PSGI/FAQ.pod view on Meta::CPAN
обÑекÑÑ Ð² IO::Handle-подобнÑе.
=head3 Ðак ÑеÑвеÑÑ ÑледÑÐµÑ Ð¾Ð¿ÑеделÑÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑÑ Ð¿ÐµÑеклÑÑиÑÑÑÑ Ð½Ð° иÑполÑзование
sendfile(2)?
ÐÐ»Ñ Ð½Ð°Ñала, пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¡ÐÐÐУÐТ вÑегда ÑоздаваÑÑ IO::Handle-подобнÑй обÑекÑ
(или маÑÑив ÑаÑÑей), коÑоÑÑй оÑвеÑÐ°ÐµÑ Ð½Ð° C<getline> и C<close> как Ñело оÑвеÑа.
ÐÑо гаÑанÑиÑованно ÑабоÑÐ°ÐµÑ Ñ Ð»ÑбÑми ÑеÑвеÑами.
ÐпÑионалÑно, еÑли ÑеÑÐ²ÐµÑ Ð½Ð°Ð¿Ð¸Ñан на Perl или Ð¼Ð¾Ð¶ÐµÑ Ð¿ÐµÑедаÑÑ Ð½Ð¾Ð¼ÐµÑ Ñайлового
деÑкÑипÑоÑа на C-ÑÑоÑÐ¾Ð½Ñ Ð¿ÑогÑаммÑ, ÑÑÐ¾Ð±Ñ Ð¾Ð±ÑлÑжиÑÑ Ð·Ð°Ð¿ÑÐ¾Ñ Ð½Ð° ÑÑÐ¾Ñ Ñайл, Ñо
ÑеÑÐ²ÐµÑ ÐÐÐÐТ пÑовеÑиÑÑ, ÑвлÑеÑÑÑ Ð»Ð¸ Ñело ÑеалÑнÑм ÑайловÑм деÑкÑипÑоÑом
(возможно, иÑполÑзÑÑ ÑÑнкÑÐ¸Ñ C<is_real_fh> из L<Plack::Util>), заÑем полÑÑиÑÑ
ÑайловÑй деÑкÑипÑÐ¾Ñ Ð¿Ñи помоÑи C<fileno> и вÑзваÑÑ sendfile(2) или
ÑквиваленÑнÑÑ ÑÑнкÑÐ¸Ñ Ð¿ÐµÑедаÑи даннÑÑ
без заÑÑÐ°Ñ Ð½Ð° копиÑование, иÑполÑзÑÑÑÑÑ
его.
РпÑоÑивном ÑлÑÑае, еÑли ÑеÑÐ²ÐµÑ Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ Ð¾ÑпÑавиÑÑ Ñайл иÑполÑзÑÑ ÑайловÑй
деÑкÑипÑоÑ, но нÑждаеÑÑÑ Ð² локалÑном пÑÑи к ÑÐ°Ð¹Ð»Ñ (как mod_perl или nginx),
пÑиложение Ð¼Ð¾Ð¶ÐµÑ Ð²ÐµÑнÑÑÑ IO::Handle-подобнÑй обÑекÑ, коÑоÑÑй Ñакже оÑвеÑÐ°ÐµÑ Ð½Ð°
меÑод C<path>. ÐÑÐ¾Ñ Ñип IO-подобнÑÑ
обÑекÑов Ð¼Ð¾Ð¶ÐµÑ Ð»ÐµÐ³ÐºÐ¾ бÑÑÑ Ñоздан пÑи
иÑполÑзовании L<IO::File::WithPath>, L<IO::Handle::Util> или ÑÑнкÑии
C<set_io_path> из модÑÐ»Ñ L<Plack::Util>.
Middleware Ñакже Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑовеÑÑÑÑ, еÑÑÑ Ð»Ð¸ Ñ body меÑод C<path>, и делаÑÑ Ñ Ð½Ð¸Ð¼
ÑÑо-нибÑÐ´Ñ Ð¸Ð½ÑеÑеÑное - вÑоде ÑÑÑановки заголовка C<X-Senfile>.
ÐÐ¾Ð´Ð²Ð¾Ð´Ñ Ð¸Ñог:
=over 4
=item *
ÐÑи оÑдаÑе ÑÑаÑиÑеÑкиÑ
Ñайлов пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ ÑледÑÐµÑ Ð²Ñегда возвÑаÑаÑÑ ÑеалÑнÑй
деÑкÑипÑÐ¾Ñ Ð¸Ð»Ð¸ обÑÐµÐºÑ IO::Handle. ÐÑо должно ÑабоÑаÑÑ Ð²ÐµÐ·Ð´Ðµ, и Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ
опÑимизиÑовано в некоÑоÑÑÑ
ÑÑедаÑ
.
=item *
ÐÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³ÑÑ Ñакже ÑоздаваÑÑ IO::Handle-подобнÑй обÑÐµÐºÑ Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑнÑм
меÑодом C<path>, поÑле Ñего ÑÑо Ñакже должно ÑабоÑаÑÑ Ð²ÐµÐ·Ð´Ðµ, и Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ
опÑимизиÑовано даже в болÑÑем колиÑеÑÑве ÑазлиÑнÑÑ
ÑÑед.
=back
=head3 ЧÑо еÑли Ñ Ñ
оÑÑ ÑÑÑимиÑÑ ÐºÐ¾Ð½ÑÐµÐ½Ñ Ð¸Ð»Ð¸ иÑполÑзоваÑÑ long-polling Comet ÑеÑ
нологиÑ?
СамÑй пÑоÑÑой ÑпоÑоб Ð´Ð»Ñ ÑеализаÑии ÑеÑ
нологии push Ñо ÑÑоÑÐ¾Ð½Ñ ÑеÑвеÑа ÑÑо
веÑнÑÑÑ Ð¸Ð· пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ IO::Handle-подобнÑй обÑÐµÐºÑ ÐºÐ°Ðº body, коÑоÑÑй
ÑеализÑÐµÑ Ð¼ÐµÑод C<getline> возвÑаÑаÑÑий push даннÑе. ÐÑо гаÑанÑиÑованно везде
ÑабоÑаеÑ, но ÑÑо болÑÑе pull, Ñем push, и Ñложно делаÑÑ Ð½ÐµÐ±Ð»Ð¾ÐºÐ¸ÑÑемÑй
ввод/вÑдаÑÑ, еÑли ÑолÑко не иÑполÑзÑеÑÑÑ Coro.
ÐÑли Ð²Ñ Ñ
оÑиÑе делаÑÑ push Ñо ÑÑоÑÐ¾Ð½Ñ ÑеÑвеÑа, где пÑиложение ÑабоÑÐ°ÐµÑ Ð² Ñикле
обÑабоÑки ÑобÑÑий (event loop) и пÑи гоÑовноÑÑи вÑÐ´Ð°ÐµÑ Ð´Ð°Ð½Ð½Ñе клиенÑÑ, ÑледÑеÑ
веÑнÑÑÑ callback Ð´Ð»Ñ Ð¾Ñложенного оÑвеÑа.
# long-poll comet подобное ÑаÑ-пÑиложение
my $app = sub {
my $env = shift;
unless ($env->{'psgi.streaming'}) {
die "ÐÑо пÑиложение ÑÑебÑÐµÑ Ð¿Ð¾Ð´Ð´ÐµÑжки psgi.streaming";
}
return sub {
my $respond = shift;
wait_for_new_message(sub {
my $message = shift;
my $body = [ $message->to_json ];
$respond->([200, ['Content-Type', 'application/json'], $body]);
});
};
};
C<wait_for_new_message> Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð±Ð»Ð¾ÐºÐ¸ÑÑÑÑим и неблокиÑÑÑÑим: вÑÐ±Ð¾Ñ Ð·Ð°
ÑазÑабоÑÑиком. РболÑÑинÑÑве ÑлÑÑаев ÑÑебÑеÑÑÑ Ð½ÐµÐ±Ð»Ð¾ÐºÐ¸ÑÑÑÑий Ñежим, Ñогда
ÑледÑÐµÑ Ð¸ÑполÑзоваÑÑ Ñикл обÑабоÑки ÑобÑÑий (event loop), как L<AnyEvent>. Также
можно пÑовеÑиÑÑ Ð·Ð½Ð°Ñение C<psgi.nonblocking>, и, еÑли ÑÑо не поддеÑживаеÑÑÑ,
иÑполÑзоваÑÑ Ð±Ð»Ð¾ÐºÐ¸ÑÑÑÑий вÑзов.
ÐÐ»Ñ Ñого, ÑÑÐ¾Ð±Ñ ÑÑÑимиÑÑ ÐºÐ¾Ð½ÑÐµÐ½Ñ (Ð´Ð»Ñ ÑÑÑиминга ÑообÑений ÑеÑез Flash ÑÐ¾ÐºÐµÑ Ð¸Ð»Ð¸
multipart XMLHTTPRequest):
my $app = sub {
my $env = shift;
unless ($env->{'psgi.streaming'}) {
die "ÐÑо пÑиложение ÑÑебÑÐµÑ Ð¿Ð¾Ð´Ð´ÐµÑжки psgi.streaming";
}
return sub {
my $respond = shift;
my $writer = $respond->([200, ['Content-Type', 'text/plain']]);
wait_for_new_message(sub {
my $message = shift;
if ($message) {
$writer->write($message->to_json);
} else {
$writer->close;
}
});
};
};
=head3 Ðакой же ÑÑеймвоÑк иÑполÑзоваÑÑ Ð´Ð»Ñ ÑÑÑиминга?
ÐÑÑÑ ÑеÑвеÑÑ, коÑоÑÑй поддеÑживаÑÑ Ð½ÐµÐ±Ð»Ð¾ÐºÐ¸ÑÑÑÑий Ñежим (где C<psgi.nonblocking>
Ð¸Ð¼ÐµÐµÑ true знаÑение), но пÑоблема в Ñом, ÑÑо ÑеÑвеÑнÑй ÑÑеймвоÑк ÑовÑем не
обÑзаÑелÑно поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð°ÑинÑ
ÑоннÑй Ñикл обÑабоÑки ÑобÑÑий. ÐапÑимеÑ, в
Catalyst еÑÑÑ Ð¼ÐµÑод C<write> Ñ Ð¾Ð±ÑекÑа оÑвеÑа:
while ($cond) {
$c->res->write($some_stuff);
}
ÐÑо должно ÑÑабоÑаÑÑ Ñ ÑеÑвеÑами поддеÑживаÑÑими C<psgi.streaming> даже еÑли они
блокиÑÑÑÑие, и еÑли они ÑабоÑаÑÑ Ð² Ñежиме неÑколÑкиÑ
пÑоÑеÑÑов
(C<psgi.multiprocess> в знаÑении true).
L<Catalyst::Engine::PSGI> Ñакже поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ ÑÑÑÐ°Ð½Ð¾Ð²ÐºÑ IO::Handle-подобного
обÑекÑа, коÑоÑÑй Ð¸Ð¼ÐµÐµÑ C<getline> меÑод, пÑÐ¸Ð¼ÐµÑ Ñ L<IO::Handle::Util>
my $io = io_from_getline sub {
return $data; # or undef when done()
};
$c->res->body($io);
Ð ÑÑо ÑабоÑÐ°ÐµÑ Ð²Ð¿Ð¾Ð»Ð½Ðµ ноÑмалÑно Ð´Ð»Ñ ÑÑÑиминга, но ÑÑо ÑкоÑее блокиÑÑÑÐ°Ñ Ð¾Ð¿ÐµÑаÑиÑ
(I<pull>), а не аÑинÑ
ÑоннÑй push Ñо ÑÑоÑÐ¾Ð½Ñ ÑеÑвеÑÑ, поÑÑомÑ, опÑÑÑ Ð¶Ðµ, ÑÑоиÑ
бÑÑÑ Ð¾ÑÑоÑожнÑм пÑи запÑÑке пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð² неблокиÑÑÑÑем (и не многопÑоÑеÑÑоÑном)
ÑеÑвеÑном окÑÑжении.
ÐжидаеÑÑÑ, ÑÑо бÑдÑÑ Ð¿Ð¾ÑвлÑÑÑÑÑ Ð½Ð¾Ð²Ñе ÑÑеймвоÑки или доÑабаÑÑваÑÑÑÑ
ÑÑÑеÑÑвÑÑÑие, коÑоÑÑе поддеÑживаÑÑ Ð°ÑинÑ
ÑоннÑй и неблокиÑÑÑÑий ÑÑÑиминг
инÑеÑÑейÑ.
=head3 ЯвлÑеÑÑÑ Ð»Ð¸ инÑеÑÑÐµÐ¹Ñ psgi.streaming необÑ
одимÑм Ð´Ð»Ñ ÑеÑвеÑов?
Ðн Ñказан в ÑпеÑиÑикаÑии как B<SHOULD>, поÑÑомÑ, еÑли Ð½ÐµÑ ÑеÑÑÑзной пÑиÑинÑ
оÑказаÑÑÑÑ Ð¾Ñ ÑеализаÑии инÑеÑÑейÑа, вÑем ÑеÑвеÑам ÑекомендÑеÑÑÑ ÑеализовÑваÑÑ
ÑÑÐ¾Ñ Ð¸Ð½ÑеÑÑейÑ.
Тем не менее, еÑли Ð²Ñ ÑеализовÑваеÑе PSGI ÑеÑвеÑ, иÑполÑзÑÑ Perl XS инÑеÑÑейÑ
Ð´Ð»Ñ Ð´Ð¾ÑÑÐ¸Ð¶ÐµÐ½Ð¸Ñ Ð¼Ð°ÐºÑималÑной пÑоизводиÑелÑноÑÑи или инÑегÑаÑии Ñ Ð²ÐµÐ±-ÑеÑвеÑами
вÑоде Apache или nginx, или ÑоздаÑÑе окÑÑжение Ñипа "пеÑоÑниÑÑ" (наподобие
Google AppEngine или Heroku), или ÑаÑпÑеделÑннÑÑ Ð¿Ð»Ð°ÑÑоÑмÑ, иÑполÑзÑÑ ÑÑилиÑÑ
вÑоде Gearman, Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе не заÑ
оÑеÑÑ ÑеализовÑваÑÑ ÑÑÐ¾Ñ Ð¸Ð½ÑеÑÑейÑ.
ÐÑо пÑекÑаÑно, и в ÑÑом ÑлÑÑае пÑиложениÑ, оÑнованнÑе на поÑоковом инÑеÑÑейÑе,
вÑÑ ÐµÑÑ Ð¼Ð¾Ð³ÑÑ Ð¸ÑполÑзоваÑÑ L<Plack::Middleware::BufferedStreaming> в каÑаÑÑве
запаÑного ваÑианÑа Ð´Ð»Ñ Ð±ÑÑеÑизованной запиÑи на неподдеÑживаемÑÑ
ÑеÑвеÑаÑ
.
=head3 ÐоÑÐµÐ¼Ñ Ð¿ÐµÑеменнÑе окÑÑÐ¶ÐµÐ½Ð¸Ñ Ð² ÑÑиле CGI вмеÑÑо Ñ
еÑа Ñ HTTP заголовками?
ÐолÑÑинÑÑво ÑÑÑеÑÑвÑÑÑиÑ
ÑÑеймвоÑков Ð´Ð»Ñ Ð²ÐµÐ±-пÑиложений Ñже ÑодеÑÐ¶Ð°Ñ ÐºÐ¾Ð´ или
обÑабоÑÑик Ð´Ð»Ñ Ð·Ð°Ð¿ÑÑка в CGI-окÑÑжении. ÐÑполÑзование CGI-подобнÑÑ
клÑÑей Ñ
еÑа
вмеÑÑо HTTP заголовков Ð´ÐµÐ»Ð°ÐµÑ ÑÑивиалÑной Ð´Ð»Ñ ÑазÑабоÑÑиков ÑÑеймвоÑков задаÑÑ
ÑеализаÑии адапÑеÑа Ð´Ð»Ñ Ð¿Ð¾Ð´Ð´ÐµÑжки PSGI. ÐапÑимеÑ, L<Catalyst::Engine::PSGI>
вÑего лиÑÑ Ð½Ð° неÑколÑко дÑжин ÑÑÑок оÑлиÑаеÑÑÑ Ð¾Ñ L<Catalyst::Engine::CGI> и
бÑл напиÑан менее Ñем за ÑаÑ.
=head3 ÐоÑÐµÐ¼Ñ PATH_INFO URI декодиÑован?
ÐÐ»Ñ ÑовмеÑÑимоÑÑи Ñо ÑпеÑиÑикаÑией CGI (RFC 3875) и болÑÑинÑÑвом ÑеализаÑий
веб-ÑеÑвеÑов (наподобие Apache и lighttpd).
Я понимаÑ, Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð½ÐµÑдобно, ÑÑо Ð²Ñ Ð½Ðµ можеÑе ÑазлиÑиÑÑ C<foo%2fbar> оÑ
C<foo/bar> в оконÑании пÑÑи, но ÑпеÑиÑикаÑÐ¸Ñ CGI ÑÑно говоÑиÑ, ÑÑо
C<PATH_INFO> ÑледÑÐµÑ Ð´ÐµÐºÐ¾Ð´Ð¸ÑоваÑÑ Ð¿Ð¾Ð¼Ð¾Ñи ÑеÑвеÑа, и ÑÑо веб-ÑеÑвеÑÑ Ð¼Ð¾Ð³ÑÑ
оÑклонÑÑÑ Ð·Ð°Ð¿ÑоÑÑ, ÑодеÑжаÑие C<%2f> (Ñак как Ñакие запÑоÑÑ Ð¼Ð¾Ð³ÑÑ Ð¿Ð¾ÑеÑÑÑÑ
инÑоÑмаÑÐ¸Ñ Ð² PATH_INFO). ÐÑÑавив ÑÑи заÑезеÑвиÑованнÑе ÑимволÑ
недекодиÑованнÑми (ÑаÑÑиÑное декодиÑование) можно ÑÑ
ÑдÑиÑÑ Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ðµ, Ñак как
поÑле ÑÑого Ð²Ñ Ð½Ðµ ÑможеÑе ÑказаÑÑ C<foo%2fbar> из C<foo%252fbar>, и возможна
дÑÑка в безопаÑноÑÑи пÑи двойном кодиÑовании или декодиÑовании.
ÐÐ»Ñ ÑазÑабоÑÑиков веб-ÑÑеймвоÑков, коÑоÑÑм нÑжен болÑÑий конÑÑÐ¾Ð»Ñ Ð½Ð°Ð´
акÑÑалÑнÑм необÑабоÑаннÑм URI (ÑакиÑ
как L<Catalyst>), Ð¼Ñ Ñделали
клÑÑ Ñ
еÑа окÑÑÐ¶ÐµÐ½Ð¸Ñ C<REQUEST_URI> ÐÐЯÐÐТÐÐЬÐЫÐ. СеÑвеÑам ÑледÑеÑ
ÑÑÑанавливаÑÑ Ð½ÐµÐ´ÐµÐºÐ¾Ð´Ð¸ÑованнÑй (неÑазобÑаннÑй) оÑигиналÑнÑй URI (ÑодеÑжаÑий
ÑÑÑÐ¾ÐºÑ Ð·Ð°Ð¿ÑоÑа) в знаÑение ÑÑого клÑÑа. ÐбÑаÑиÑе внимание, ÑÑо C<REQUEST_URI>
ÑовеÑÑенно необÑабоÑан, даже еÑли закодиÑованнÑе ÑÑÑноÑÑи URI-безопаÑнÑ.
ÐÐ»Ñ ÑÑавнениÑ, WSGI (PEP-333) опÑеделÑÐµÑ C<SCRIPT_NAME> и C<PATH_INFO> как
декодиÑованнÑе, и Rack оÑÑавлÑÐµÑ ÑÑо завиÑеÑÑ Ð¾Ñ ÑеализаÑии, в Ñо вÑÐµÐ¼Ñ ÐºÐ°Ðº
I<иÑпÑавление> болÑÑей ÑаÑÑи PATH_INFO оÑÑалоÑÑ Ð·Ð°ÐºÐ¾Ð´Ð¸ÑованнÑм в ÑеализаÑиÑÑ
Ruby веб-ÑеÑвеÑов.
L<http://www.python.org/dev/peps/pep-0333/#url-reconstruction>
L<http://groups.google.com/group/rack-devel/browse_thread/thread/ddf4622e69bea53f>
=head1 СÐ. ТÐÐÐÐ
WSGI FAQ ÑÑно оÑвеÑÐ°ÐµÑ Ð½Ð° множеÑÑво вопÑоÑов о Ñом, как бÑли пÑинÑÑÑ Ð½ÐµÐºÐ¾ÑоÑÑе
ÑеÑÐµÐ½Ð¸Ñ Ð² ÑÑÑÑойÑÑве API, некоÑоÑÑе из коÑоÑÑÑ
можно пÑÑмо пÑимениÑÑ Ðº PSGI.
L<http://www.python.org/dev/peps/pep-0333/#questions-and-answers>
( run in 1.707 second using v1.01-cache-2.11-cpan-39bf76dae61 )