Web Фреймворк по-японски — Amon2

от автора

INTRO

В интервью японца Tokuhiro Matsuno прозвучала следующая фраза:

«Некоторыми приложениями нашей компании пользуются более миллиона человек. Все это работает на Amon2

Я не нашел на русском языке никакой инфы об этом веб фреймворке. И решил попробовать, что это за Amon2, чисто для себя, и, может быть, кому-то это будет интересно.

Установка.

Под руку попалась виртуалка с Debian GNU/Linux 7.3 (wheezy)
Поехали…

# curl -L http://cpanmin.us | perl - Amon2 ................ Building and testing Amon2-6.00 ... OK Successfully installed Amon2-6.00 78 distributions installed  Successfully installed Amon2-6.00 

Все! Установка завершена.

Из коробки мы получили:

  • Built on PSGI/Plack
  • no XS deps.
  • Thin
  • Easy to learn
  • CLI support
  • Stable
  • Secure options by default
  • uses Xslate templating

Создание каркаса

adduser dotcloud su - dotcloud amon2-setup.pl BBS 
Все идет хорошо, пока …

— Running flavor: Basic — [main] Loading asset: jQuery
[main] Loading asset: Bootstrap
[main] Loading asset: ES5Shim
[main] Loading asset: MicroTemplateJS
[main] Loading asset: StrftimeJS
[main] Loading asset: SprintfJS
[main] Loading asset: MicroLocationJS
[main] Loading asset: MicroDispatcherJS
[main] Loading asset: XSRFTokenJS
[Flavor::Basic] writing tmpl/index.tx
[Flavor::Basic] writing tmpl/include/layout.tx
[Flavor::Basic] writing tmpl/include/pager.tx
[Flavor::Basic] writing lib/BBS.pm
[Flavor::Basic] writing lib/BBS/Web.pm
[Flavor::Basic] writing lib/BBS/Web/Plugin/Session.pm
[Flavor::Basic] writing lib/BBS/Web/Dispatcher.pm
[Flavor::Basic] writing lib/BBS/Web/View.pm
[Flavor::Basic] writing lib/BBS/Web/ViewFunctions.pm
[Flavor::Basic] writing lib/BBS/DB.pm
[Flavor::Basic] writing lib/BBS/DB/Schema.pm
[Flavor::Basic] writing lib/BBS/DB/Row.pm
[Flavor::Basic] writing script/bbs-server
[Flavor::Basic] writing Build.PL
[Flavor::Basic] writing minil.toml
[Flavor::Basic] writing builder/MyBuilder.pm
[Flavor::Basic] writing cpanfile
[Flavor::Basic] writing static//js/jquery-2.0.3.min.js
[Flavor::Basic] writing static//bootstrap/fonts/glyphicons-halflings-regular.eot
[Flavor::Basic] writing static//bootstrap/css/bootstrap-theme.min.css
[Flavor::Basic] writing static//bootstrap/fonts/glyphicons-halflings-regular.woff
[Flavor::Basic] writing static//bootstrap/fonts/glyphicons-halflings-regular.ttf
[Flavor::Basic] writing static//bootstrap/css/bootstrap.min.css
[Flavor::Basic] writing static//bootstrap/js/bootstrap.min.js
[Flavor::Basic] writing static//bootstrap/fonts/glyphicons-halflings-regular.svg
[Flavor::Basic] writing static//bootstrap/js/bootstrap.js
[Flavor::Basic] writing static//bootstrap/css/bootstrap.css
[Flavor::Basic] writing static//bootstrap/css/bootstrap-theme.css
[Flavor::Basic] writing static//js/es5-shim.min.js
[Flavor::Basic] writing static//js/micro_template.js
[Flavor::Basic] writing static//js/strftime.js
[Flavor::Basic] writing static//js/sprintf-0.7-beta1.js
[Flavor::Basic] writing static//js/micro-location.js
[Flavor::Basic] writing static//js/micro_dispatcher.js
[Flavor::Basic] writing static//js/xsrf-token.js
[Flavor::Basic] writing static/img/.gitignore
[Flavor::Basic] writing static/robots.txt
[Flavor::Basic] writing static/js/main.js
[Flavor::Basic] writing static/css/main.css
[Flavor::Basic] writing db/.gitignore
[Flavor::Basic] writing config/development.pl
[Flavor::Basic] writing config/production.pl
[Flavor::Basic] writing config/test.pl
[Flavor::Basic] writing sql/mysql.sql
[Flavor::Basic] writing sql/sqlite.sql
[Flavor::Basic] writing t/Util.pm
[Flavor::Basic] writing t/00_compile.t
[Flavor::Basic] writing t/01_root.t
[Flavor::Basic] writing t/02_mech.t
[Flavor::Basic] writing t/03_assets.t
[Flavor::Basic] writing t/06_jshint.t
[Flavor::Basic] writing xt/01_pod.t
[Flavor::Basic] writing xt/02_perlcritic.t
[Flavor::Basic] writing .gitignore
[Flavor::Basic] writing .proverc
[Flavor::Basic] writing static/500.html
[Flavor::Basic] writing static/504.html
[Flavor::Basic] writing static/503.html
[Flavor::Basic] writing static/502.html
[Flavor::Basic] writing static/404.html
There is no git command.
Setup script was done! You are ready to run the skelton.  You need to install the dependencies by:      > carton install  And then, run your application server:      > carton exec perl -Ilib script/bbs-server  -------------------------------------------------------------- 

