вторник, 7 января 2014 г.

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. В целом оставил приятное впечатление.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers.


Комментариев нет:

Отправить комментарий