6時28分、日の出だよ。朝が来たことをお知らせするよ。
— にちぼついったー (@nichibotwit) February 14, 2014
久しぶりにまともなコードを書いたので,ちょっと作業内容などを記録しておこうかなと思いました。
旧バージョンは 2009 年の秋頃に作成・リリースしていました。ちょうど Moose を使いたくて仕方ない頃だったらしく MooseX::App::Cmd という Moose ベースでコマンドラインツールを書くためのフレームワークを使って書いていました。
"set" コマンドを AM 1:00 に実行し,その日の日の出・日の入りの時間を調べて Cron 書き換え,そしてその時間に "tweet" コマンドが起動してつぶやくというイケてない実装でした。もともとは at
で実行時間をセットするように書いていたものの,実際にデプロイした VPS で at
を使えないというトラブルのためリリース前に cron を使う方式に書き直した経緯があります。
この旧 bot には致命的な欠点が 2 つありました。
結果的にメタデータの更新を忘れてしまったことや,別サーバに移したときに cron 書き換えをしたくないために止めてしまっていました。
そこで,欠点それぞれに対しての解決策を考えてにちぼくんを再実装しました。
Astro::Sunrise は緯度・経度を基にその場所の日の出・日の入り時刻を計算してくれるモジュールです。
使い方もとてもシンプル。
1 2 3 4 5 6 |
|
結果はそれぞれ "hh:mm" という文字列で返ってくるので,split して時と分に分けるなり,再度オブジェクトにするなり自由に加工できます。
毎回計算することでメタデータを利用する必要がなくなりました。弊害としては,計算方式の違いで国立天文台のこよみと少し違う時間となるケースが起きてしまいました。しかし,ずれていても 1 分程度なので,今回のサービス的には許容できる誤差と考えています。
AnyEvent は定番過ぎるので,紹介については割愛します。一日 2 回しかつぶやかないのでループにしておくのは勿体ないようにも思えましたが,毎回つぶやくタイミングが違うことに対する解決策が思い浮かばなかったためこうなりました。。
せっかく Astro::Sunrise で動的に計算できるようにしたので,今後は mention を受けて東京以外の場所や別の日の計算もしてくれるようにしたいですね!
それ以前にコード内に consumer_key や access_token を直接書いてしまっているので,このあたりの設定切り出しはしておきたいです。
選挙速報を見ながら書いていたのですが、ぎりぎりになったところで子供に泣かれてあやしていたら日付を超えてしまいましたすみません。。。 様々な政策が再び大きく変わりそうですが、子育て支援をはじめとして親としては気になる内容も多いので見守りつつ書いています。
今年の1月に子供が産まれました。
生活は大きく変わりました。
例えばおでかけの時。妻と2人で散歩してるときはあまり気にせず公園の中も自由に歩けていましたが、ベビーカーを使っていると特定のスロープを通るルートしか選べなかったり。出かける先も授乳室やおむつ替えスペースがありそうなところであったり、食事をするのも子供連れでも利用できるレストランを探したり。帰ってくるのも遅くなりすぎない時間に戻れるようなスケジュール(しかも、30分程度はバッファを見た上で)をなんとなく考えるようになりました。
そういう意味では、視点も大きく変わったのかなと思います。
買い物も大きく変わった一つかと思います。
妊娠中、重い買い物をしなくても良いようにと個人宅配に加入したのですが、これはとても良い選択でした。休みの日に家族 3 人で買い物にでかけるのは良いのですが、子供をだっこして重い買い物袋をいくつも持ってくるのは大変です。もちろん、平日に妻が子供と2人で毎日買い物に行くことはもっと大変です。 そこで、お米やたまご、常備菜などの重かったり運びにくい食材は宅配にお願いして、必要なものを都度、私が帰りがけに買って帰るなどの運用になりました。宅配の商品は店頭より高かったり、半月ほど前には注文を提出する必要があったりすることもありますが、持ち帰る手間や届く品物の質を考えれば良いかなと考えるようになりました。
また、生活雑貨ではネット通販に大変お世話になっています。中でも一番お世話になっているのは Amazon です。取扱品が多くて探しやすく、店頭価格と比べても変わりない(場合によっては店頭より安いこともある)ので、おむつなどかさばる商品はとても便利です。
ちなみに、最近は “Amazon ファミリー” というパパ・ママ向けのサービスをしています。初回登録時のクーポンや Amazon プライム無料お試しなど、特典が魅力的なのでおすすめです。
あとは、周りのお父さんが口を揃えていうことですが、本当に時間がないです。覚悟していた以上でした。 起きているときは一緒に遊んだり見守ったりしますし、寝てるときも突然夜泣きしたり寝ぼけて起き上がったりします。そもそもすんなり寝付いてくれません。寝不足にもなりますし、イライラしてしまうこともあります。 この問題については、未だに試行錯誤の毎日です。どうやって時間を作り、効率良く自分の時間を使い、満足するか。子供と一緒に成長していくしかないのかなと思ったりしています。
子供ができて、考えるようになったことも多くあります。
なによりも、妻への感謝でした。 育児休業で自宅にずっといるのですが、それでも掃除や洗濯・炊事などをしながら子供の面倒を見てくれているわけで、平日に関してはかなりの負担をかけてしまっています。平日はできるだけ早く帰って妻の話を聞いてあげる時間をとったり、休日は家族で気分転換になるよう出かけたりと努力してみましたが、それでもまだ足りないかなと思っています。 子供にとってのお母さんは、お父さんが代わりになることはできないほどの存在に見えます。眠いとき・不安な時などはお母さんにだっこされて授乳しないと落ち着かなかったりします。 それほどに大事な存在だからこそ、適度にリフレッシュしながら毎日楽しく育児をして欲しいと思うわけです。妻はしっかりしている人なので産まれる前は大丈夫かなと思っていたのですが、実際に産まれてから半年くらいするとかなり精神的に参ってきていたようです。時々実家に帰省したり、旅行にいったりしたのは気分転換にはなったようです。 家族として、夫として、妻や子供を支えられるようにならなければと強く思うようになりました。
次に、仕事のことでした。 偶然にも、今年の始めに私の職務内容が変わるチャンスがあり、昨年のような深夜作業・障害対応がメインの仕事ではなくなりました。家庭の生活リズムがつかみにくい時期に仕事のリズムが調整可能であったことはとても運の良いことでした。 一方で、生活の中でしめる仕事の割合の大きさにも気づかされました。時間はもちろん、仕事に関連した生活リズムや夜中のアラートなど、妻だけであれば説明して我慢してもらえるものでも子供の場合は異なってくることもあります。自分の仕事や年齢、家族との生活とのバランスなどを立ち返って考えるきっかけにはなりました。
今後も子供・家族との時間を大事にできるエンジニアを目指して成長したいと思います。
子供を見ていると、その好奇心の旺盛さと成長の早さにはかなり刺激を受けます。大人が見過ごしてしまうようなものを見つけたり、昨日できなかったことが今日できるようになっていたり。負けじと親も成長しなきゃ、と焦ってしまうことも。 でも、焦りすぎてもダメなんだと思います。離乳食を始めても、いろんな食材を一つずつ、少量から試していってアレルギー反応が出ないことを確認していくのです。そうして積み重ねていけば、大きくなったらいろいろ食べられるようになるのです。
着実に成長を重ねていって、いつか親子でペアプロするような機会があればいいなと思います。 そうそう、この github のロンパース が結構かわいいです。親が好きな服を着せられるのも今のうちかなと思って買ってしまいました。
あまりエンジニア的な話ができずすみません。でも、同じような立場で子育てをされている方の話を聞いてみたい、といつも思っていたので、このような企画に参加できてとてもよかったです。企画してくださった @choplin さんに感謝いたします。
]]>RaspberryPi は、ARMCore プロセッサ搭載の小型基板です。もともと発売開始の頃に買おうとしていたのですが、ただでさえ発送までの時間がかかる上に、販売代理店のサイトで購入中にエラーになってしまってそのままあきらめていたのでした。 ところが、先日 この記事 を見て思い出したので、買ってみたわけでした。
イギリスからの発送なのでそれなりに時間がかかりますが、それでも元々の代理店よりはかなり早いと思います。値段は £29.99 + £4.99 (送料) の計 £34.98。日本円換算で 4,500 円程度です。
ModMyPi は RaspberryPi 専用のカスタムケースなどを取り扱うネットショップです。今回は本体セットを購入したので、本体ボードとケースが送られてきます。が、組み立てというほどではなく載せてはめれば完了です。上下で色を選べるので、上を白、下を青にしてみました。
iPhone と比べると大きさは同じくらいですが、厚さが3倍くらいあります。
あとは OS イメージを書き込んだ SD カードをスロットにいれ、LAN と電源を接続すれば準備完了です。
RaspberryPi の公式から OS イメージがダウンロードできます。展開すると 2GB くらいになるので、利用する SD カードは 4GB 以上が推奨されています。今回は手元に余ってた Transcend の SDHC 16GB (Class10) を用意しました。
大容量の SDHC も昔に比べれば値段が安くなっているのでいいですね。
イメージはいくつか種類がありますが、今回はシンプルな ArchLinux を使うことにしました。 SD カードをマウントして書き込めばいいのですが、スクリプトを利用します。Github で公開されているのですが、残念なことに直さないと動きません。 オリジナルのブランチにもいろんな方から PullRequest があるのですが、反映されてない (しかも多すぎてどれが正しいのか分からない) ので、やむを得ず動く状態に直したものを用意しました。
コロンが抜けてるところと、インデントのおかしな所を直しただけのバージョンです。MacOSX 10.8.2 の python で動作しました。
ローカルに取得した後、スクリプトを起動してウィザードに沿って SD カードへの展開を進めます。mac の SD カードスロットに差し込み、スクリプトを sudo で実行します。
$ sudo ./raspiwrite.py
これでイメージ完成です。簡単ですね。 スクリプトに sudo が必要なのはマウント周りの操作を行うためかと思いますが、複数ディスクがある場合などは全部フォーマットされてしまう可能性もあるので十分に注意が必要です。
できあがった SD カードを入れ、LAN ケーブルを挿し、電源を挿します。スイッチはないので、電源をつないだら基板の LED がひかり、10秒ほどで起動します。デフォルトは DHCP 取得になっているので、ルータ等で割り当て IP を調べて ssh するのがよさそうです。
[root@alarmpi ~]# pacman -Sy
[root@alarmpi ~]# pacman -Syu
[root@alarmpi ~]# uname -a
Linux alarmpi 3.2.27-5-ARCH+ #1 PREEMPT Fri Sep 14 13:23:44 UTC 2012 armv6l GNU/Linux
[root@alarmpi ~]# df -hT
Filesystem Type Size Used Avail Use% Mounted on
rootfs rootfs 1.8G 523M 1.2G 32% /
/dev/root ext4 1.8G 523M 1.2G 32% /
devtmpfs devtmpfs 92M 0 92M 0% /dev
tmpfs tmpfs 92M 0 92M 0% /dev/shm
tmpfs tmpfs 92M 304K 92M 1% /run
tmpfs tmpfs 92M 0 92M 0% /sys/fs/cgroup
tmpfs tmpfs 92M 0 92M 0% /tmp
/dev/mmcblk0p1 vfat 94M 21M 74M 22% /boot
[root@alarmpi ~]# free
total used free shared buffers cached
Mem: 446888 48856 398032 0 9268 20624 -/+
buffers/cache: 18964 427924
Swap: 0 0 0
[root@alarmpi ~]# ps auxf
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 2 0.0 0.0 0 0 ? S 16:47 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S 16:47 0:00 _ [ksoftirqd/0]
root 5 0.0 0.0 0 0 ? S 16:47 0:00 _ [kworker/u:0]
root 6 0.0 0.0 0 0 ? S< 16:47 0:00 _ [cpuset]
root 7 0.0 0.0 0 0 ? S< 16:47 0:00 _ [khelper]
root 8 0.0 0.0 0 0 ? S 16:47 0:00 _ [kdevtmpfs]
root 9 0.0 0.0 0 0 ? S< 16:47 0:00 _ [netns]
root 10 0.0 0.0 0 0 ? S 16:47 0:00 _ [sync_supers]
root 11 0.0 0.0 0 0 ? S 16:47 0:00 _ [bdi-default]
root 12 0.0 0.0 0 0 ? S< 16:47 0:00 _ [kblockd]
root 13 0.0 0.0 0 0 ? S 16:47 0:00 _ [khubd]
root 14 0.0 0.0 0 0 ? S< 16:47 0:00 _ [rpciod]
root 15 0.0 0.0 0 0 ? S 16:47 0:00 _ [kworker/0:1]
root 16 0.0 0.0 0 0 ? S 16:47 0:00 _ [khungtaskd]
root 17 0.0 0.0 0 0 ? S 16:47 0:02 _ [kswapd0]
root 18 0.0 0.0 0 0 ? S 16:47 0:00 _ [fsnotify_mark]
root 19 0.0 0.0 0 0 ? S< 16:47 0:00 _ [nfsiod]
root 20 0.0 0.0 0 0 ? S< 16:47 0:00 _ [crypto]
root 30 0.0 0.0 0 0 ? S< 16:47 0:00 _ [kthrotld]
root 31 0.0 0.0 0 0 ? S< 16:47 0:00 _ [VCHIQ-0]
root 32 0.0 0.0 0 0 ? S< 16:47 0:00 _ [VCHIQr-0]
root 33 0.0 0.0 0 0 ? S< 16:47 0:00 _ [dwc_otg]
root 34 0.0 0.0 0 0 ? S< 16:47 0:00 _ [DWC Notificatio]
root 35 0.0 0.0 0 0 ? S 16:47 0:00 _ [kworker/u:1]
root 36 2.6 0.0 0 0 ? S 16:47 1:59 _ [mmcqd/0]
root 37 0.0 0.0 0 0 ? S 16:47 0:01 _ [jbd2/mmcblk0p2-]
root 38 0.0 0.0 0 0 ? S< 16:47 0:00 _ [ext4-dio-unwrit]
root 82 0.0 0.0 0 0 ? S< 16:47 0:00 _ [bcm2708_spi.0]
root 384 0.0 0.0 0 0 ? S 17:23 0:00 _ [kworker/0:2]
root 28528 0.0 0.0 0 0 ? S 17:54 0:00 _ [flush-179:0]
root 1 0.0 1.2 4596 2396 ? Ss 16:47 0:01 /usr/lib/systemd/systemd --system --deserialize 28
root 46 0.0 0.6 3736 1208 ? Ss 16:47 0:00 /usr/lib/systemd/systemd-udevd
root 50 0.0 1.0 5208 1996 ? Ss 16:47 0:00 /usr/lib/systemd/systemd-journald
root 95 0.0 0.6 2772 1200 ? Ss 16:47 0:00 /usr/sbin/crond -n
root 97 0.0 1.1 6248 2160 ? Ss 16:47 0:00 /usr/sbin/sshd -D
root 163 0.0 1.6 9968 3140 ? Ss 16:49 0:02 _ sshd: root@pts/0
root 165 0.0 0.9 3272 1744 pts/0 Ss 16:49 0:00 _ -bash
root 28579 0.0 0.5 2648 944 pts/0 R+ 18:03 0:00 _ ps auxf dbus 99 0.0 0.7 2808 1396 ? Ss 16:47 0:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
root 106 0.0 0.3 1752 676 tty1 Ss+ 16:47 0:00 /sbin/agetty --noclear tty1 38400
root 144 0.0 0.2 1928 516 ? Ss 16:47 0:00 /sbin/dhcpcd -A -q -w eth0 ntp 146 0.0 0.4 3508 792 ? S 16:47 0:00 /usr/sbin/ntpd -s
root 147 0.0 0.3 3676 572 ? Ss 16:47 0:00 /usr/sbin/ntpd -s
root 319 0.0 0.6 2996 1240 ? Ss 17:00 0:00 /usr/lib/systemd/systemd-logind
root 385 0.0 1.5 7076 2900 ? Ss 17:23 0:00 /usr/sbin/syslog-ng -F
起動するとこんな感じです。ひとまず pacman でパッケージをアップデートしてあげたら、あとは好みに環境構築すればいいです。 うまく動かなくなったら、また SD カードを作り直せばいいですよね。
[root@alarmpi ~]# cat /proc/meminfo
MemTotal: 446888 kB
MemFree: 397924 kB
Buffers: 9300 kB
Cached: 20624 kB
SwapCached: 0 kB
Active: 16772 kB
Inactive: 17684 kB
Active(anon): 4564 kB
Inactive(anon): 168 kB
Active(file): 12208 kB
Inactive(file): 17516 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 1048572 kB
SwapFree: 1048572 kB
Dirty: 12 kB
Writeback: 0 kB
AnonPages: 4528 kB
Mapped: 7264 kB
Shmem: 208 kB
Slab: 11436 kB
SReclaimable: 8652 kB
SUnreclaim: 2784 kB
KernelStack: 384 kB
PageTables: 360 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 1272016 kB
Committed_AS: 12868 kB
VmallocTotal: 188416 kB
VmallocUsed: 1004 kB
VmallocChunk: 186592 kB
[root@alarmpi ~]# cat /proc/cpuinfo
Processor : ARMv6-compatible processor rev 7 (v6l)
BogoMIPS : 697.95
Features : swp half thumb fastmult vfp edsp java tls
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xb76
CPU revision : 7
Hardware : BCM2708
Revision : 000f
Serial : xxxxxxxxxxxxxxxx
とても手軽です。類似のものとしては Openblocks がありますが、桁一つ違うのは大きいですね。 Openblocks が一般的なサーバ機器で、RaspberryPi がパソコンくらいのイメージでしょうか。
2.4 以前の config では deprecated になっている設定項目があるため、一部手を入れる必要があります。mac で launchctl を使っている場合、自動起動に失敗していても気づきにくいので注意が必要です。
$ redis-server /usr/local/etc/redis.conf
*** FATAL CONFIG FILE ERROR
*** Reading the configuration file, at line 389
>>> 'vm-enabled no' Bad directive or wrong number of arguments
Virtual Memory (仮想メモリ) の設定は非サポートになっているので、丸ごと削除してしまいます。
An overview of new features and changes in Redis 2.6.x
======================================================
...
* Virtual Memory removed (was deprecated in 2.4)
...
2.4 以降で depricated になっている下記のプロパティが対象のようです。
$ redis-server /usr/local/etc/redis.conf
*** FATAL CONFIG FILE ERROR
*** Reading the configuration file, at line 367
>>> 'hash-max-zipmap-entries 512' Bad directive or wrong number of arguments
2つの設定の設定項目の名称が変更になっています。
Migrating from 2.4 to 2.6
=========================
...
The following redis.conf and CONFIG GET / SET parameters changed:
* hash-max-zipmap-entries, now replaced by hash-max-ziplist-entries
* hash-max-zipmap-value, now replaced by hash-max-ziplist-value
...
リリースノートを参考にリネームします。
mroonga で TokenMecab トークナイザーを利用するためには MeCab が必要です。 Homebrew で IPA 辞書と合わせてインストールします。
$ brew install mecab mecab-ipadic
$ mecab -D
filename: /usr/local/Cellar/mecab/0.994/lib/mecab/dic/ipadic/sys.dic
version: 102
charset: utf8
type: 0
size: 392126
left size: 1316
right size: 1316
$ mecab 今日は雨です
今日 名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
雨 名詞,一般,*,*,*,*,雨,アメ,アメ
です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
EOS
brew で mecab-ipadic 入れるとデフォルトで UTF-8 になるようになっています。mecab コマンドでインタラクティブに形態素解析してみて、文字化けせずに出力されれば問題なしです。
もし、文字化けしてる場合は Homebrew 周りのどこかに問題があります。brew doctor などで調べていきます。
$ brew unlink mecab mecab-ipadic
$ brew uninstall mecab mecab-ipadic
$ brew doctor
私の場合、10.8 にアップデートする以前に Homebrew で入れた libiconv が中途半端に残ってたことでおかしくなっていたようでした。
MeCab の次は groonga をインストールします。
$ brew install groonga
$ groonga --version
groonga 2.0.7 [darwin12.2.0,x86_64,utf8,match-escalation-threshold=0,nfkc,msgpack,zlib,lzo,kqueue]
configure options: < '--prefix=/usr/local/Cellar/groonga/2.0.7' '--with-zlib' 'CC=cc' 'CXX=c++' 'PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/share/pkgconfig:/usr/local/Library/Homebrew/pkgconfig'>
インストール後にチェックをして、TokenMecab が使えるか確認します。 mecab と書かれていない場合は使えません。groonga の configure オプションでは mecab はデフォルト有効と書かれており、mecab-config を自動で探してくれることになっているのですが、パスが通ってないなどがあるのかもしれません。 直接 brew edit で Fomula を書き換えて再度インストールしてしまいます。
diff --git a/Library/Formula/groonga.rb b/Library/Formula/groonga.rb
index 1c4e8cf..45a7a2b 100644
--- a/Library/Formula/groonga.rb
+++ b/Library/Formula/groonga.rb
@@ -8,9 +8,11 @@
depends_on 'pkg-config' => :build
depends_on 'pcre'
depends_on 'msgpack'
+ depends_on 'mecab'
+ depends_on 'mecab-ipadic'
def install
- system "./configure", "--prefix=#{prefix}", "--with-zlib"
+ system "./configure", "--prefix=#{prefix}", "--with-zlib", "-with-mecab", "-with-mecab-config=/usr/local/bin/mecab-config"
system "make install"
end
end
これでOK。
$ brew install groonga
$ groonga --version
groonga 2.0.7 [darwin12.2.0,x86_64,utf8,match-escalation-threshold=0,nfkc,mecab,msgpack,zlib,lzo,kqueue]
configure options: < '--prefix=/usr/local/Cellar/groonga/2.0.7' '--with-zlib' '--with-mecab' '--with-mecab-config=/usr/local/bin/mecab-config' 'CC=cc' 'CXX=c++' 'PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/share/pkgconfig:/usr/local/Library/Homebrew/pkgconfig'>
次は mroonga をインストールします。Homebrew には内包されていませんが、mroonga のリポジトリに Fomula があるのでこちらを使います。
$ brew install https://raw.github.com/mroonga/Homebrew/master/mroonga.rb --use-Homebrew-mysql
もし、MySQL を Homebrew で入れていない場合 (オフィシャルバイナリを利用している場合など) は、同一バージョンのソースを別途ダウンロードして引数に渡します。また、パーミッションの関係で最後の make install で失敗するので、plugin ディレクトリの所有グループを変更してパーミッションも変えておきます。
$ sudo chgrp staff /usr/local/mysql/lib/plugin
$ sudo chmod g+w /usr/local/mysql/lib/plugin
$ brew install https://raw.github.com/mroonga/Homebrew/master/mroonga.rb --with-mysql-source=/usr/local/src/mysql-5.5.28 --with-mysql-config=/usr/local/mysql/bin/mysql_config
嵌まりながら MySQL を Homebrew 管理とオフィシャルバイナリの両方で試してみたのですが、基本的には Homebrew で揃えた方が便利かなと思いました。
オフィシャルバイナリの特徴をまとめてみるとこんな感じです。
個人的には、複数のユーザで利用している mac でユーザ共通に自動起動させたい(もしくはどうしてもオフィシャルバイナリを使いたい)という条件でなければ Homebrew で良いのかなと思いました。
MySQL Server が起動していれば、mroonga の Fomula の中でプラグインと関数の追加も行われています。停止していた場合は起動後に追加のコマンドを入力します。
$ mysql -uroot -e 'INSTALL PLUGIN mroonga SONAME "ha_mroonga.so"; CREATE FUNCTION last_insert_grn_id RETURNS INTEGER SONAME "ha_mroonga.so"; CREATE FUNCTION mroonga_snippet RETURNS STRING SONAME "ha_mroonga.so";'
これで mroonga ストレージエンジンが使えるようになります。
root@localhost[test]> SHOW ENGINES;
+-------+---+----------------------+-----+--+----+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+-------+---+----------------------+-----+--+----+
| FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
| MyISAM | YES | MyISAM storage engine | NO | NO | NO |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO |
| CSV | YES | CSV storage engine | NO | NO | NO |
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
| mroonga | YES | CJK-ready fulltext search, column store | NO | NO | NO |
| InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO |
| ARCHIVE | YES | Archive storage engine | NO | NO | NO |
+-------+---+----------------------+-----+--+----+
10 rows in set (0.01 sec)
root@localhost[test]> SHOW PLUGINS;
+---------+----+-------+-----+---+
| Name | Status | Type | Library | License |
+---------+----+-------+-----+---+
| binlog | ACTIVE | STORAGE ENGINE | NULL | GPL |
| mysql_native_password | ACTIVE | AUTHENTICATION | NULL | GPL |
| mysql_old_password | ACTIVE | AUTHENTICATION | NULL | GPL |
| CSV | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MEMORY | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MyISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MRG_MYISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
| ARCHIVE | ACTIVE | STORAGE ENGINE | NULL | GPL |
| BLACKHOLE | ACTIVE | STORAGE ENGINE | NULL | GPL |
| FEDERATED | DISABLED | STORAGE ENGINE | NULL | GPL |
| InnoDB | ACTIVE | STORAGE ENGINE | NULL | GPL |
| INNODB_TRX | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_LOCKS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_LOCK_WAITS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMP | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMP_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMPMEM | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_CMPMEM_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_BUFFER_PAGE | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_BUFFER_PAGE_LRU | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INNODB_BUFFER_POOL_STATS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| PERFORMANCE_SCHEMA | ACTIVE | STORAGE ENGINE | NULL | GPL |
| partition | ACTIVE | STORAGE ENGINE | NULL | GPL |
| mroonga | ACTIVE | STORAGE ENGINE | ha_mroonga.so | GPL |
+---------+----+-------+-----+---+
24 rows in set (0.01 sec)
root@localhost[test]> CREATE TABLE diaries (
-> id INT PRIMARY KEY AUTO_INCREMENT,
-> content VARCHAR(255),
-> FULLTEXT INDEX (content) COMMENT 'PARSER "TokenMecab"'
-> ) ENGINE = mroonga COMMENT = 'engine "innodb"' DEFAULT CHARSET utf8;
Query OK, 0 rows affected (0.50 sec)
root@localhost[test]> SHOW CREATE TABLE diaries;
+---+--------------------------------------------------------------------------------------+
| Table | Create Table |
+---+--------------------------------------------------------------------------------------+
| diaries | CREATE TABLE `diaries` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`content` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
FULLTEXT KEY `content` (`content`) COMMENT 'PARSER "TokenMecab"'
) ENGINE=mroonga DEFAULT CHARSET=utf8 COMMENT='engine "innodb"' |
+---+--------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
warning がでなければ問題なく動作しています。念のため mysql.err や groonga.log といったログにも目を通しておきます。
これで mroonga が使えるようになりました。使ってみた印象としては、文節を考慮してくれる高速な LIKE というイメージです。ちょっとした全文検索であれば、手軽に使えるレベルで良いかと思いました。
]]>YAPC の懇親会での話がきっかけで @riywo さんに企画していただいたイベントでした。趣旨としては、既成のツールに焦点を絞るのではなく、サーバを効率的(かつ、可能であれば統一的)に管理するにはどうすればいいかというざっくりとした情報交換の場だったのですが、各社の苦悩が感じられてとても面白いものでした。
そのあと、ちょっと自分なりに考えてみたので覚え書きしてみます。
今回の話を踏まえると、最初に考えなければならないのは大きく2つの点だと思います。 (解釈間違えなどあればご指摘ください。。)
サーバ管理といっても様々な管理があります。
このほかにも、オンプレミス/クラウド(VM含)やスペック毎/役割毎など、いろんな分類基準があるわけです。全てをカバーするのも一つの選択肢ですが、ここは目的から軸となる区分を明確化しておく必要がありそうです。 @kentaro さんがおっしゃられていたように、まさに利用シーンの現状や想定を整理した上で、実際どのあたりを吸収するか考える必要があるのだろうと思います。
@riywo さんのアイディアでは、既存ツールのデータを活かすために Core が欲しいデータを持っている各ツールに問い合わせて返ってきた情報を集約する形になっています。 一方で、@kuwa_tw さんからの意見で全部まとめた箱としてしまうというアイディアもあり、これもありだと思います。
それぞれのメリットを考えてみます。
これは現状の利用状況に依るのかも知れないですね。ツールがどの程度(種類・頻度)利用されていて移行のコストがどれくらいかかるのか、あるいは部署を横断的にまとめていくことが社内政治的に可能なのかどうか、そもそも現状のデータをどれくらい Core が吸収できるのか、といったあたりが焦点になる気がします。
私自身の利用経験や環境から考えると、集約してしまう方式が敷居は低そうかなと感じました。連携のために既存ツールに手を入れなければならないのは導入コストとして高くつくかなと。(でも、結局はバランスを見てのハイブリッドになりそう。。)
自分なりにちょっとずつ整理しながら、ひとまずはシンプルなモックを作ってみようかなと思っています。
次回、が行えるようであればさらに掘り下げて、少しでもインフラ担当者が楽になれると幸せですね。 あと、Web サービス事業者だけに限らず、ホスティングなどでまとまった台数を管理していそうな DC 事業者さんとかの話も伺ってみたいと思いました。
]]>
諸般の事情でまだサービスリリースがされていないこともあり、かなり概説的な内容となっています。このような場でトークさせていただくのは MySQL Casual に続いて2度目だったのですが、内容が少し分散してしまいまとまりのない感じになってしまったところが反省でした。
YAPC でのスピーカーは一つの目標でした。
はじめて Perl-CGI に触れたのは高校生の頃でした。当時はアクセスカウンタや掲示板のスクリプトでしたが、”プログラムがホームページで動く” ということ自体にわくわくしながら見よう見まねでいじってました。大学でもデータ解析やサーバ管理など、何かプログラムを書くときには Perl を使っていました。
その後、社会に出てから改めてオブジェクト指向やモダンな Perl を学びました。サーバ管理などの小さなスクリプトからWebサービスまで、業務で利用してきた期間も5年近くになります。私にとっての Perl はこれまで一番お世話になっているプログラム言語であり、今エンジニアとして仕事をしているのも Perl のおかげだと思っています。
昨年の YAPC::Asia Tokyo 2011 で @lestrrat さんや @941 さんが「来年はないかも知れない」という話をされていたこともあり、開催告知がされた時に応募しようと思っていました。お世話になった Perl を盛り上げたい、何か恩返しにでもなればという思いからでした。
このような思いを踏まえてうまく伝えられなかったなと反省しているのですが、拙い発表を聞いていただいた方の中に一人でも何か新しいこと・今までと違う視点に気づいていただけたならそれで良いのだと自分に言い聞かせています。
年に一度のお祭りですが、参加するたびに自分が Perl を取り巻く文化に魅了されていることに気づかされます。 様々なトークがあり、いろんな視点での意見が交わされているのはとても刺激になりますし、テンションも上がります。この勢いでサービスもうまく形にして、同時に自分自身についてもしっかりと考えていきたいと思いました。
他のトークに優先して聞きに来てくださったみなさま、素敵なカンファレンスを運営してくださっている JPA とスタッフのみなさま、そして多くのスポンサーのみなさま、ありがとうございました!
]]>Redis を使った処理のテストを書く必要があり、これと同じような方法で立ち上げる設定を作ろうとしました。 デフォルトとは異なるポートで Redis のサーバを立ち上げてあげればいいのですが、redis-server コマンドは起動時の引数で直接ポート指定ができず設定ファイルとして渡す必要があります。ちょっと面倒だな、と思って手抜きをしようと探したところ、p5-Redis のテストコードの中に目的のものを見つけました。
このモジュールを use して、テスト開始時に呼び出して Redis のデーモンを起動、テスト終了後にデーモンを終了してあげればよさそうです。 フレームワークとして Amon2 を使っていたので、t::Util のようなモジュールを作って必要なテストで use してあげるような仕組みでやってみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
$ENV{TEST_REDIS} に格納されるのは “127.0.0.1:11121″ のような接続先アドレスなので、Redis への接続時に使われるように設定しました。
config はこんな感じ。
1 2 3 4 5 6 |
|
コンストラクタはこんな感じ。(Teng とかとほぼ同じですが。。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
これで無事、テストを走らせるときに一緒に Redis が立ち上がるようになりました。
1 2 3 4 5 6 7 8 9 10 11 12 |
|
めでたしめでたし。
と思ったら、ちゃんと Test::RedisServer というモジュールがつくられていました。
こちらだと Test::mysqld と同じように書けるのですっきりして見やすそうです。typester++
]]>今回構築しようと思う構成は次の通りです。
スーパーサーバーSupervisorの導入手順メモ – Glide Note – グライドノート を参考に supervisord を導入します。
今回は CentOS 6 系のサーバで system python に pip 経由でインストールします。 pythonbrew などを利用してシステムと切り離すことも検討したのですが、supervisord を使う目的が OS とアプリの間でプロセス管理をすることなので system python で問題ないと考えました。
# setuptools + pip + supervisord のインストール
sudo yum install python-setuptools
sudo easy_install pip
sudo pip install supervisord
# ログ保存用ディレクトリ作成
sudo mkdir /var/log/supervisord/
# 個別設定を格納するディレクトリを作成
sudo mkdir /etc/supervisord.d/
# ベースとなる conf を生成
sudo su - root -c "echo_supervisord_conf > /etc/supervisord.conf"
supervisord.conf も前述の記事とほぼ同じですが、umask を CentOS 風にしたいために 002 にしています。
そして、下記のような /etc/init/supervisord.conf を作成した後に initctl start supervisord
で起動します。
description "supervisord"
start on runlevel [2345]
stop on runlevel [!2345]
respawn exec /usr/bin/supervisord -n
supervisord のプロセスが正常に起動していて、ログファイル (/var/log/supervisord/supervisord.log) に正常に出力されていれば OK です。
PSGI アプリを supervisord で管理するための設定を用意します。 ここで、環境変数が必要となるのでコマンドラインで調べておきます。
まずは、carton 利用時の perl のサーチパス (@INC) を調べておきます。
$ carton exec -I./lib/ -- perl -e "print join(q/:/,@INC)"
./lib/:local/lib/perl5/x86_64-linux:local/lib/perl5:.:/home/hatak/perl5/perlbrew/perls/perl-5.16.0/lib/5.16.0:/home/hatak/perl5/perlbrew/perls/perl-5.16.0/lib/5.16.0/x86_64-linux
同様に、今度は $PATH を調べておきます。
$ carton exec -I./lib/ -- echo $PATH
/home/hatak/.perlbrew/libs/perl-5.16.0@carton/bin:/home/hatak/perl5/perlbrew/bin:/home/hatak/perl5/perlbrew/perls/perl-5.16.0/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/hatak/bin:/home/hatak/bin
これらの環境変数を使って、/etc/supervisord.d/sample.ini という設定を書いていきます。 $PATH に加えて、@INC の中身を $PERL5LIB として設定し、直接 supervisord が server_start するようにします。 (server_start する部分を別のスクリプトにしてしまうと、supervisord で restart などの処理を行ってもプロセスが切り離されてしまい、管理から外れてしまう状態になってしまいます)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
これで準備は完了です。あとは、supervisord で起動すればおしまいです。
sudo supervisorctl add sample
少し回りくどい構成のようにも思えますが、ソースをアップロードして server_start のプロセスに -HUP を送ることで Server::Starter がいい感じにプロセスを置き換えてくれます。また、サーバプロセスがなくなったときやサーバ再起動時などには supervisord がサーバプロセスを立ち上げてくれるので、管理も簡単です。
外部からのリクエストは、一度 Nginx などのリバースプロキシで受けて、動的なものだけを PSGI に送りレスポンスを返す形にすると様々な恩恵が受けられそうです。 ただ、今回試した範囲では Nginx から直接 socket に送ることができなかったのでここは今後の課題でした。
]]>CentOS6 系のサーバに perlbrew + Carton で環境を構築していたのですが、一通り構築が終わって plackup すると segmentation fault となってしまったのでした。 /var/log/messages を見てもこんなログばかり。
Jun 18 19:28:48 xx-xxxx kernel: app.psgi[2084] general protection ip:322fe17088 sp:49302b8e8cb3704b error:0 in ld-2.12.so[322fe00000+20000]
こんなとき、Perl に coredump を吐かせて gdb で見ることで当たりをつけることができます。
# core file size を設定(今回は仮に unlimited に)
limit -c unlimited
# segfault を起こすコマンドを実行
carton exec -- plackup app.psgi
# -> セグフォ
# gdb [実行ファイル] [コアダンプファイル]
gdb `which perl` core.2084
こうすることで、gdb のコンソールが表示されます。 あとは where コマンドで関数の呼び出し順序を調べたり、list を使って該当ソースを見たりして当たりをつけましょう。
ulimit で設定していないと core ファイルが生成されないかもしれない、というお話でした。 このような当たりの付け方は Perl に限らず他のプログラムでも同様にできると思います。
ちなみに今回は MySQL-shared のパッケージが足りず、DBD::mysql がうまく入っていなかったためでした。。 local を丸ごと削除して再度 carton install で解決しました。
]]>以前までは、bash_completion を利用して表示するということをしていました。.bashrc の例ですが、こんな感じです。
1 2 3 4 |
|
これはこれで良いのですが、git でしか利用できません。メインで利用する VCS は git なので問題ありませんが、それ以外の VCS で管理されたコードを読んだりする機会も多々あります。 調べてみたところ、zsh に vcs_info という関数があることを知りました。そこで、これを使ってプロンプトを少し派手にしてみました。
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 |
|
はじめは %1v として $psvar[1]
の値をとっていたのですが、カラースキーマがうまくいかないため配列の要素を直指定する形にしています。vcs 管理下にないディレクトリでは $psvar[1]
の値は何も入らないため、デザインも崩れません。
小さな話をいっぱい寄せ集めた内容だったので、うまくまとめきれずすみませんでした。また、時間を気にしてしまって少し早口だったり聞き取りにくかったりした所もあったかと思います。
伝えたかった思いはまとめに集約しています。 何よりも「**MySQL すごいよ、ありがとう**」と言いたかったのでした。MySQL 自体のソフトウェアとしての完成度や開発体制もさることながら、多くのユーザがいて様々な知見・ノウハウが共有されているこの環境自体も大きな資産であると感じています。ない分の動きを把握していて、様々手を加えられるのはとても理想的なことですし憧れます。ですが、そこまでのスキルセットがない人でも、調べたり試したりすることである程度がんばれる、というのが環境含めて完成されている証だと思っています。 また、これは MySQL に限った話ではないのですが、私自身の考えとして実際のサービス運用では様々な視点・知識・経験が必要だと思っています。「何でも屋になろう」ということではなく、「視点を変えてみるとうまくいくんじゃないかな」「そのためには薄くでも知識や経験があると取っつきやすいんじゃないかな」という考えです。サービスを運用していく以上は、使っていただいているユーザさんを「もてなす」心を意識して、そのためにどうすればいいかを考えてメンバーと協力して作り上げていきたいと思っています。
偉そうなことを言いながらも最近は直接のインフラ運用をしていないことも多いのですが、全体としては業務に限らない私自身の経験や思いをまとめたものとさせていただきました。 このような公の場でトークさせていただくのは初めてだったのですが、資料を作る時点で様々追って調べたりまとめたりと、かなり良い勉強となりました。アウトプット大事ですね。 いつもお世話になっているコミュニティに対して、今までは情報を集めて使うだけの立場だったのですが、少しずつ発信・共有する立場にもなりたいというのが今年の目標でした。まだ内容的にも未熟な点が多いと思いますが、人に説明できるまで理解をする(=自分の言葉でかみ砕く)を重ねていってコミュニティを支えたい・恩返しをしたいと強く思った一日でした。
快適な会場を提供いただいた Oracle のみなさま、とりまとめていただいた運営のみなさま、そしてお集まりいただいて素敵な時間を共有していただいた参加者のみなさま、ありがとうございました。
]]>MySQL のレプリケーションは、安定稼働やバックアップ、負荷分散などの目的に利用できる優れた機能です。 bin-log (バイナリログ) を利用して Master サーバから Slave サーバに更新を伝播させ、データの複製を行います。Slave サーバでは、2 つのスレッドが動作しています。
“SQL_THREAD” による遅延の場合は、Slave サーバで “SHOW SLAVE STATUS” コマンドを実行することで確認ができます。
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 34 35 36 37 38 39 40 41 42 43 |
|
ここに示されている “Seconds_Behind_Master” の値が、「現在 SQL_THREAD が実行しているクエリの実行時刻」と「Slave サーバが保持しているリレーログの時刻」の差となり、遅延を表しています。
“IO_THREAD” による遅延の場合は、Master からのバイナリログが受信しきっていないため、Master における “SHOW MASTER STATUS” の結果も参考にする必要があります。
1 2 3 4 5 6 7 |
|
この結果を基に、どれくらいずれているかを見なければなりません。
Master と Slave で “File” と “Master_Log_File”、”Position” と “Read_Master_Log_Pos” をそれぞれ比較し、どの程度転送が遅れているかをチェックします。 “IO_THREAD” に起因した遅延の場合は、サーバの処理というよりはネットワーク帯域の問題である可能性が高いと思います。
今回は “SQL_THREAD” による遅延を想定してまとめていきます。
レプリケーションで送られてくるクエリの流量が多すぎる場合、つまり Master の更新が激しすぎて追いつかないケースでは、そもそも Master での更新を止めてしまうという方法があります。
これは、MASTER_POS_WAIT() 関数を利用することで実現できます。
手順については、MySQL5.1 リファレンスマニュアルの FAQ 項目内に「レプリケーションが追いつくまでマスタの更新をブロックする方法」として紹介されています。
この方法では同期化をコントロールすることで追いつかせることができますが、実際にサービス運用中のサーバではなかなか使いづらいところもあります。
このとき、レプリケーションで伝播するクエリは全て直列化されるため、更新が激しい場合はどうしても遅れてしまうことがあります。 DiskI/O への負荷が高いとき “innodb-flush-log-at-trx-commit” の値を変更することで、ディスクへのフラッシュを減らすことができます。このパラメータではログバッファからログファイルへの書き込み、およびディスクへのフラッシュをコントロールすることができます。
設定値 | ログバッファのファイルへの書き込み | ディスクへのフラッシュ | 備考 |
---|---|---|---|
0 | 毎秒 | ログファイル上 | |
1 | コミット時 | ログファイル上 | デフォルト値 |
2 | コミット時 | 毎秒 |
この設定値によるパフォーマンス向上度合いは、経験的には効果の大きい順に 0 > 2 > 1 の順と思っています。
my.cnf に記述し起動時に適用することもできますが、 mysqld の再起動をせずに変更・反映が可能です。
1 2 |
|
この設定値はパフォーマンス向上の代わりに、信頼性を犠牲にします。プロセスが突然落ちた場合などにディスクにフラッシュされていないデータをロストする可能性がありますので、状況に応じて(あるいは追いつかせるまでの間だけなど)の使用に抑えることが良いかと思います。
MySQL のレプリケーションが追いつかない場合、プロセスの再起動を行わずに簡単に試せて効果の期待できる方法をまとめてみました。
「実践ハイパフォーマンスMySQL」や「エキスパートのためのMySQLトラブルシューティングガイド」などの書籍でもわかりやすく紹介されていますので、ぜひご参照ください。
このほか、サーバ上で不要なデーモン(cpuspeed など)が動いていないかチェックする、ionice(I/O スケジューラを cfq にする必要があります) で mysqld が優先的に DiskI/O を使えるようにするなどサーバ側でもできることはありそうです。
間違っているところや、他にもこんな方法がある、などございましたらぜひお聞かせください。
明日は @kamipo さんです!
]]>町田も久しぶりすぎて変化に戸惑いが隠せない感じでした。資料作成しようと思ったカフェとかなくなってたし!
自己紹介代わりの LT はやっぱりおもしろいと思います。規模が大きくなると難しくなりますが、全員に向かって各々が話す hachioji.pm ならではの雰囲気は好きです。
かなり様々なお話を聞けたことも大きな収穫でした。同時に、モチベーションが上がるような刺激を受けることができました。
その他、つらつらと思ったことを。
LT で話した資料をこちらにおいてあります (PDF 形式です)。 お題の「○○道」でネタを探していたのですが、preload のことで頭いっぱいだったこともありライトな感じにざっとまとめてみました。
周りの方にアドバイスいただいたり、調べたり、試したりしたものを組み合わせた結果、個人的な答えとして今はこのような手法がよいのかなと考えています。ただ、もっと 楽な 効率のよい方法など、実際に皆さんがどのようにされているかを知りたいなと思っているところです。
幹事の @ytnobody さん、主催の @uzulla さん、そして参加された皆さん、お疲れさま & ありがとうございました。 また次回も都合をつけて参加したいなー。
]]>個人的な視点で、今回の YAPC から感じた Perl とそれを取り巻く Web サービス系の世界の現状をいくつかまとめると、
といったところかなと思います。 会社で標準的に使われている開発言語が違っても、根底の考え方や Web サービス系全般での動きは同じだなと痛感しました。
※講演資料 [No Title] DeNA の kazuho (@kazuho) さんの講演。前回に引き続いて、Unix 環境で正しく動くコードを作るための Tips 紹介のトークでした。Unix の知識が足りずまだ理解が追いついていないので、調べて試さないとと感じた発表でした。
※講演資料 [No Title] Livedoor の kazeburo (@kazeburo) さんの講演。これまでの運用経験を基に、運用しやすい Web アプリケーションとなるためのログや DBI / cache の使い方・Tips をまとめて紹介されていました。確かに、と思うポイントが多く、とても参考になるトークでした。
DeNA の nekokak (@nekokak) さんの講演。社内 DevOps の観点から基準を決めてログ出力し、それを監視するためのツールを作成したというお話。”DevOps” と “ログ監視” については各社でかなり試行錯誤しているところかもしれません。 ログ監視は最近色々考えていて自分で実装しようかなと思っているところだったので、Komainu も試してみます。あと、「必要に応じたエンジニアリング」というスタンスはいいなと思います。
DeNA の hidek (@hidek) さんの基調講演。Perl ハッカーを束ねるマネージャーとしての考え方や経験のお話でした。 とてもいい話でした。DeNA には優秀で著名な方が集まっているイメージがありますが、このようなコミュニティというか、仲間の魅力が根底にはあるのだろうなと感じる内容でした。途中、何度もチームを褒めているところが、率直に褒めているように感じられて印象的でした。
このほか、LT なども面白く刺激的なものが多く、とても良いカンファレンスでした。
次回がどのようになるかはまだ未定とのことでしたが、次回が YAPC::Asia どこで行われても参加したいと思っています。同時に、これまではカンファレンスやセミナーに参加しつつもずっと聞く側でしたが、今後は YAPC に限らず、もっとコミュニティ全般に対して積極的に貢献できる活動をしたいと思った 3 日間でした。
発表者、スタッフ、参加者、そしてスポンサー企業のみなさま、お疲れ様でした。
]]>振り返ると、インフラ寄りな内容を選んでいたこともありますが、今日は Perl に限らない話も多かったように思います。それだけ広い知識と経験が必要で、いろんな所でいろんなひとが挑戦していることがわかってわくわくしましたが!
今回のスペシャルゲスト、 Perl5 開発リーダーの Jesse Vincent (@obra) さんの講演。Perl5 の開発プロセスがどのように変化してきたか、そして今後の Perl5 がどうなっていくのかというお話でした。 (英語のセッションだったので内容を頭の中で理解するのが追いつかずメモ取りきれなかったので間違えていたら指摘をお願いします。。)
Perl5 の開発体制が整ってきたのでリリーススパンが早くなってきた。
“New version should not break old environment” と “Perl should run everywhere”
そして機能をシンプルにして、仕様を明確化させる。
※講演資料 YAPC::Asia 2011 / 高速化のはなしとか ライブドアの mala (@bulkneets) さんの講演。すべてを聞いたあとの「気持よく書ける範囲で最適化」というまとめに納得しました。先回りしてキャッシュしておく戦略は難しそうですが、効果は大きそうなのでやってみたいと思っています。
はてなの大西 (@yasuhiro_onishi) さんの講演。はてなダイアリーが “Hatena Blog” にリニューアルを解説するセッションでした。主に表示に関わる仕様変更をユーザの行動に影響しないようにするため、様々な工夫をされているのですね。。
「安全なWebアプリケーションの作り方」の著者、徳丸浩 (@ockeghem) さんの講演。同本の 5.1 章を解説する流れで説明されていましたが、RainbowTable などの説明がとてもわかり易かったです。
単に HASH 化しただけでは元に戻せるのか? - クラックは 2 種類 – オンラインクラック : リモートからのパスワード試行 – オフラインクラック : 情報を盗み、攻撃者の手元で平文パスワードを求める - パスワードだけ保護する理由とは? – パスが漏れてれば他の個人情報も漏れている – パスワードを使いまわす利用者もいる – パスワード保護は運営者の義務
※講演資料 <a href=”http://dl.dropbox.com/u/224433/YAPC2011/index.html KAYAC の sfujiwara (@sfujiwara) さんの講演。”こえ部” をレンタルサーバから自社インフラに移設した時のまとめを紹介されていました。アップロードデータのあるサービスで新しいファイルを旧環境でケアしてあげる方法は難しそうですが、Nginx の効率のよい使い方などは参考になりました。
DeNA の zigorou (@zigorou) さんの講演。モバゲーオープンプラットフォームの障害事例とその対処法についてのお話でした。大規模サービスの障害事例はとても参考になります。「原因究明」「失敗防止」「知識配布」という項目でまとめているのもわかりやすかったですし、これらの障害報告会を社内で定期的に行なって共有する体制を作っているのはとても良いことだと思いました。
DeNA の riywo (@riywo) さんの講演。DeNA の内製 SNG の運営におけるチューニングのお話でした。台数が増えると起きてくる問題や、人気が出てイベントなどでアクセスが集中すると起きる問題など、そのアプローチが参考になりました。DevOps 的な問題点についても、規模は小さいながらも同じような状況を見ている立場としてとても共感できるものでした。
LT もレベルが高く面白い発表ばかりだったのですが、聞くことに専念していたのでメモとってませんでした。。。 そして前夜祭のメモまとめてないことに気づいたのであとでまとめます。
2 日目につづく。
]]>そこで、こんな感じの構成を目指して、github 上のプロジェクトの fork をプライベートな git サーバで管理してみました。
|プライベートなリモートリポジトリのメインブランチ|origin/master| |github のプロジェクトのメインブランチ|github/upstream|
事前準備として、プライベート git サーバには push できる空のリポジトリを作っておきます。 (gitosis の場合であれば、gitosis.conf にリポジトリ名を追加しておく感じでいけます)
まず、おおもとのツリーを github から clone して取得します。
$ git clone --origin github https://github.com/edavis10/redmine.git
$ cd redmine
$ git config -l
...
remote.github.fetch=+refs/heads/*:refs/remotes/github/*
remote.github.url=https://github.com/edavis10/redmine.git
branch.master.remote=github
branch.master.merge=refs/heads/master
ここでは master が github のメインブランチになっています。 今回はオリジナルの master を upstream という名前で扱うようにしたいので、ブランチ名を変更します。
$ git branch master
$ git branch -m master upstream
$ git branch upstream
$ git config -l
...
remote.github.fetch=+refs/heads/*:refs/remotes/github/*
remote.github.url=https://github.com/edavis10/redmine.git
branch.upstream.remote=github
branch.upstream.merge=refs/heads/master
これでおおもとの master は、ローカルでは github/upstream という名前で扱えるようになりました。 実際にこちらでカスタマイズするのは github/upstream のタグ “1.2.0″ をベースに使いたいので、ここから master ブランチを切ります。
$ git branch master 1.2.0
$ git branch master upstream
そして、プライベートな git サーバをリモートリポジトリ “origin” として追加します。
$ git remote add origin ssh://gitosis@git.example.jp/redmine.git
$ git config branch.master.remote origin
$ git config branch.master.merge refs/heads/master
$ git config -l
...
remote.github.fetch=+refs/heads/*:refs/remotes/github/*
remote.github.url=https://github.com/edavis10/redmine.git
branch.upstream.remote=github
branch.upstream.merge=refs/heads/master
remote.origin.url=ssh://gitosis@git.example.jp/redmine.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
あとはプライベートリポジトリに push すれば完了です。
$ git push origin master
$ git push origin upstream
これで、origin/master に push/pull し放題になります。
]]>サイバーエージェントの坂本佳久 (@ton_katsu) さんの発表。プライベートクラウドを構築するプロジェクトのひとつ、OpenStack を検証した結果のまとめ。
Nova と Swift を組み合わせたプロジェクト。 OpenStack を検証対象として選んだ理由は次のとおり。
AWS と比較すると、下記のような対比でだいたい同じことができる。
インスタンスの起動や管理を行う "CloudController" と、この配下に複数の "Computenode" を配置する構成をとる (最小構成では両プロセスを同じマシンに同居させることも可能)。Computenode に hypervisor などをいれ、実際にインスタンスを動作させることとなる。その他、副次的に MySQL や RabbitMQ などのプロセスも利用する。
実際に検証で用いた環境は下記の通り。
これらの管理を行うために、 Django ベースの GUI が付属している。WebSocket を利用するため、Safari などで操作する必要がある (Chrome はうまく動作しなかったとのこと)。また、VNC コンソールは Cactus のバージョンでは未実装なので、利用する場合は trunk から取得する必要がある。
その他、API も用意されているので自前で管理ツールを作成することも可能。
来月より検証環境で運用するとのことで、今後のレポートにも注目したいところです。
サイバーエージェントの森野耕平 (@kohei_april20) さんの発表。AmebaPico のアーキテクチャや体制に関して。
アメーバピグの海外版として位置づけられているサービス。
すべて AWS で運用されている。
クライアントサイドではまず main.swf のみをロードし、必要に応じてサブモジュールをロードする。
EC2 上でサービスを運用してみての総括。
そして、MongoDB をメインで利用してみての総括。
MongoDB を大規模に利用しているケースなので、とても興味深いものでした。海外展開の際に DC の場所を気にしなくても良い、というのは AWS ならではのメリットに感じました。
クックパッドの成田一生 (@mirakui) さんの発表。レシピに必須の画像をリアルタイムでリサイズするための Apache モジュール "TOFU" について。
URL に処理内容をマッピングし、リクエストの度に画像をリサイズする Apache モジュール (mod_tofu.so)。
/recipes/{:recipe_id}/{:size}/{:hash}
画像処理には ImageMagick を利用している。
画像種類もリクエストも多いのにリアルタイムに変換するのは大変そうに思ったのですが、Apache モジュールと聞いて少し納得。キャッシュもうまく組み込んでいて、かなりコストを意識した工夫がされている印象を受けました。
クックパッドの菅原元気さんの発表。先日のアマゾンウェブサービスクラウドアドバンテージセミナーで発表された内容をベースに、AWS 移行に向けた全体的なお話。 プレゼン資料がとてもまとまっているので、そちらを直接見たほうが。。。
さすがに全台で resolv.conf を書き換えていくのは大変なのと、いくつかの問題点がクリア出来ない。
そのため、分散 DNS を開発。
$ ruby gem ddns
DNS がそれぞれノードとして機能する動きは、クラウドならではの問題点をクリアするためのひとつの解決策かと思います。現状のサービスを AWS に移行する際の参考になるような、総括的な話でした。
LT もあり、その後の懇親会ではおいしい料理もあり、でとても素敵な勉強会でした。スピーカー&スタッフの皆様、ありがとうございました!
]]>git のリモートリポジトリから別のサーバにバックアップを作成するのは、hooks を利用することで簡単に設定できます。例えば、対象となるリポジトリの post-receive で下記のようなコマンドを設定しておくとできます。
1 2 3 4 5 6 7 8 |
|
":mirror" オプションを付けることで、バックアップ先にも bare のままディレクトリが作成されます。 リモートリポジトリとして利用するサーバと別のサーバで Redmine や Trac、あるいは gitweb などを動作させてリポジトリブラウザを利用する場合などでも bare を付けます。
hooks/post-receive は、リポジトリに加わる変更を受信したタイミングで実行される hook script です。cron などで仕込むものとは異なり、push されたタイミングで sync されるので無駄にコネクションが張られることがありません。 ただし、push するタイミングで別サーバへの push が実行されるため、ユーザからみると push 自体の時間が少し長くなるのが欠点です。
]]>そんな Git を複数メンバー・複数環境で利用する場合、マスターリポジトリを利用することがあります。これにより、Subversion のような中央集約型のソースコード管理をしつつも Git の恩恵を受ける開発スタイルを取ることができるます。 マスターリポジトリとして GitHub を利用するのが最も手っ取り早いですが、プライベート(= メンバーのみが閲覧できる)なリポジトリを作成するためには有料オプションにしなければなりません。しかも地味に高い。
こんな時、gitosis を利用すると手軽にプライベートな Git サーバを構築することができます。もちろん、リポジトリを利用するメンバー全員が SSH での接続ができるサーバに bare リポジトリを作ることでも Git サーバとして機能しますが、それでも gitosis を使う優位性は以下のような点にあります。
gitosis はマスターリポジトリとして利用するサーバのみインストールします。リモートから clone / pull / push をするクライアントには、通常通りの Git がインストールされていれば利用することができます。
gitosis は python で記述され、gitで管理されているプロジェクトです。 CentOS の場合、EPEL リポジトリに Git / gitosis 共にパッケージが存在するので、これを利用することで簡単にインストールできます。
$ sudo yum install git python-setuptools gitosis
この方法で導入した場合、gitosis ユーザが合わせて作成されます。
gitosis の設定は、 gitosis 管理リポジトリのファイルを変更し push することで反映されます。 設定を行うためには、管理ユーザとして最低一人の公開鍵をセットしなければなりません。ここでは、Git サーバ上の現在の操作ユーザの鍵を管理ユーザとしてセットする例を示します。
$ cd /var/lib/gitosis
$ sudo -H -u gitosis gitosis-init < ~/.ssh/id_rsa.pub
これで、gitosis のホームに "gitosis" ,"repositories" という2つのディレクトリが生成されます。
この gitosis 管理リポジトリを、登録した鍵を持つクライアント(ここでは同一ホスト)からcloneし、設定します。
$ cd ~/work
$ git clone gitosis@localhost:gitosis-admin.git
設定を変更後、push することで Hooks のスクリプトが実行されることで key が gitosis ユーザの authorized_keys に追記されていきます。 この authorized_keys には command が併記されているため、git のリモートリポジトリを操作する以外のコマンドが実行できないようになっているのです。
新規ユーザの追加は、*.pub ファイルを作成して該当するグループに追記、push するだけです。 gitosis では、グループ毎に権限をコントロールする形式を取ります。このため、ユーザが複数のグループに所属しているとうまく動作しないことがあります。 *.pub は単なる authorized_keys なので、1行にひとつの公開鍵を書く形式になっていれば複数設定可能です。
新規リポジトリの追加は、gitosis.conf に変更を加えて push するだけです。空のまま pull すると init されるだけですが、追加して push すれば大丈夫です。
keydir 以下に公開鍵ごとにファイルを作成し、 gitosis.conf に公開鍵のファイル名 (.pub を除く) を設定していきます。
[gitosis]
[group gitosis-admin]
writable = gitosis-admin
members = admin
[group development]
writable = misc/sandbox project test
members = hatak hoge fuga
リポジトリはサブディレクトリに入れることができます。 上記 sandbox の場合は次のようになります。
サブディレクトリは予め作成しておく必要がありますが、こうすることで乱立するリポジトリを階層分けして整理することができます。
$ sudo -H -u gitosis mkdir /var/lib/gitosis/repositories/misc
gitosis.conf ではユーザが多いときなどバックスラッシュを入れることで、設定ファイル内でも改行することができます。 ユーザが多いときなどに可読性を上げることができ、とても便利です。