Книга: Программирование на языке Ruby

19.2. FastCGI

19.2. FastCGI

Чаще всего CGI критикуют за то, что при каждом запросе создается новый процесс, и это заметно снижает производительность. Невозможность сохранять в памяти объекты между последовательными запросами также не украшает дизайн системы. Для разрешения этих проблем была создана технология FastCGI.

По сути дела, FastCGI — это определение и программная реализация протокола. Обычно она реализуется в надстройки над Web-сервером, например модуля в случае сервера Apache. FastCGI позволяет работающему внутри процесса компоненту перехватывать HTTP-запросы и направлять их через сокет другому процессу, работающему в течение длительного времени. По сравнению с традиционным порождением новых процессов это существенно ускоряет работу. Кроме того, программист получает возможность оставить данные в памяти и найти их там при обработке следующего запроса.

Серверы, адаптированные для работы с FastCGI, реализованы на многих языках, в том числе на Ruby. Эли Грин (Eli Green) написал целиком на Ruby модуль (он есть в архиве RAA), который реализует протокол FastCGI и упрощает разработку FastCGI-программ.

Не вдаваясь в детали реализации, мы представили в листинге 19.1 пример приложения. Как видите, он повторяет функциональность предыдущего примера.

Листинг 19.1. Пример FastCGI

require "fastcgi"
require "cgi"
last_time = ""
def get_ramblings(instream)
 # He слишком красивый способ извлечь значение из первой пары
 # имя-значение. CGI сделал бы это за нас.
 data = ""
 if instream != nil
  data = instream.split("&")[0].split(" = ")[1] || ""
 end
 return CGI.unescape(data)
end
def reverse_ramblings(ramblings)
 if ramblings == nil then return "" end
 chunks = ramblings.split(/s+/)
 chunks.reverse.join(" ")
end
server = FastCGI::TCP.new('localhost', 9000)
begin
 server.each_request do |request|
  stuff = request.in.read
  out = request.out
  out << "Content-type: text/htmlrnrn"
  out << <<-EOF
<html>
<head><titlе>Отражатель текста</title></head>
<h1>sdrawkcaB txeT</h1>
<i>Вы перед этим сказали: #{last_time}</i><BR>
<b>#{reverse_ramblings(get_ramblings(stuff))}</b>
<form method="POST" action="/fast/serv.rb">
<textarea name="ramblings">
</textarea>
<input type="submit" name="submit">
</form>
</body></html>
EOF
  last_time = get_ramblings(stuff)
  request.finish
 end
ensure
 server.close
end

Сразу же бросается в глаза (если вы читали предыдущий раздел) то, что в FastCGI приходится вручную делать кое-какие вещи, которые были не нужны при работе с библиотекой CGI. Во-первых, «зашивание» в код экранированного HTML-кода. Во-вторых, метод get_ramblings, который сам разбирает входные данные и возвращает нужное значение. Кстати, этот код будет работать только для POST-запросов — еще одно удобство, утраченное с отказом от библиотеки CGI.

Но вместе с тем у FastCGI есть и достоинства. Мы не проводили замеров, но — как следует из самого названия — FastCGI быстрее CGI. Вместо накладных расходов на создание нового процесса мы просто открываем соединение с портом 9000 на локальной машине (FastCGI::TCP.new('localhost', 9000)). Кроме того, в переменной last_time хранится часть состояния сеанса — вещь, невозможная в традиционной технологии CGI.

Отметим также, что эти библиотеки можно до определенного предела «смешивать». Вспомогательные функции из cgi.rb, например метод CGI.escapeHTML, можно использовать автономно (не делая библиотеку основой приложения). Тогда предыдущий пример оказался бы несколько проще для восприятия.

Оглавление книги


Генерация: 1.990. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз