株式会社はてなに入社しました
Google App Engineでローカル開発をするときにdispatch.yamlをもとにReverse Proxyしてくれるツールを書いた
これです
なぜ作ったのか
dispatch.yaml
や dispatch.xml
はGoogle App Engine(以下GAE)のFrontendでルールベースでL7 HTTP Reverse Proxyしてくれるものです。
これはMicroservicesをやる上では大変便利なものになっています。
一方で、これをローカルで動かす手段が少なくとも自分の知る限りはありませんでした。
なので、いままでは各サービスを連携して動作検証したいときは、GAEにデプロイしてしまうか、
あるいは各サービスをそれぞれ別々のポートで立ち上げながら、各サービスに何らかの方法でそれらのマッピング情報を入れてサービス間で連携が可能なようにするなど工夫をする必要がありました。
別々のポートで立ち上げるところまではよしとしても、めんどくさいのでその後の各サービスには統一的にアクセスしたいわけです。
しかし、dispatch.yaml
や dispatch.xml
をnginx.confなどに移植してnginxを立ち上げたりなんてのもまためんどくさい。ぐぬぬ。
せめて dispatch.yaml
や dispatch.xml
をそのまま読んでよしなにReverse Proxyしてくれるサーバーがあると楽そうです。
ということで作りました。
使い方
README.mdにあるとおりですが、こういう感じで使えます。
$ (cd default; dev_appserver.py --port=8081 | tee -a dev.log) & $ (cd mobile-backend; dev_appserver.py --port=8082 | tee -a dev.log) & $ (cd static-backend; dev_appserver.py --port=8083 | tee -a dev.log) & $ gae-dispatcher-emulator -c dispatch.yaml -s default:localhost:8081 -s mobile-frontend:localhost:8082 -s static-backend:localhost:8083
-c
で渡した dispatch.yaml
と -s
で渡しているサービスの待受情報をもとによしなにやってくれるというわけです。
これでデフォルトの localhost:3000
で gae-dispatcher-emulator
実際はforemanなどと組み合わせて使うのがおすすめです。
インストール
go製なので go get
でいけます。
$ go get -u github.com/karupanerura/gae-dispatcher-emulator/...
また、Github Releasesにてバイナリの配布もしてますのでそちらもご利用いただけます。
Releases · karupanerura/gae-dispatcher-emulator · GitHub
macOSであればこういう感じでインストールできるでしょう:
$ curl -sfL -o ~/bin/gae-dispatcher-emulator https://github.com/karupanerura/gae-dispatcher-emulator/releases/download/v0.3.0/gae-dispatcher-emulator_darwin_amd64 $ chmod +x ~/bin/gae-dispatcher-emulator
実装
dispatch.yaml
などを読めることを除けば素直なReverse Proxyとして動くと思います。
具体的には、X-Forwarded-For
ヘッダを処理したりRFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1をもとにhop-by-hopなものとして定義されているヘッダフィールドを取り除くなどのことをしています。
このあたりはlib/Plack/App/Proxy.pm - metacpan.org の実装を参考にしました。
一応APIも公開していますのでforkして追いかけるのはつらそうだけど表面だけ変えたいとかあればお使いください(ただしインターフェースは突然変わるかもしれません):
なにか気になること、困ったこと、要望などあればお気軽にissueやTwitterなどでお知らせください。
errnoから何のエラーか簡単に調べるためのワンライナーの解説
こんなワンライナーがあります:
% perl -E 'say$!=24' Too many open files
これの正体に迫っていきたいと思います。
どのように解釈されるのか
まずはこれがいったいどのようにParseされるのかを知るために、
-MO=Deparse
を付けて実行してみましょう。
% perl -MO=Deparse -E 'say$!=24' use feature 'current_sub', 'evalbytes', 'fc', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval'; say $! = 24; -e syntax OK
say $! = 24
キモはこれです。
$!
という変数に 24
を代入して、その式の結果を say
が受け取っています。
Perlの代入式は左辺値の値が取られるため、これは以下のコードと等価です。( 参考: perlop - Perl の演算子と優先順位 - perldoc.jp )
$! = 24; say $!;
24
を代入したのに文字列が出てきた!?バグか!?と驚くかもしれません。
しかし、これは実はちゃんとPerlのドキュメントに明記されている挙動です。
特殊変数
Perlにおいては $!
のようにシジル($
など)のあとの変数名が記号で始まるものは特殊変数と呼ばれ、処理系によって特殊な扱われ方をする変数になっています。
特定の特殊変数がどのようなものかは perldoc -v '$!'
などとしたりすることで調べられます。
$!
とはなんなのかを調べてみましょう。perldoc.jp でも簡単に調べられます。
Perlの組み込み変数 $! の翻訳 - perldoc.jp
$!
はerrnoを扱うための特殊変数だということがわかります。
こんな記述があります:
参照されると、$! は C の errno 正数変数の現在の値を取得します。 $! に数値が代入されると、その値は errno に補完されます。 文字列として参照されると、$! は errno に対応するシステムエラー 文字列を返します。
つまり、そういう挙動をする特殊変数なので、そうなる。という感じです。
インターフェースに対する考察
でも、「文字列として参照されると」とは、どういうことなのか? なんで、こんな不自然に見えるインターフェースになっているのか?
これにはPerl特有のコンテキストという考え方が関わってきます。
コンテキスト
Perlは文脈的多態言語 (Contextually Polymorphic Language)として作られています。 これは要するに、データ表現を単一のスカラにまとめ、そしてそのスカラを評価した文脈によってデータ表現を変えることによって、同一の概念を1つの変数で簡便に扱うための概念です。
参考資料:
http://perldoc.jp/docs/perl/5.26.1/perldata.pod#Scalar32values https://www.slideshare.net/karupanerura/ss-98704540 https://www.slideshare.net/KondoYoshiyuki/yapc2012-20120929
このコンテキストを実現するための仕組みとして、Perlのスカラ変数は同一の値に対する複数の型のデータ表現を持つSV構造体として表現されます。 具体的にはPV/IV/NVという3つの値をSVに同時に持つことができます。
参考資料:
http://xsubtut.github.io/ https://metacpan.org/pod/B#OVERVIEW-OF-CLASSES
通常はこれらのIV/PVなどには同一のデータを単に型変換したデータが保持されます。
use Devel::Peek; # IVだけを持つSVを作る my $age = 17; Dump $age; # 文字列コンテキストで評価したことによってPV値が求められる print "私は永遠の $age 歳です\n"; # $ageはIVとPVを持つSVに変わる Dump $age;
実行してみるとこのとおりです:
SV = IV(0x7ffe9080dd88) at 0x7ffe9080dd98 REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 17 私は永遠の 17 歳です SV = PVIV(0x7ffe9080b820) at 0x7ffe9080dd98 REFCNT = 1 FLAGS = (PADMY,IOK,POK,pIOK,pPOK) IV = 17 PV = 0x7ffe8f402de0 "17"\0 CUR = 2 LEN = 10
PV値に "17"
という値が増えて、FLAGS
に POK
が増えています。(PVはPointer Valueなのでその名の通り、実際にはその文字列へのポインタです)
内部的にはこのようにして同一の値に対する異なる表現のデータを持ち、コンテキストでその評価を変えるのがPerlのContextually Polymorphic Languageたる世界観なのです。
ソフトウェア工学的に正しいかどうかはさておき、データを直感的に扱うためのアプローチとしてはユニークで面白い概念なのではないかと個人的には思います。
dualvar
さて、これを見た賢い人は「つまり単一のスカラに違うデータを入れることも可能なのでは?」と考えると思います。 まさにそのとおりで、標準モジュールのScalar::Utilにdualvarという機能があります。
https://metacpan.org/pod/Scalar::Util#dualvar
これを使うとこういったことができます:
use Devel::Peek; use Scalar::Util qw/dualvar/; # PVとIVを持つSVをdualvar関数で作る my $age = dualvar 17, 'seventeen'; Dump $age; # 文字列コンテキストで評価したことによってPV値が参照される print "I'm $age years old.\n"; # 数値コンテキストで評価したことによってIV値が参照される print "Next age: ", $age + 1, "\n";
結果としてはこうです:
SV = PVNV(0x7fa429802150) at 0x7fa42981da58 REFCNT = 1 FLAGS = (IOK,POK,IsCOW,pIOK,pPOK) IV = 17 NV = 0 PV = 0x7fa42b200570 "seventeen"\0 CUR = 9 LEN = 11 COW_REFCNT = 1 I'm seventeen years old. Next age: 18
IV/PVに別々の値が入っており、それがそれぞれのコンテキストに応じて使われている事がわかります。
即ち、Perlではerrnoとそのエラーメッセージは表裏一体の同一概念として扱えるべきだと考えて $!
をdualvarのようなスタイルで実装していると考えられます。
ちなみに、一応書いておくと、dualvarを通常のソフトウェア開発で使うべき場面は基本的には存在しないと思います。
$!の正体に迫る
ここまでの知識を前提知識として知っていると $!
はdualvarのようにして実装されているのでは?と想像できると思います。
実際に実行してみましょう:
use Devel::Peek; $! = 24; say $!; Dump $!;
やはりIVにはerrnoが、PVにはそのエラーメッセージが格納されています。
Too many open files SV = PVMG(0x7fb7ce827140) at 0x7fb7ce806ff8 REFCNT = 1 FLAGS = (GMG,SMG,NOK,POK,pNOK,pPOK) IV = 24 NV = 24 PV = 0x7fb7cdc07b00 "Too many open files"\0 CUR = 19 LEN = 21 MAGIC = 0x7fb7cdc08ec0 MG_VIRTUAL = &PL_vtbl_sv MG_TYPE = PERL_MAGIC_sv(\0) MG_OBJ = 0x7fb7ce807058 MG_LEN = 1 MG_PTR = 0x7fb7cdc028d0 "!"
では $!
をsay
の文字列コンテキストで評価する前に参照してみるとどうでしょうか?
use Devel::Peek; $! = 24; Dump $!;
なんとPVは0です:
SV = PVMG(0x7fc936815b40) at 0x7fc93581d9f8 REFCNT = 1 FLAGS = (GMG,SMG,IOK,pIOK) IV = 24 NV = 0 PV = 0 MAGIC = 0x7fc93570a450 MG_VIRTUAL = &PL_vtbl_sv MG_TYPE = PERL_MAGIC_sv(\0) MG_OBJ = 0x7fc93581da58 MG_LEN = 1 MG_PTR = 0x7fc93570a480 "!"
$!
を評価したときに何かが起きて、IVに応じたPVがセットされた。ということがわかります。
これを実行しているのがMAGICと呼ばれる仕組みです。
MAGIC
MAGICは変数の操作に対してフックするための仕組みです。 以下のようなことができます:
関数ポインタ その振る舞い ---------------- ------------ svt_get SV の値が取得された前に何かを行う。 svt_set SV に値を代入した後で何かを行う。 svt_len SV の長さを報告する。 svt_clear SV が表わしているものををクリアする。 svt_free SV に結び付けられてい領域を解放する。 svt_copy tie された変数のマジックを tie された要素にコピーする svt_dup スレッドのクローン化中にマジック構造体を複製する svt_local 'local' 中にマジックをローカル変数にコピーする
出展: https://perldoc.jp/docs/perl/5.20.1/perlguts.pod#Magic32Variables
$!のMAGIC
Devel::Peekによると MG_TYPE = PERL_MAGIC_sv
とあるので先のドキュメントと照らし合わせるとやはり特殊スカラ変数向けのMAGICが内部的に定義されていることが分かります。
mg_type (old-style char and macro) MGVTBL Type of magic -------------------------- ------ ------------- \0 PERL_MAGIC_sv vtbl_sv 特殊スカラ変数
該当箇所のソースを追うと、 mg_vtable.hでこれが定義されており Perl_magic_set
と Perl_magic_get
によって実際の処理が行われていることが分かります。
https://github.com/Perl/perl5/blob/v5.30.0/mg_vtable.h#L191
$! = 24
のように代入されるタイミングで Perl_magic_set
が実行され、 MG_PTR = 0x7fc93570a480 "!"
なので以下の分岐に入ってきます。
https://github.com/Perl/perl5/blob/v5.30.0/mg.c#L3074-L3089
代入元のスカラを数値コンテキストで評価したときと同じ値を、
SETERRNOマクロで一般的な errno.h
の提供するグローバル変数のerrnoにもセットしています。VMSの場合は挙動が少し違うようです。
https://github.com/Perl/perl5/blob/v5.30.0/perl.h#L1330
そして $!
が評価されるタイミングで Perl_magic_get
が実行され、errnoをSVのIVスロットにセットし直して最終的にはstrerror関数によってerrnoのエラーメッセージを取得してPVスロットにセットしています。
https://github.com/Perl/perl5/blob/v5.30.0/mg.c#L1003-L1032 https://github.com/Perl/perl5/blob/v5.30.0/embed.h#L843 https://github.com/Perl/perl5/blob/v5.30.0/mg.c#L883-L897
こうして $!
の挙動がどのように実現されていることが分かりました。
まとめ
$!
はPerlの特殊変数でerrnoを扱います。その挙動はMAGICによって実装されており、dualvarのように振る舞います。
$!
を使うときはコンテキストによって表現を変えるのでコンテキストを適切にコントロールしましょう。
バックアップ用NAS検討
ことのあらまし
バックアップしてたらバックアップ用のHDD飛んだ…
— かるぱねるら (@karupanerura) 2019年5月2日
お亡くなりだー pic.twitter.com/owNsHgCEX6
— かるぱねるら (@karupanerura) 2019年5月2日
なんとか認識まで行ったけどどこに退避しようか… pic.twitter.com/7o8Xbma3DN
— かるぱねるら (@karupanerura) 2019年5月2日
バックアップの救出作業が終わらない
— かるぱねるら (@karupanerura) 2019年5月2日
雑に外付けに逃したら、非同期で差分をDropboxにも上げてくれて、そんで省電力にスタンドアロンで動いてくれる仕組みがほしい
— かるぱねるら (@karupanerura) 2019年5月3日
作るか…ということでおすすめのLinux NASを緩募
— かるぱねるら (@karupanerura) 2019年5月3日
すると有益な情報を友人知人に教えてもらえた。(超感謝) おすすめされたメーカーで分類すると、Synology, ASUSTOR, Drobo, QNAPの4つ。
補足すると、Linux NASがと明言したのはLinuxだったら公式のサポートがなくてもコード書けばどうにでもできるやろ…という希望的観測が持てたからで、要件としてはツイートしたとおり「非同期で差分をDropboxにあげてくれる(Dropboxじゃなくても良い)」「省電力でスタンドアロンで動いてくれる」ということでDropbox同期などの機能があるNASなら問題なかった。というより正直なところ連携をあまり期待していなかったのでこんなにあるのかと驚いた。
(ただ、Linuxだったら色々 いたずら 楽しいことが出来そうという気持ちもあり、Linux basedのほうが気持ちがわくわくしそう。)
また、NAS自作も選択肢にあったが、楽をしたいので出来合いのやつがあればいいなという感じ。
そして、おすすめしてもらったやつはいずれも要件を満たしていた。つまり、迷う。レッツ比較。
Synology
Linuxであるっていうのは何かその上で動かしたいとかあります?
— おっ (@monamomi) 2019年5月3日
現状、SynologyであればCloud Sync、ASUSTORであればDataSyncでDropBoxとの同期処理はしてくれますよ
ちょうど最近Synology DS416Jを2万ちょいで購入して、8TB*2を指して運用始めたんですけど、自由度高い感じで感じでかなりよさげですよ。試してないけどsshやrsyncも普通に出来るっぽいし、dropboxや外付けへの自動バックアップもできるし、ブラウザベースのUIも悪くないし、おすすめです
— I.Nagata (@i110) 2019年5月3日
クラウドストレージ連携
Hyper BackupがDropboxとかへのバックアップ機能らしい。
だいたいの機種が対応しているようだ。
Dropboxに対しては同期も可能なようだ。
省電力性
省電力性はValueシリーズがSpec上は優秀そうに見える。
16.79 W (アクセス)
5.16 W (HDD ハイバネーション)
Plusシリーズもよさそう。
17.23 W (アクセス)
5.4 W (HDD ハイバネーション)
価格
【NASキット】Synology DiskStation DS218play [2ベイ / クアッドコアCPU搭載 / 1GBメモリ搭載] マルチメディアサーバーに最適
- 出版社/メーカー: Synology
- 発売日: 2018/09/01
- メディア: Personal Computers
- この商品を含むブログを見る
3万円弱くらい。
このモデルは CPU: Realtek RTD1296 クアッドコア 1.4 GHz
メモリ: 1 GB DDR4
のようだ。
【NASキット】Synology DiskStation DS218+ [2ベイ / デュアルコアCPU搭載 / 2GBメモリ搭載] オールラウンドストレージソリューション
- 出版社/メーカー: Synology
- 発売日: 2018/09/01
- メディア: Personal Computers
- この商品を含むブログを見る
こっちは3万円台後半で CPU: Intel Celeron J3355 デュアルコア 2.0 burst up to 2.5 GHz
メモリ: 2 GB DDR3L
のようだ。
ASUSTOR
クラウドストレージ連携
Dropbox同期機能があるようだ。
非同期なバックアップはなさそう。(同期でも良いんだけどバックアップとしてはone wayなほうが安心感がある…)
省電力性
省電力性はv2シリーズが優秀そうに見える。
14.1 W(操作)
6.9 W (ディスクのハイバネーション)
消費電力: 14.6W (操作)
8.1W (ディスクのハイバネーション)
0.89W (スリープモード)
価格
ASUATOR NASケース AS10 v2シリーズ 2ベイモデル AS1002T v2
- 出版社/メーカー: ASUSTOR
- 発売日: 2018/07/27
- メディア: Personal Computers
- この商品を含むブログを見る
このモデルは2万円弱で CPU: Marvell ARMADA-385 1.6GHz (Dual-Core) Processor
メモリ: 512MB DDR3
のようだ。
ASUSTOR NASケース 31シリーズ 2ベイモデル AS3102T v2
- 出版社/メーカー: ASUSTOR
- 発売日: 2018/07/27
- メディア: Personal Computers
- この商品を含むブログを見る
このモデルは2万円台後半で CPU: Intel Celeron 1.6GHz Dual-Core (burst up to 2.48GHz) Processor
メモリ: 2GB DDR3L
のようだ。
安い。
Drobo
LinuxらしさはないですがDrobo使ってます
— Hidenori MATSUKI (@mazgi) 2019年5月3日
HDD入れ替えていけば容量増やせるのがメリットです
最近のやつは色々アプリインストールできる模様
ちなみにJP/USで価格差がかなり...😭https://t.co/le5VHrVRsohttps://t.co/XkaUbvtqHW
— Hidenori MATSUKI (@mazgi) 2019年5月3日
HDD入れ替えていけば容量増やせる
ってどういうことだろうと思ったらBayond RAIDという機能があるようだ。
https://ascii.jp/elem/000/001/422/1422949/ascii.jp
クラウドストレージ連携
期待したようなものはなさそう。
SSHできるようだしPerlも動かせそうなのでなんとかしようと思ったら出来そう。
省電力性
Datasheetに載ってたり載ってなかったりする…謎。 製品のウリ的に2 bayみたいな小さいモデルはないようだ。
このモデルにはあった。
https://drobo-wpengine.netdna-ssl.com/downloads/products/04-05-01-b810n-DS.pdf
8 bayで 13W~82W っぽい。
価格
- 出版社/メーカー: Drobo
- メディア: Personal Computers
- この商品を含むブログを見る
5 bayで5万円台といったところか。
QNAP
QNAP普通に便利に使っている。https://t.co/HdKHsVu9tA
— songmu (@songmu) 2019年5月3日
UPSと連動してくれるのはたしかに良さそう。
クラウドストレージ連携
Cloud Drive Syncという機能がそれに当たるっぽい。
省電力性
省電力性はTS-251bが同社の2 bay製品のなかではSpec上は優秀そうに見える。
電力消費量:HDDスリープモード 8.08 W
電力消費量:動作モード、通常時 15.25 W
価格
QNAP (キューナップ) 2ベイ 単体モデル 専用OS QTS搭載 デュアルコア2.0GHz メモリ 2GB TS-251B-2G 【国内正規代理店品】
- 出版社/メーカー: QNAP
- メディア: 付属品
- この商品を含むブログを見る
3万円台後半。
このモデルは CPU: Intel® Celeron® J3355デュアルコア2.0 GHzプロセッサ(最大バースト2.5 GHz)
メモリ: 2 GB SO-DIMM DDR3L(1 x 2 GB)
のようだ。
検討
自分は本ちゃんのバックアップはクラウドに置いて運用したい。うっかりDriveの寿命を迎えたりするリスクがないし、可用性の観点で安心だし、アクセスもしやすいから。 そのための、前段に置くバックアップとアップロードを代わりにやってくれるマイクロホームサーバーとしてNASがほしい。
そういう用途なのでNAS自体の可用性や拡張性は自分にとってはあまり重要ではない。
一方でLinuxで動いていると嬉しいことがいくつかあり、たとえばmackerel-agentでS.M.A.R.Tを監視したりできるので、故障前にアラートで通知してもらったり障害を検知したりできるはずだ。 その点はどれもLinuxベースのようなので良さそう。
性能面も踏まえると、総合的には個人的にQNAP TS-251bかSynology DS218+、AUSUSTOR AS3102T v2が良さそうかなぁ。
追記
Github/Dropboxだけだとダメなの?ってなるけど、コードとかはもちろんGithubにあげてるけど楽曲制作やってるとレコーディングした各楽器の各テイクを96kbps/24bitとかで持っているのでそれなりの容量になってしまう。ときどき録画データとかもあるので、それを保管するのも手間。 Dropboxは普段使いは良いけどselected syncの設定を逐一いじるのが手間だし、アップロード完了まで待たないといけないので、普段使いのノートPCには不向き。Smart Syncも楽曲制作のために確実に容量を空けておきたいとなるとあまり期待できない気がする。 とはいえ、なにかしらのクラウドストレージサービスにアップロードしておきたい。というわけで、NASにコピーさえすればあとはよしなにやってくれるという世界観になるとうれしいとなった。
Dropbox以外はダメなのかというとそんなことはなくて、Dropboxは今自分が年間契約している唯一のクラウドストレージサービスなのでまずはそこにあげようとしているだけで、GCSとかGlacierやGoogle Driveも検討外というわけではなくそのうち別途検討しようと思っている。
Japan Perl Associaton代表理事に就任します
SEE ALSO:
なぜ平成も終わるこのご時世に?と思う方もいらっしゃると思います。 思いの丈を書いてみます。
昨今のWeb開発のトレンドとしては、動的型付け言語から静的型付け言語へシフトが進んでいます。 また、PaaS/SaaS/FaaSの普及により言語選択よりも技術選択とそのアーキテクチャがより重要になってきており、 *1いちプログラミング言語の重要性というものは、(特に動的型付け言語においては)昔ほど重要ではなくなっているのが実情かと思います。
その中でもPerlは、人気度でいえば比較的低い言語といえるでしょう。 LLと呼ばれる言語の中で最低の人気と言っても間違いではないかもしれません。 ひどいときには、1987年に作られたPerlと1959年に作られたCOBOLが並べて語られることすらあります。*2
それでも、ぼくはPerlが好きです。
Perlを支えてきたPerlコミュニティが好きです。
Perlコミュニティが作り上げてきたCPAN Moduleが好きです。
Perlはたぶん知らない人が思ってるよりは、実際はもっと使いやすく、また面白い言語です。 一方で他のプログラミング言語とは考え方が、一見似ているようでまるで違う部分もあります。 たとえば、文脈的多態言語 (contextually polymorphic language) としての特徴は他のプログラミング言語によく慣れた人には奇妙な設計に見えるでしょう。 しかし、この特徴があるお蔭で、一定以上Perlに慣れれば直感的にPerlのコードを書き下すことができます。(詳しくはここでは割愛します)
もちろん、ただ書き下しただけの読みにくいコードがどういう問題を引き起こすかという話はありますが、それは実際には書き下しただけのコードをリファクタリングせずに運用してしまう開発体制の問題であり、Perlに限った話ではなくどの言語でも起こり得るものです。 一方で、そういった問題に苦しめられた結果、Perlを嫌いになってしまったという話も悲しいことによく見ます。
ただ、そういった噂が尾びれをつけて、Perlでコードを書くと汚くなる、Perlでは綺麗なコードは書けない、などとあらぬ誤解が多く広まってしまっている悲しい実情もあります。 綺麗なコードが書けるかどうかは、単にその言語の熟練度とその書き方の問題です。「罠」と言われるものの大半は、言語仕様やその考え方に対しての無知から来ている誤解です。 Perlは正しく理解すれば、とても強力なスクリプト言語になります。
そして、多くのCPANモジュールはPerlでより大規模なサービスを作れるようにしてくれました。 結果として、いまも多くのWebサービスがPerlで支えられています。
しかし、現状は残念ながらその実力が過小評価されてしまっている場面がやはり多いと思います。 ぼくはそんな現状が悲しいのです。
ところで、実用上はどうでしょうか。
実際のところ、まだまだPerlのまま運用されている、そしてまだしばらくはPerlのまま運用しようとしている、そしてそれが収益の柱(の一部)になっているというサービスは無数にあります。 また、IaaS/オンプレミスでの運用もまだまだ少なくはなく、ログをしゅっと集計するスクリプトをさっと書きたいような場面もたくさんあります。
冒頭で述べたようなトレンドの変化に加え、各クラウドベンダーは残念ながらPerlをサポート外にしていることも多く、新規開発でPerlという事例はもうほとんどなくなっていくでしょう。 一方でPerlの利用場面が全くなくなるかというとそんなことはなく、その強力な正規表現エンジンはML学習用データのクリーニングに使えば複雑なケースでもシンプルに問題を解決できるでしょうし、 OSにプリインストールされて互換性の高いスクリプト言語として、ワンライナーや書捨てスクリプトの類ではまだまだ力を発揮することでしょう。もちろんCPANモジュールを使えばもっと高度なこともできます。 当然、延命させてきたPerlのサービスに突然ビジネスチャンスがやってきてすばやく改修を加えたい。となる場面もあるかもしれません。
かくして、まだまだPerlのエンジニアは必要とされており、その一方でPerlのエンジニアの採用に困っているという声もよく聞きます。 決してメジャーラインではありませんが「死んだ」と形容されることが似合うほど落ちてもいないのではないでしょうか。
色々考えた結果、自分にとって大切なものをsortするとやっぱPerlは上位に来るし、ろくに知られもせずに悪名高い感じの評価をされてるのが本当に気に食わないから、なんとかしたいんだよなぁ
— かるぱ@M3 I-05a (@karupanerura) May 17, 2018
そういうわけで、こういう僕のエゴで僕が id:nekokak に代わり代表理事を引き継ぐことにしました。
まだまだ自分は若輩者で、牧さんやねこかくさんほどの働きができるとは思えませんが、そういった気持ちを胸に少しでも現状をよくできたら、Perlコミュニティがもっと楽しい場になると良いなと思っています。 不束者ではございますが、みなさん改めてよろしくおねがいします。
YAPC::Tokyo 2019で話したことの落穂拾い、あるいはISUCON8予選問題出題の感想
話してきた。スライドはこちら。
20分で話せるボリュームにまとめるにはちょっとスコープが広すぎて抽象的かつ割と普通な結論になってしまったなと題材選びに反省がある。 もう少し具体例について堀り下げられる時間がほしかったが、コンテキストなくそこだけ話してもやはり本質的には意味の薄いものになってしまっただろう。 問題を考えるときに、チームとして実際に考えてたことの本質的な部分についてなんとか言語化できたかなーという気がする。 逆に言えばそういう言葉を使って議論してたわけじゃなくて、自然とそういう目的や価値観を議論の中で共有できたからこそ、問題を良い方向にどんどんブラッシュアップできた。といえると思う。(ぼくが勝手にそう思っていただけでなければ…)
基本的にはまとめに書いたとおり、目的ドリブンで価値観を決めて、その価値観をもとに良し悪しを図り、やっていく。を実践した結果としてこういうのが出来たという話をした。 言ってることは当たり前のことになっちゃったけど、なんだかんだ一番重要かつ本質的に一番大事だったのはここで、これをそのまま伝えることにした。
プロポーザルに書いておいて語れなかったことにちょっと触れる。
どのようにしてブラックボックスとなっているアプリケーションが仕様を満たしているかをテストするとよいのか
これは id:sonots さんが主にやっていたことなので本当はインタビューしないといけないんだけど、 基本的には操作による状態の変化をエミュレートして、サービスが返すデータがそれと矛盾していないことをテストしていた。 簡単な具体例をだすと、S席が100席あるときに並列で5人同時に買ったら、残り95席になっているはず、それぞれ別の席が得られているはず、ということを確かめる。
実際はもっと複雑で、タイムアウトがありえる。すると何が難しいかというと、クライアント側からは操作が成功しているか失敗しているかが分からない。 つまり、並列で5人同時に買った操作のうち2件がタイムアウトした場合、残りの座席は95席とは限らないし97席とも限らない。 僕たちはどうしたかというと、許容誤差の範囲を動的に計算して、95席〜97席の範囲に収まっていれば正とするようなチェックをしていた。
また、座席のランダムチェックに関しては、全体でn件以上予約した結果として全体の座席の割り振られた順番が等差数列的になっていないことを確認していた。
こうすることで、単純な ORDER BY RAND()
を ORDER BY id
などに書き換えればFAILさせることができるし、一方でランダムにn個生成した数が等差数列になる確率は許容範囲になるだろうという目論見があった。
n件予約できない場合はもちろんこのチェックは走らないが、このようなことを試すモチベーションは仕様無視して予約処理の高速化を図るチート行為なので、件数が増えたときだけチェックすればよく何ら問題がなかった。
極限までチューニングする上でどのようにプロファイリングするとよいのか
普通にプロファイリングする。のだけど、以下のようなツールを組み合わせてボトルネックを解析してチューニングするのをひたすら繰り返していた。
- Linux
- dstat
- pidstat
- iostat
- netstat
- ss 使うべきなんだろうけどまだ慣れきってない…
- MySQL
- pt-query-digest
- SHOW ENGINE INNODB STATUS
- https://dev.mysql.com/doc/refman/5.6/ja/innodb-information-schema-transactions.html
- Redis
- SLOWLOG GET
- Perl
- Devel::NYTProf
- Devel::KYTProf
- log
- alp
ボトルネックとその原因を明確につかめるまでは多角的に情報を集めて矛盾の無い判断をするように気をつけていたと思う。 あと、PerlのNYTProfはかなり詳細に出せるので、読み方さえ理解すればすごく強力な武器になった。
あとは理屈上このほうが速いんじゃね?というのを適当にいろいろ試したりするのは予想外の結果になったりして面白く純粋に楽しかった。
そのほか
当たり前だけど、完璧な問題が作れたわけじゃない。課題はたくさん残ったまま予選当日を迎えてしまったし、いくつか初期実装の不備も出してしまった。 それらの点に関しては講評でも触れたとおりだけど反省しかないし申し訳ないと思っている。
その一方で、出題した問題そのものの本質的な問いかけに関しては、自分で言うのもなんだが高い評価をもらえたんじゃないかなと思っている。 おこがましいけど過去イチで面白くやりがいのある問題を作り上げてやろうと(勝手に)思っていて、そう思っていた反面ぜんぜん自信がなかったからずっと不安だったけど、良いフィードバックがたくさんもらえたのは本当に嬉しかったし、ひとに会うたびに無限に褒められが発生したので自信につながった。
あとは、ISUCONの作問は業務時間を使ってやっていたんだけど、仕事としてやる以上は成果を残さなきゃいけないというプレッシャーもあった。 ISUCONに関わる上での成果とはなにかって考えると、やはり良い問題を作るというのが本質的なコミュニティへの貢献だし、それこそが会社や自分自身のプレゼンスの向上への最大の近道だと思ってやっていた。逆にいえば、中途半端な成果にはしないという覚悟をしたからこそ「やります」という声を挙げられた。覚悟だいじ。
今年もいろいろ覚悟を決めて良い変化をちょっとずつ起こしていきたい。
追記
落穂拾いをずっと落ち葉拾いって読んでしまってた。おち"ぼ"ひろいなのかー。勉強になった
— かるぱねるら (@karupanerura) January 29, 2019
落ち穂拾い != 落ち葉拾い。覚えた。
ところでこれ送り仮名つけるのとつけないのどっちが正しいの?