@nqounetです。

Mojoliciousのプロダクション用サーバーのhypnotoadを使ってHerokuで動作させる方法を考えてみます。

まず、Herokuで起動するためのPORTを設定する必要があります。

起動スクリプトの中で$PORTとなっているのは、環境変数なので、Perlでは$ENV{PORT}で取得できます。

hypnotoadの設定

hypnotoadは設定ファイルに設定内容を書きますが、その中で環境変数を書いておくこともできます。

config.plの例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
hypnotoad => {
accepts => 1000,
backlog => 10,
clients => 10,
graceful_timeout => 20,
heartbeat_interval => 5,
heartbeat_timeout => 20,
listen => [qq{http://*:$ENV{PORT}}],
proxy => 1,
requests => 25,
upgrade_timeout => 60,
workers => 4,
},
};

ただ、このようにした場合、どのような環境でもPORTの設定が必要になるので、実際にはMOJO_MODEごとの設定ファイル(例えばconfig.production.confのような)にするのが良いでしょう。

perl app.pl で起動する

前回も書いたとおり、Procfileには1つだけ書くようにしたいので、Procletを使用して見掛け上を1つのアプリにします。

app.plの例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/usr/bin/env perl
use utf8;
use strict;
use warnings;
use Proclet;
use Furl;
require EV;
require IO::Socket::Socks;
require IO::Socket::SSL;


my $proclet = Proclet->new;

$proclet->service(
code => ['hypnotoad', '-f', 'script/app'],
tag => 'web',
);

$proclet->service(
code => ['perl', 'script/worker'],
tag => 'worker',
);

$proclet->service(
code => sub {
my $keepalive_url = $ENV{APP_KEEPALIVE_URL} or die 'set env APP_KEEPALIVE_URL.';
Furl->new->get($keepalive_url);
},
tag => 'keepalive',
every => '*/30 * * * *',
);

$proclet->run;

Procfileの例

1
web: carton exec -- perl app.pl

ポイントとしては、hypnotoadをフォアグラウンドで動作させることです。

hypnotoadをそのまま実行すると、アプリをデーモンにしてしまうのですが、そうするとProcletで管理できなくなります。

workerがある場合は、workerも同じようにserviceとして登録します。

さらに、サービスがスリープしないように、30分毎に自分自身にアクセスするようにすると便利だと思います。

APP_KEEPALIVE_URLは、こちらHUBOT_HEROKU_KEEPALIVE_URLを読み替えて設定してください。