YAPC::Asia Tokyo 2014 Tokyo の1日目の「Web Framework BenchmarksとPerlの現状報告会」というタイトルでLTと、2日目に「Dockerで遊ぼう」という発表をしてきました。

うしろのばやしさんにラーメンと一緒に飲み込まれてしまった感がありますが、PSGI/Plackのパフォ厨としては、どうしても現状を報告しておきたい内容でありました。unicornに勝ちたい!!

2日目の朝イチというコマでありましたが、大勢の方に見に来て頂いて驚きました。前半の内容を盛り込みすぎて時間が足りなくなってしまい、すみませんでした。アンケートで既にDockerを使っている方が凄く多かったので、インストールの部分とかは飛ばしてもよかったんじゃないかと思いましたが、Dockerを使う上で少しでも役に立てば幸いです。

ベストトーク賞

うずらさんのPHP発表は内容面白かったし、喋りはうまいし、スライドも作り込んであってさすがという感じでした。ベンチマークで自分がLTで紹介したオプションを使って頂いて嬉しかった。時代はPHP

その他のトークではgugodの「One layer down below」とSawyerの「Plack for Fun and Profit (But Mostly Profit)」の二人がよかった。新しいものや多機能なものに飛びつくのではなく、ひとつレイヤーの低い部分から必要最小限で高速に動作するものを作ったり、ビジネスの継続という視点で冷静に見極める。Booking.comという大規模なサービスの中身が垣間みれたようで、とても参考になりました。

そうそう、今回はスピーカー登録だけだったので、ベストトーク賞の投票権がなかったのが残念。

microservice

昔からあるものにそれっぽい名前がついて流行るというやつなんだけど、今回のYAPC::Asiaでもいくつかのトークで出て来た。とくにあんちぽくんさんの発表がよくまとまっていた。

個人的に、この分野にコミットできることとしては、内部APIをコールする高速なHTTPクライアントや、内部APIに実行に特化したAppサーバの開発があるのかなぁと漠然と思った。gugodがトークで紹介していたHijkがまさにそれ。

おそらく、それがないと「microservice化したらアプリケーションが100倍遅くなった!!!microserviceは単なるバズワード!!!!!」とかになってしまうので、microserviceを唱えるみなさまにおかれましては如何に通信のオーバーヘッドを減らすかというあたり、「並列実行で万全〜」とかじゃなくもうちょい具体的な解決案の提案が必要なんじゃないかと思いました。

そういえば。2009年のYAPC::AsiaでLWPからCurlに変更してCPU使用率をグッと下げるというのを紹介していた

isuconの宣伝

2つの資料にも入っていますが、今回のYAPC::Asiaでは会う人、会う人にISUCON予選への出場を進めておいた。楽しいし、勉強になるし、100万円は僕らが頂くので貰えませんが賞金でるし、みんな挑戦するとよいですよ #上から目線

参加はこちらから↓↓↓↓

ISUCON4 オンライン予選の参加登録を開始しました

余談

スライドのレゴはこのセットのバイクを組み替えると作れます。Pete Corpさんという方がyoutubeで公開している動画を見て作ってみました

レゴ ムービー スーパーサイクルチェイス 70808
レゴ (2014-02-07)
売り上げランキング: 1,434

レゴムービーは最高の映画です

LEGO (R) ムービー ブルーレイ&DVDセット(初回限定生産/2枚組/デジタルコピー付)  [Blu-ray]
ワーナー・ブラザース・ホームエンターテイメント (2014-08-02)
売り上げランキング: 460

8月28日から30日まで開かれる YAPC::Asia Tokyo 2014 で Dockerの話をします。

コマは2日目、30日の朝イチの「多目的教室3」です

Dockerで遊んでみよっかー - YAPC::Asia Tokyo 2014

各所で盛り上がりに盛り上がっているDockerを試して、遊んで、どんなものなのか理解していこうという内容です。Hello Worldで終わるのではなく、身近な作業に活用したり、ちょっとしたアプリケーションの実行環境として使ってみようという内容です。

資料できてきていますが、やや基本の部分のボリュームが大きくなっています。Dockerに興味がある、でもまだ手を付けてないような方がいましたら、聞きに来てくれると嬉しいです。

前日HUBで飲み過ぎないでね!

<おまけ>

Dockerとは関係ありませんが、ISUCON4 オンライン予選の参加登録が開始されています!!!Webアプリケーションを書いている方もインフラを扱っているエンジニアも運用エンジニアも、ぜひチャレンジしてください!!私もでます!!

参加はこちらから↓↓↓↓

ISUCON4 オンライン予選の参加登録を開始しました

昨日のエントリで紹介した「Webアプリケーションの パフォーマンス向上のコツ 実践編」ですが、いくつかスライドを追加して、「完全版」として公開しました。

ISUCONだけに限らず、一般的なWebアプリケーション、SQLのチューニングの参考となる資料となっていると思いますので、見て頂けたら嬉しいです。

<追記>

ISUCON4 オンライン予選の参加登録が開始されています!!!Webアプリケーションを書いている方もインフラを扱っているエンジニアも運用エンジニアも、ぜひチャレンジしてください!!私もでます!!

参加はこちらから↓↓↓↓

ISUCON4 オンライン予選の参加登録を開始しました

学生さん限定のイベント「ISUCON 夏期講習」今年もやりました。イベントは、tagomorisからISUCONやWebアプリケーションについての座学を行ったあとに、ISUCON3の予選問題にチャレンジをしてもらいました。またチャレンジをしてもらいながら、どのようにWebアプリケーションのパフォーマンスをあげていったらよいのか、自分の方から説明をしました。今年はスコアをあげることができる参加者が多く、驚きました。

去年と同じようにISUCONの問題にチャレンジする環境としてEC2を使いましたので、そのAMIを公開します。

AMI ID:ami-e796b3e6
AMI Name: isucon_summer_class_2014
Region: Asia Pacific (Tokyo)

「ISUCON 夏期講習 2014」サーバのつくりかた

EC2のインスタンスを起動する際に、上記のAMIを指定して起動してください。HVM対応のインスタンスが必要になります。夏期講習では「c3.xlarge」を使いました。スポットインスタンスを活用するとリーズナブルに試す事ができると思われます。

ベンチマークツールにポート5043が必要になるので、ssh、http、tcpの5043をセキュリティグループの設定をつかってアクセス可能にする必要があります。

サーバが起動したら、「ec2-user」でログインしてください。

$ ssh -i keyfile.pem ec2-....amazonaws.com

ISUCON2の環境は「isu-user」ユーザにて構築してあります。

$ sudo su - isu-user

パスワードが設定されてないので、適宜設定するなりsshの公開鍵を設置すると作業がしやすいですね。

ベンチマークツールはWebUIを用意してあります。ブラウザでサーバのtcp 5043にアクセスします

http://ec2-....amazonaws.com:5043/

benchui.png

こんな画面になります。説明が下の方にありますので、読んでください。

ベンチマークツールですが、去年の予選とは若干異なり、時間は30秒。workloadは「1」に固定されています。よりチャレンジしたい場合はソースコード見て変更してみてください。

「Webアプリケーションの パフォーマンス向上のコツ」の発表資料

夏期講習の座学用に用意した資料となります。Webアプリケーションのパフォーマンスをあげるにはどんなことを考えて、やればいいのかについて簡単に解説しています。資料は2つに分かれていて、一つ目が「概要編」、二つ目が「実践編」となっています。

実践編は途中で力尽きている感じですが、ちゃんと書けば仕事でも役に立ちそうなので、あとで完全版にしたいと思っております。

<追記>
完全版公開しました
「ISUCONで学ぶ Webアプリケーションのパフォーマンス向上のコツ 実践編 完全版」を公開しました
</追記>

学生のみなさまのISUCON4への参加と活躍を楽しみにしております。

追記(2014/08/22)と謝辞

実践編の資料を作るにあたり、@acidlemon さんの記事を参考にしました
ざっくりと #isucon 2013年予選問題の解き方教えます

サーバ環境の構築にあたっては「オンライン予選で使用した問題が手元で再現できるAMIを公開しました」で紹介されているAMIも参考にしています。

改めて出題の @fujiwaraさん @acidlemonさんをはじめKAYACの皆様に感謝しております。

追記2

ISUCON4 オンライン予選の参加登録が開始されています!!!Webアプリケーションを書いている方もインフラを扱っているエンジニアも運用エンジニアも、ぜひチャレンジしてください!!私もでます!!

参加はこちらから↓↓↓↓

ISUCON4 オンライン予選の参加登録を開始しました

最近、Module::CoreListのWebUIと、perl-buildで使っているperlのリリースとアーカイブのリストの生成をHerokuに移動しました。両方とも、情報を更新するworkerとappサーバが必要になるので、Heroku上でProcletを使ってappサーバとworkerなどを動かしてみました。

HerokuでのProcletの使い方

まず、cpanfileとProcfileを用意します。

$ cat cpanfile
requires 'HTTP::Tiny','0.043';
requires 'Getopt::Long';
requires 'Proclet';
requires 'Plack';
requires 'Starlet';

$ cat Procfile
web: ./server.pl --port $PORT

Procfileに書くのは1つだけです。2つ以上起動する場合は、別途お金がかかります。

server.plはこんな感じで、オプションでportを受け取り、workerとStarletのプロセスを起動します。

#!/usr/bin/env perl

use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/lib";
use Proclet;
use Plack::Loader;
use Getopt::Long;
use HTTP::Tiny;

my $port = 5000;
Getopt::Long::Configure ("no_ignore_case");
GetOptions(
    "p|port=s" => \$port,
);

$proclet->service(
    tag => 'worker',
    code => sub {
        my $worker = MyWorker->new;
        $worker->run
    },
);

my $app = MyWeb->to_psgi;
$proclet->service(
    code => sub {
        my $loader = Plack::Loader->load(
            'Starlet',
            port => $port,
            host => 0,
            max_workers => 5,
        );
        $loader->run($app);
    },
    tag => 'web',
);

$proclet->run;

場合によっては定期的にサービスを叩くworkerも合った方がいいかもしれません

$proclet->service(
    every => '*/30 * * * *',
    tag => 'ping',
    code => sub {
        my $ua = HTTP::Tiny->new;
        $ua->get("http://${yourservicename}.herokuapp.com/");
    }
);

Procletはcron likeなworkerもサポートしています。

server.plは実行権限も付けておきます

$ chmod +x server.pl

準備ができたら、herokuコマンドを使ってアプリケーションを登録します。

$ heroku create yourappname --buildpack https://github.com/kazeburo/heroku-buildpack-perl-procfile.git

拙作のbuildpackを使うと、cpanfileを使って依存モジュールをいれ、環境変数を設定してくれます。

最後にpushしてサービスを起動します。

$ git push heroku master
...
-----> Heroku receiving push
-----> Fetching custom buildpack
-----> Perl/Procfile app detected
-----> Installing dependencies

便利ですね!

タイトルがそのままですが、GrowthForecastのDocker imageを作りました。

https://registry.hub.docker.com/u/kazeburo/growthforecast/

使い方は単純に起動するだけなら次のようになります。

$ docker run -p 5125:5125 kazeburo/growthforecast

これだと、データが永続化されないので、適当なボリュームをマウントします。

$ docker run -p 5125:5125 -v /host/data:/var/lib/growthforecast kazeburo/growthforecast

起動オプションを変更したい場合は、コマンドを渡すか、Dockerfileを書いてビルドすると良いでしょう。

$ docker run -p 5125:5125 -v /host/data:/var/lib/growthforecast kazeburo/growthforecast \
    growthforecast.pl --time-zone UTC --data-dir /var/lib/growthforecast

ヘルプの表示

$ docker run -i kazeburo/growthforecast growthforecast.pl -h

Dockerfileの例

FROM kazeburo/growthforecast CMD growthforecast.pl —time-zone Asia/Tokyo —data-dir /var/lib/growthforecast —front-proxy 0.0.0.0/0 ..

GitHubとDocker Hubを組み合わせてDocker imageの作成を自動化

このDocker imageはGitHubとDocker HubのAutomated Build Repositoryの機能を組み合わせて、GitHub上でタグが作れたのをフックして自動的に作られています。

Automated Build Repositoryを使うには、まずDocker Hub側で、ビルドを開始するためのTrigger URLを有効にします。

gf_gh_trigger.png

そして、このURLをGitHubに入力します。新規のwebhookを追加し、Payloadに先ほどのURLをいれます。Secretは使わないので適当に入れました。今回はタグが作成された際にDocker Imageを作りたいので、Webhookを起動するイベントの「individual events」のラジオボタンを押し、出てきた中から、「Create」だけにチェックボックスをいれました。

gf_hook_gh.png

あと、Dockerfileで最新のタグを指定してソースコードを取得し、インストールを行うようにしています。

RUN git clone -b $(curl -s https://api.github.com/repos/kazeburo/GrowthForecast/tags|jq -r '.[0].name') https://github.com/kazeburo/GrowthForecast.git /tmp/GrowthForecast
RUN cpanm -n --no-man-pages -v --no-interactive /tmp/GrowthForecast

GrowthForecast(や他のCPANモジュール)は、MinillaShipItというツールで、タグの追加とCPANへのリリースを同時に行っていますが、上の例でGrowthForecastのインストールをCPANから行わずにgithubから取得しているのは、DockerのAutomated Buildがgit pushした瞬間から開始されて、CPANのインデックスの更新が追いつかずdocker build中に最新版が取得できない可能性があるからです。

どうぞご利用くださいませ。

最近、Vagrantのprovisionerを使ってパッケージの作成などをいくつか行っているのですが、その際にVMを落とし忘れ、ホストしてるマシンの余計なリソースを使ってしまっていることがあります。

なので、provisionerでサーバをdestroy/haltするやつを書いてみました。

rubygems: https://rubygems.org/gems/vagrant-destroy-provisioner
github: https://github.com/kazeburo/vagrant-destroy-provisioner

勝手にshutdownしてイメージを破棄するデモ動画です。

インストールはvagrant pluginコマンドから行います。

$ vagrant plugin install vagrant-destroy-provisioner

使い方はこんな感じ

VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "CentOS-6.4-x86_64-v20131103"
  config.vm.box_url = "http://developer.nrel.gov/downloads/vagrant-boxes/CentOS-6.4-x86_64-v20131103.box"
  config.vm.provision "shell", inline: "echo 'Hello Provisioner'"
  config.vm.provision "destroy"
end

VMのshutdownだけをするモードも一応サポートしていて

config.vm.provision "destroy", destroy: false

とすると、vagrant halt相当のみ実行されます。destroyオプションのデフォルトはtrueです。

Docker Provisionerを使う場合は、destroy: falserun: "always" を使うと多分便利。先日のPerl-Buildのfatpackの例だと

 config.vm.provision "docker", run: "always" do |d|
    d.build_image "/perl-build/author",
        args: "-t perl-build"
end
config.vm.provision "shell", run: "always",
    inline: "docker run -v /perl-build:/perl-build perl-build"
config.vm.provision "destroy", destroy: false, run: "always"

となります。毎度 vagrant up に —provision オプションを付けなくても良いので楽。

vagrant-destroy-provisionerを使うと、VMの使い捨てが自動化されて非常に便利。どうぞご利用ください。

以下のgems、サイトを参考にしました。

https://rubygems.org/gems/vagrant-reload

vagrantのprovisionerを自作する - Qiita

plenvやxbuildで使っているperl-buildなのですが、ひろむ氏からコミット権限頂いてアップデートをしました。

変更点としてはいつでも使えるように search.cpan.org への依存度を減らしたことと、だれでも同じように作業ができるよう依存モジュールを1つのスクリプトにまとめるfatpackにDockerを導入して自動化した点です。

search.cpan.org への依存度の削減

perl-buildはperlのバージョンを引数に渡してインストールを行います。

$ perl-build 5.20.0 /opt/perl-5.20

この際に、渡されたperlのバージョンからアーカイブのパスを調べる必要があります。アーカイブのパスとは以下のようなものです

R/RJ/RJBS/perl-5.21.0.tar.gz
R/RJ/RJBS/perl-5.20.0.tar.gz
R/RJ/RJBS/perl-5.20.0-RC1.tar.gz
S/SH/SHAY/perl-5.19.11.tar.gz
A/AR/ARC/perl-5.19.10.tar.bz2
T/TO/TONYC/perl-5.19.9.tar.bz2

アーカイブはリリースを行ったCPAN Authorのディレクトリ以下に配置されます。perlのソースコードをダウンロードするにはそのバージョンのperlをリリースしたAuthorのPAUSE IDやパスをなにかしらの方法で調べる必要があります。

この一つの方法が CPAN::Perl::Releases モジュールです。CPAN::Perl::Releasesを使うとこんな感じでパスが取れます。

use CPAN::Perl::Releases qw/perl_tarballs/;
perl_tarballs( '5.14.0' );

Returns a hashref like:

{
  "tar.bz2" => "J/JE/JESSE/perl-5.14.0.tar.bz2",
  "tar.gz" => "J/JE/JESSE/perl-5.14.0.tar.gz"
}

CPAN::Perl::Releasesのソースコード中にベタにバージョンとPAUSE IDの対照表が書かれています。

perl-buildのスクリプトにはCPAN::Perl::Releasesが組み込まれており、最初にCPAN::Perl::Releasesを使ってパスを得ようとします。しかし、組み込まれているCPAN::Perl::Releasesはperl-buildスクリプトをアップデートしない限り、どんどん古くなって行くので、新しいバージョンがリリースされたときに追従出来ず、パスを探せなくなります。

そこでperl-buildは次に http://search.cpan.org/dist/perl-$version をスクレイピングし、パスを調べます。ところが最近、しばしばsearch.cpan.orgがダウンし、またそのダウンタイムも長くなっている(感覚値)ことから、perlをインストールしたい時にエラーでインストールができないということも起きています。

そこで、search.cpan.orgへの依存を減らすべく、こんなページを作りました。curlでアクセスするとこんな感じ。

$ curl -s http://perl-releases.s3-website-us-east-1.amazonaws.com/|head
5.21.0  R/RJ/RJBS/perl-5.21.0.tar.gz
5.20.0  R/RJ/RJBS/perl-5.20.0.tar.gz
5.20.0-RC1      R/RJ/RJBS/perl-5.20.0-RC1.tar.gz
5.19.11 S/SH/SHAY/perl-5.19.11.tar.gz
5.19.10 A/AR/ARC/perl-5.19.10.tar.bz2
5.19.9  T/TO/TONYC/perl-5.19.9.tar.bz2
5.19.8  R/RJ/RJBS/perl-5.19.8.tar.bz2

中身はtsvファイルで、バージョンとパスの組み合わせが得られるだけのページです。静的ファイルなのでs3でホストしています。tsvファイルを作るスクリプトは

https://github.com/kazeburo/perl-releases-list

にあげてあります。このスクリプトをcronで定期的に動かし、s3にアップロードしています。

新しいperl-buildはsearch.cpan.orgにアクセスする前に、このページをダウンロードしてパスを解決します。このページでも解決できない場合はsearch.cpan.orgへアクセスします。

さらに、perlのアーカイブをダウンロードする際のデフォルトのミラーがsearch.cpan.orgだったので、www.cpan.orgへ変更し、search.cpan.orgへの依存をぐっと減らしました。これでもし、search.cpan.orgが落ちていたとしてもperl-buildが使えるようになりました。

ちなみにミラーは環境変数で変更が可能です。

$ PERL_BUILD_CPAN_MIRROR=http://ftp.jaist.ac.jp/pub/CPAN/ perl-build 5.18.1 /opt/perl-5.18

国内ミラーの方がダウンロード速度は速くなるんじゃないかなぁと思います。

Dockerを使ったfatpack

githubに上がっているperl-buildは依存モジュール等を1つにまとめたスクリプトとなっています。これはApp::Fatpackerを使って生成したファイルとなっています。

fatpackしたスクリプトが古いperl 5.8でも動くようにするために、fatpackを行うperlも5.8を使います。以前はtokuhirom氏のローカル環境でやっていた思うのですが、だれでも簡単に再現できるようにした方がいいよねということで、Docker(+Vagrant)で自動化してみました。

Vagrantは1.63が必要です。実行は

$ cd author
$ vagrant up --provision
$ vagrant halt

Docker provisionerを使ってimageを作って実行します。Vagrantfileはこんな感じ

Vagrant.configure("2") do |config|
  config.vm.box = "hashicorp/precise64"
  config.vm.synced_folder "../", "/perl-build"
  config.vm.provision "docker" do |d|
    d.build_image "/perl-build/author",
      args: "-t perl-build"
  end
  config.vm.provision "shell",
    inline: "docker run -v /perl-build:/perl-build perl-build"
end

最後、shell provisionerを使ってdocker runしていますが、これはDocker provisionerにサポートされているrun機能を使うとrunが終了するまえにvagrant upコマンドが終了してしまう(runはバックグラウンドで実行されている)からです。shellで実行するとfatpackが完了するまでvagrant upが待ってくれるので分かりやすくなります。

Dockerfileはこんなの

FROM jmmills/plenv-base:latest
RUN plenv install 5.8.5
RUN plenv global 5.8.5
ENV PLENV_VERSION 5.8.5
RUN curl -L http://cpanmin.us/ | plenv exec perl - -n ExtUtils::MakeMaker@6.56
RUN curl -L http://cpanmin.us/ | plenv exec perl - -n App::cpanminus
RUN curl -L http://cpanmin.us/ | plenv exec perl - -n Perl::Strip App::FatPacker
RUN plenv rehash
CMD bash -l -c 'cd /perl-build; cpanm -n --installdeps . ; bash author/fatpack.sh'

あとは、作ったスクリプトのテストもDocker使ってできるといいなぁと思ってます。

どうぞご利用ください。

あるモジュールがPerlのコアモジュールに含まれているか、どのバージョンが含まれているかをたまに確認したくなりますが、その時に使うのが Modure::CoreList です。Modure::CoreListにはコマンドラインツールも用意されているのですが、tokuhiormが Web Interface版を作っていてとても便利でした。が、こちらは今404になってしまっているので、tokuhiromに確認の上、新しくサイトを動かしました。

http://corelist.rpee.be/

画面はこんな感じ

corelistweb.png

あるバージョンのperlにどのモジュールのどのバージョンが含まれているのかと、モジュールがどのPerlに含まれているのかのリストがでます。

corelistweb2.png

もとのソースコードを参考にしつつ、Kossyとboostrap3で移植しました。移植するついでに、Proclet、Server::Starter、cpanmを使い、無停止でModule::CoreListが自動でアップデートされるようにしてみました。コードはこんな感じ

my $proclet = Proclet->new;

$proclet->service(
    every => '3 * * * *',
    tag => 'cron',
    code => sub {
        open(my $fh, "<", "server.pid") or die "$@";
        my $pid = <$fh>;
        chomp $pid;
        my ($result,$exit_code) = capture(['cpanm','-lCoreList-lib','Module::CoreList']);
        if ( $exit_code == 0 && $result =~ m!Successfully installed Module-CoreList! ) {
            warn "KILLHUP server-starter ($pid)\n";
            kill 'HUP', $pid;
        }
    }
);

$proclet->service(
    code => sub {
        exec(qw!start_server --port!,$port,qw!--pid-file server.pid  --!,
             qw!plackup -Mlib=CoreList-lib/lib/perl5 -E production!,
             qw!-s Starlet --max-workers 10 -a  app.psgi!);
    },
    tag => 'web',
);

$proclet->run;

ニッチですがご利用ください

弊社のGrowthForecast、グラフ数が5000件近くになっていて、複合グラフ作成ページのプルダウンが多くなり杉でグラフを選ぶのが大変な状態だったので、プルダウンを3つにわけました

gf_complex.png

どうぞご利用ください

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

アイテム

  • benchui.png
  • gf_hook_gh.png
  • gf_gh_trigger.png
  • corelistweb2.png
  • corelistweb.png
  • gf_complex.png
  • jstat2gf.png
  • filter-topn.png
  • load-avg.png
  • sum_series.png

ウェブページ

OpenID対応しています OpenIDについて
Powered by Movable Type 4.27-ja