Вроде все ок, но не хватает carton и рекомендуется ввести еще несколько команд.
Ставим его

cpan Carton  # От рута carton install #  Надо делать в папке BBS! Не от рута! 

Получаем следующую структуру файлов и директорий:

builder  Build.PL  config  cpanfile  cpanfile.snapshot  db  lib  local  minil.toml  script  sql  static  t  tmpl  xt 

Создание веб приложения

cd db vim sqlite.sql 

Файл sqlite.sql со следующим содержанием:

CREATE TABLE IF NOT EXISTS member (     id           INTEGER NOT NULL PRIMARY KEY,     name         VARCHAR(255) );  CREATE TABLE IF NOT EXISTS sessions (     id           CHAR(72) PRIMARY KEY,     session_data TEXT );  CREATE TABLE IF NOT EXISTS entry (     entry_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,     body varchar(255) not null );  

Создаем базу:

sqlite3 development.db < sqlite.sql   

Далее

cd config/ vim  development.pl 

Втыкаем в него вот такой конфиг:

use File::Spec; use File::Basename qw(dirname); my $basedir = File::Spec->rel2abs(File::Spec->catdir(dirname(__FILE__), '..')); my $dbpath = File::Spec->catfile($basedir, 'db', 'development.db'); +{     'DBI' => [         "dbi:SQLite:dbname=$dbpath", '', '',         +{             sqlite_unicode => 1,         }     ], }; 

Пытаемся для теста запустить веб сервер.

 perl -Ilib script/bbs-server Can't locate Teng/Schema/Declare.pm in @INC (you may need to install the Teng::Schema::Declare module) (@INC contains: script/../lib lib /etc/perl /usr/local/lib/perl/5.18.1 /usr/local/share/perl/5.18.1 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.18 /usr/share/perl/5.18 /usr/local/lib/site_perl .) at script/../lib/BBS/DB/Schema.pm line 6. BEGIN failed--compilation aborted at script/../lib/BBS/DB/Schema.pm line 6. Compilation failed in require at script/../lib/BBS.pm line 7. BEGIN failed--compilation aborted at script/../lib/BBS.pm line 7. Compilation failed in require at /usr/share/perl/5.18/parent.pm line 20. BEGIN failed--compilation aborted at script/../lib/BBS/Web.pm line 5. Compilation failed in require at script/bbs-server line 9. BEGIN failed--compilation aborted at script/bbs-server line 9. 

И обламываемся.
Хорошо, ставим

cpan Teng::Schema::Declare cpan Module::Functions cpan Plack::Middleware::ReverseProxy cpan Plack::Handler::Starlet 

Наконец-то увидели заветное:

dotcloud@debian:~/BBS$ perl -Ilib script/bbs-server BBS: http://127.0.0.1:5000/ 

Если зайти по этому адресу, то можно увидеть вот такую неземную красотищу:

Теперь осталось из этого хозяйства сделать ВВС — доску объявлений (бабку бибисиху — знаете такую?)

vim lib/BBS/DB/Schema.pm 

И постим туда следующее:

 package BBS::DB::Schema; use strict; use warnings; use utf8;  use Teng::Schema::Declare;  base_row_class 'BBS::DB::Row';  table {     name 'sessions';     pk 'id';     columns qw(session_data); };  table {     name 'entry';     pk 'entry_id';     columns qw(entry_id body); };  1; 

Далее:

vim lib/BBS/Web/Dispatcher.pm 
package BBS::Web::Dispatcher; use strict; use warnings;  use Amon2::Web::Dispatcher::Lite;  any '/' => sub {     my ($c) = @_;      my @entries = $c->db->search(         entry => {         }, {             order_by => 'entry_id DESC',             limit    => 10,         }     );     return $c->render( "index.tx" => { entries => \@entries, } ); };    post '/post' => sub {     my ($c) = @_;      if (my $body = $c->req->param('body')) {         $c->db->insert(             entry => +{                 body => $body,             }         );     }     return $c->redirect('/'); };  1; 

И правим темплейт

vim tmpl/index.tx 
: cascade "include/layout.tx"  : override content -> {  <form method="post" action="<: uri_for('/post') :>">     <input type="text" name="body" />     <input type="submit" value="Send" /> </form>  <ul>     <: for $entries -> $entry { :>     <li><: $entry.entry_id :>. <: $entry.body :></li>     <: } :> </ul>  : } 

Запускаем:

perl -Ilib script/bbs-server 

И при необходимости доустанавливаем следующие пакеты

cpan Router::Simple cpan Router::Simple::Sinatraish  cpan DBD::SQLite 

УРА!
Бабка бибисиха — работает!

Осталось все это задеплоить на nginx

Устанавливаем nginx в качестве фронтэнда

Сначала делаем init файл, и чтобы запускался не от рута
vim /etc/init.d/plackup  
#!/bin/sh  PORT=5000 WORKERS=4 AMON_DIR="/home/dotcloud/BBS" AMON_APP="$AMON_DIR/script/bbs-server" AMON_USER="dotcloud" AMON_MODE="development" website="cc_Website" plackup="/usr/local/bin/plackup " PID=$AMON_DIR/logs/plackup.$website.pid plackup_args="-E $AMON_MODE -p $PORT -s Starman --pid=$PID --workers $WORKERS -D"  U=`id -un` if [ $U = root ]; then        WRPERM=`find $AMON_DIR/ ! -user $AMON_USER | wc -l`        if [ "$WRPERM" != 0 ]; then                echo Fixing file ownership on $AMON_DIR                chown -R $AMON_USER.nginx $AMON_DIR        fi        cd /        su $AMON_USER -s /bin/sh  $0 "$@"        exit elif [ $U != $AMON_USER ]; then        echo "Should be run under $AMON_USER or root"        exit 1 fi   lockfile=$AMON_DIR/logs/plackup.$website  start() {     [ -x $plackup ] || exit 5     [ -f $AMON_APP ] || exit 6     echo -n $"Starting $website: "     $plackup $plackup_args -a $AMON_APP 2>&1 > /dev/null     retval=$?     if [ $retval -eq 0 ]; then         echo OK         touch $lockfile     else         failure $"Unable to start"     fi     echo     return $retval }  stop() {     echo -n $"Stopping $website: OK"     if [ -f $PID ]; then         kill `cat $PID` > /dev/null         retval=$?         [ $retval -eq 0 ] && rm -f $lockfile         echo         return $retval     fi     failure $"pid $PID not found"     echo     return 1 }  restart() {     stop     start }  case "$1" in     start)         $1         ;;     stop)         $1         ;;     restart)         $1         ;;     *)         echo $"Usage: $0 {start|stop|restart}"         exit 2 esac 

Добавляем конфиг в nginx

vim /etc/nginx/conf.d/virtual.conf 
upstream amon {         server 127.0.0.1:5000; }  server {     listen          *:80;           location / {                 try_files /empty  @backend;     }         location @backend {             proxy_set_header Host $http_host;             proxy_set_header X-Forwarded-Host $host;             proxy_set_header X-Real-IP $remote_addr;             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;             proxy_set_header X-Forwarded-Proto $scheme;             proxy_pass http://amon;     }   } 

Все готово!

Заключение

В качестве заключения я приведу опять-таки цитату из того самого интервью, с которого все началось:

Расскажи об Amon2. Чем он отличается от других Perl-фреймворков для веб?

Amon2 очень простой, надежный веб-фреймворк общего назначения.

Отличия от Mojolicious

Mojolicious неплох, и мне нравится сам подход. К сожалению, там не сохраняется обратная совместимость. В Amon2 же наоборот. Мне кажется, что ломать обратную совместимость можно только с изменением названия. Когда я решу что-либо серьезно изменить, я выпущу Amon3.

Отличия от Catalyst

Catalyst зависит от Moose, а Amon2 — нет. Это потому, что я хочу, чтобы мои приложения загружались быстро.

Отличия от Dancer

Практически нет никаких отличий между Amon2 и Dancer, включая Dancer2.

Автор скромняга, конечно.

А теперь мое имхо:

  1. Фреймворк и правда очень легковесный
  2. Написан японцем, с их тщательностью и перфекционизмом. Это ощущается в коде.
  3. Девушка ( miyagawa ), которая написала plackup, с ним корешится, что называется, два сапога пара.
    Ведь используется и рекомендуется именно такая связка plackup + Amon2
  4. Надеюсь, что фрейворк, который юзают «более миллиона человек» по заявлению автора, не будет брошен просто так, а будет развиваться дальше.
  5. Фрейворк — относительно новый и современный, но уже есть громадное кол-во модулей на cpan
  6. В целом оставил приятное впечатление.

ссылка на оригинал статьи http://habrahabr.ru/post/122611/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *