CGI и FastCGI плюс Java
Вдохновленный множественными статьями о микросервисах, пришла в голову идея, реализовать свой микро веб-сервис, но не стандартным путем.
Что такое CGI и FastCGI ?
CGI (от англ. Common Gateway Interface — «общий интерфейс шлюза») — стандарт интерфейса, используемого для связи внешней программы с веб-сервером. Программу, которая работает по такому интерфейсу совместно с веб-сервером, принято называть шлюзом, хотя многие предпочитают названия «скрипт» (сценарий) или «CGI-программа».
Сам интерфейс разработан таким образом, чтобы можно было использовать любой язык программирования, который может работать со стандартными устройствами ввода-вывода. Такими возможностями обладают даже скрипты для встроенных командных интерпретаторов операционных систем, поэтому в простых случаях могут использоваться даже командные скрипты.
Например bash скрипт :
Все скрипты, как правило, помещают в каталог cgi (или cgi-bin) сервера, но это необязательно: скрипт может располагаться где угодно, но при этом большинство веб-серверов требуют специальной настройки. В веб-сервере Apache, например, такая настройка может производиться при помощи общего файла настроек httpd.conf или с помощью файла .htaccess в том каталоге, где содержится этот скрипт.
То есть, создав файл с раширением .cgi (например hello.cgi), наполнив его строками приведенными выше и поместив его в каталог cgi(или cgi-bin) и запустив веб-сервер потдерживаюший cgi с правильно-выставленными путями к исходным файлам *.cji, мы можем открыть веб-бразер и обратиться по адресу http://localhost/cgi-bin/hello.cgi. И результат будет : Hello, world!
Стандарный этапы выполнения cgi скрипта :
- на сервер приходит HTTP запрос
- сервер парсит этот запрос
- создает изолированный набор переменных окружения (REQUEST_METHOD, CONTENT_LENGTH, QUERY_STRING и т.д.) и запускает cgi скрипт. (Как вы догадались, эти перменные мы и будет считывать нашим скриптом, это входящие данные, например данные запроса - QUERY_STRING)
- после завершения скрипта, веб-сервер формирует ответ на основании полученного вывода в STDOUT и отправляет клиенту.
Плюсы :
- как было сказано, подойдет любой язык(среда) который способен считывать и отдавать данные из обычного потоков ввода и вывода STDIN/STDOUT
Минусы :
- каждый новый запрос формирует отдельный экзепляр скрипта (отдельный процесс), что сказывается на быстродействии
FastCGI - дальнейшее развитие технологии CGI. По сравнению с CGI является более производительным и безопасным.
Отличия от CGI :
- Недостаток CGI-программ в том, что они должны быть перезапущены веб-сервером при каждом запросе, что приводит к понижению производительности. FastCGI, вместо того чтобы создавать новые процессы для каждого нового запроса, использует постоянно запущенные процессы для обработки множества запросов. Это позволяет экономить время.
- В то время как CGI-программы взаимодействуют с сервером через STDIN и STDOUT запущенного CGI-процесса, FastCGI-процессы используют Unix Domain Sockets или TCP/IP для связи с сервером. Это даёт следующее преимущество над обычными CGI-программами: FastCGI-программы могут быть запущены не только на этом же сервере, но и где угодно в сети. Также возможна обработка запросов несколькими FastCGI-процессами, работающими параллельно.
FastCGI может быть использован в любом языке, поддерживающем сокеты. Есть большое разнообразие библиотек для разных языков программирования.
CGI + Java
Начнем с простого. Как было описано в первых этапах, нам необходим механизм считывания переменных окружения, для того что бы знать входящие параметры HTTP запроса. Мы помним что веб-сервер создает эти переменные в изолированном виде для каждого процесса, и что простого вызова System.getProperty(“cgi.query_string”) будет недостаточно. Мы должны передать эти переменные java программе, а если быть точным, то JVM процессу. Для этого создадим скромный bash скрипт, который будет запускать java и передавать нужные параметры :
После, соответственно написать саму java программу (hello.java), скомпилировать и положить рядом. Для удобства я использовал библиотеку cgi_lib, методы которой инкапсулируют логику чтения и генерации ответа.
На самом деле методы класса cgi_lib используют функции System.getProperty() для чтения входящих данных, а поток вывода System.out.println() для формирования ответа.
Вот и все. Осталось проверить результат по адресу http://localhost/cgi-bin/Hello.cgi.
FastCGI + Java
С FastCGI придется немножко повозиться, но результат эта реализация даст лучше, потому что во первых, процесс запускается только единожды, во вторых, можно настроить лоад балансер, в третьих само приложение может находиться по совершенно другому ip адресу.
- Выкачать исходники этой библиотеки
- Распаковать и перейти в директорию java, где мы и будем создавать веб-приложение
- Создать Класс TinyFCGI.java
- скомпилировать все java файлы находящиеся в директории java
- запустить приложение java -DFCGI_PORT=9884 TinyFCGI (помним что FastCGI-процессы используют Unix Domain Sockets или TCP/IP для связи с сервером.)
- теперь осталось настроить Apache установив моудль mod_proxy_fcgi
- сделать доступным sudo a2enmod proxy_fcgi
- создать файл конфигурации /etc/apache2/conf-enabled/your_site.conf
- и перезапустить сервер sudo apache2ctl restart
Посмотреть что же у нас получилось можно по адресу - http://localhost/your_site.
Вывод
Конечно *CGI интерфейс не заменит вам полноценного JavaEE сервера или сервлет контейнера, но я бы сказал, что это простой и альтернативный путь к созданию веб-приложения “на коленке”(микро-сервис) и используя не только Java, но и тот язык, который вы довольно хорошо знаете.