読者です 読者をやめる 読者になる 読者になる

Keepalivedのシンタックスチェッカ「gokc」を作った

Go Keepalived

Keepalivedのシンタックスチェッカ「gokc」をGo言語で書きました。

github.com

執筆時点でのKeepalived最新版であるバージョン1.2.19まで対応していることと、include文に対応していることがポイントです。

使い方

https://github.com/yuuki1/gokc/releases からバイナリをダウンロードします。OSXでHomebrewを使っていれば、

$ brew tap yuuki1/gokc
$ brew install gokc

でインストールできます。

gokcコマンドを提供しており、-f オプションで設定ファイルのパスを指定するだけです。

gokc -f /path/to/keepalived.conf
gokc: the configuration file /etc/keepalived/keepalived.conf syntax is ok

シンタックスエラーのある設定ファイルを読み込むと、以下のようなエラーで怒られて、exit code 1で終了します。

gokc -f /path/to/invalid_keepalived.conf
./keepalived/doc/samples/keepalived.conf.track_interface:7:14: syntax error: unexpected STRING

なぜ作ったか

KeepalivedはIPVSによるロードバランシングと、VRRPによる冗長化を実現するためのソフトウェアです。 KeepalivedはWeb業界で10年前から使われており、はてなでは定番のソフトウェアです。 社内の多くのシステムで導入されており、今なお現役で活躍しています。

KeepalivedはNginxやHAProxy同様に、独自の構文を用いた設定ファイルをもちます。

  • しかし、Keepalived本体は構文チェックをうまくやってくれず、誤った構文で設定をreloadさせると、正常に動作しなくなることがありました。

そのため、これまでHaskellで書かれた kc というツールを使って、シンタックスチェックしていました。 initスクリプトのreloadで、kcによるシンタックスチェックに失敗するとreloadは即中断されるようになっています。

ところが、Haskellを書けるメンバーがいないので、メンテナンスができず、Keepalivedの新機能に対応できていないという問題がありました。 (Haskell自体がこのようなものを書くのに向いているとは理解しているつもりです。) さらに、kcについてはビルドを成功させるのが難しいというのもありました。Re: keepalived.confのシンタックスチェックツール「keepalived-check」「haskell-keepalived 」が凄い! - maoeのブログ

さすがに、Keepalivedの新しい機能を使うためだけに、Haskellを学ぶモチベーションがわかなかったので、Go言語とyaccで新規にgokcを作りました。 Go言語はインフラエンジニアにとって馴染みやすい言語だと思っています。 yaccは構文解析の伝統的なツールなので、情報系の大学で習っていたりすることもあります(僕は習わなかったけど、概念は習った)。

ちなみに、C言語+flex+yacc版のシンタックスチェッカである ftp://ftp.artech.se/pub/keepalived/ というものがあります。 新しい構文には対応しているのですが、include未対応だったり、動いてない部分が結構あるので、参考にしつつも一から作りました。

実装

シンタックスのチェックだけであれば、コンパイラのフェーズのうち、字句解析と簡単な構文解析だけで済みました。 「簡単な」と言ったのは、構文解析フェーズで、抽象構文木を作らなくて済んだということです。

一般に字句解析器は、自分で書くか、Flexのような字句解析器の自動生成ツールを使います。 後者の実装として、自分の知る限り、Go言語にはgolexnex があります。

ただし、include文のような字句解析をそこそこ複雑にする構文があるため、柔軟に書けたほうがよかろうということで自分で書くことにしました。 といっても、スキャナ部分はGo言語自体のスキャナであるtext/scannerを流用しました。 Go言語用のスキャナですが、多少カスタマイズできる柔軟性があるので、ユーザ定義の言語の字句解析器として利用できます。 Rational Number Calculator in Go を参照。

構文解析にはパーサジェネレータであるyaccを使いました。 yaccのGo版は標準でgo tool yaccがあります。 goyaccについて詳しくは、goyaccで構文解析を行う - Qiitaを参照してください。

多少面倒だったのはinclude文の対応です。 include対応とはつまり、字句解析器において、別の設定ファイルを開いて、また元の設定ファイルに戻るというコンテキストの切り替えをしつつ、トークンを呼び出し元の構文解析器に返すことが求められます。

字句解析器から構文解析器へトークンを渡す構造をどうするかが問題でした。 逐次的にトークンを構文解析器へ返すのを諦めて、一旦末尾まで字句解析した結果をメモリにすべてのせて、構文解析器から順に読ませるみたいなこともできました。

それでもよかったんですが、Rob Pikeの Lexical Scanning in Go の資料に、goroutineとchannelを利用して、字句解析器を作る方法が書かれており、この手法を部分的に真似てみました。

具体的には、字句解析を行うgoroutineと、構文解析を行うgoroutine(メインのgo routine)が2つがあり、字句解析goroutineが構文解析goroutineにemitetr channelを通じて、トークンを受け渡すという構造にして解決しました。 channelをキューとして扱うようなイメージです。

include文のもつ複雑さに対して、そこそこシンプルに書けたような気はしています。

参考

2015年の心に残った技術エントリ

日記

1年分の自分のはてなブックマークを見直した。 およそ 2,000 URLのエントリの中から、特に感銘を受けたり、記憶に残ったエントリを紹介したい。 2015年にブクマしたというだけで、必ずしも2016年に公開されたエントリばかりではないことに注意。

エントリ

Scalable Deployments

一昨年のRubyKaigiの講演スライド。 スクリプト言語のtar ballデプロイをみたのはこれが初めてだった。 大量のアプリケーションサーバに対するsshが遅いもしくは失敗する問題を、Serfを利用したpull型デプロイにより解決しているところがすごいアイデアだと思う。

Advanced Techinic for OS upgradeing in 3 minutes

昨年のYAPC::Asiaで直接拝聴したトーク。 前述のtar ballデプロイにも触れられている。 No sshという思想を軸に、目の前のアーキテクチャを変えずに確実に自動化していくという方法論が蒙を啓くようだった。

最近は、色濃い思想をもつ飛び道具系のツールがそこら中に飛び交っている。 いきなりそれらのツールを導入しようとした結果、自分も含めて、振り回されてしまう人たちにとって、一つの道標になる。

MySQLやSSDとかの話

前編と後編でセットになっている。 2000年代のMySQL運用から10年経った今というような視点で読める。 全く他人事ではないので、わかるわかると頷きながらスライドをめくっていた。

単に10年経ってつらいという話ではない。 ハードウェアの進化にあわせた最適な構成は何かということを考えさせるスライドだった。

モバイルアプリのスレッドプールサイズの最適化

コンピュータサイエンスの知識、ここでは待ち行列理論をモバイルアプリ開発に応用している例。 システムの振る舞いをモデル化して、検証するというサイクルを回せているのはすごい。 モバイルの人ってやっぱり計算機やネットワークのことはあまり考えないだろうという思い込みがあり、いい意味で裏切られた。

性能測定道

性能測定は技芸であり、技あるところに道ありとして、性能測定道というタイトルに行き着くまでの流れに魂みたいなものを感じた。 適当にベンチーマーク回して、最終結果の数値だけみて速いとか遅いとか言ってたりするんだけど、はたして本当にそれでいいのか。 性能測定のためにはシステムのブラックボックスを理解する必要があり、性能測定が本質的に難しいということを知れるだけでも、十分な発見だと思う。

情報科学における18のメタテクニック

キャッシング、パイプライニング、投機的実行、先読みなど、コンピュータサイエンスのあらゆるレイヤで利用される普遍的なテクニックを紹介したスライド。 切り口がよい。以前、Cache Nightとかやったらおもしろいんじゃないかとか言ってたことがある。CPUのキャッシュメモリからCDNまで幅広い話題がでてきそう。こういうレイヤを横断したトピックで、利用例を集めてみるのもおもしろいかもしれない。

Webオペレーションエンジニアのアウトプットと開発力

社外へアウトプットするということの大切さを再確認したエントリ。

自分は社内のインフラチームの中で最もアウトプットしているという自負がある一方で、自分一人ではなく、チーム全体のアウトプットを増やすにはどうしたらいいか悩むことがある。 悩みの中心はたぶんアウトプットに対する過小評価を感じている。 アウトプットの目的が単にプレゼンス向上のためだけだと社内で捉えられてしまうことがあり、揶揄も込めてプレゼンスばかりあっても意味ないという話で終わってしまう。 自分も気分が乗る人だけやればよくて無理することはないというスタンスだったんだけど、これで本当にいいのかと思うようになってきている。

改めてスライドを拝見して、アウトプットすることはより質の高い仕事をするためのステップ、もしくは成長のためのステップと捉えるのがよいのかなと思うようになってきた。

はてなに入った技術者の皆さんへ

10年前のエントリなんだけど、今でも全く色あせない。 matsumotoryさんのエントリとあわせて読むとよい。

僕たちが作るものは、会社の外から評価されることによって初めて価値が生まれるのです。

アウトプットに関しては、この一言に尽きると思う。 やはり社外へのアウトプットを単にプレゼンス向上とみなすのはもったないという気持ちが強くなってきた。

シンプルでかつ最高のJavaScriptプロファイラ sjsp を作りました!

後輩のブログなんだけど、まさにお手本のようなアウトプット。 他人が利用できる形であり、社外でも評価され、なおかつ、裏では社内のサービスのユーザ体験まで向上させている。

ペパボのインターネット基盤技術研究・開発の活動

2年間の自分の仕事を振り返ってみても、基盤技術がボトルネックでサービス開発を妥協していることは少なからずある。 開発チームからの要求があったときに、それはちょっと厳しいから、この辺で妥協するかとかよく言ってる。

一方で、もし圧倒的な基盤技術が開発できれば、例えば、コストを10倍下げて、その結果ユーザが保持できるデータ量を10倍にできるかもしれない。 基盤技術の開発により、競合サービスに対してリードできないかという視点を持ち始めるきっかけになった。

これからのWebサービスは新規性のある技術を自ら研究・開発し、ググっても解決できない問題を自分たちで解決しなければ一歩リードする事ができない時代へと突入

インフラチーム改め Site Reliability Engineering (SRE) チームになりました

昨年、Site Reliability Engineeringという言葉を初めて知った。 通常、自分たちのことをインフラ部とかサーバ管理者とか運用チームとか呼んだりするんだけど、どうにも保守的というか価値を生み出す感がなかった。 はっとしたのは次の一文だ。

...SREがソースコードを追って原因を特定し、パッチを充ててリリースをすることもあるようです。 GoogleのSREの特徴として、ソフトウェアエンジニアとしての業務の比重が大きい事が挙げれます。業務時間の20-80%は開発の業務に関わっているようです。

別の記事にもSREの役割として近い内容が書かれている。

現に、コア原則の一つは SRE が運営の作業に費やせる時間を 50% のみにすることを義務付けています。彼らは、可能な限り最大限の時間をコード書きとシステム構築に費やして、業績と運営効率を改善しなくてはならないのです。

https://www.atlassian.com/ja/help-desk/site-reliability-engineering-sre

自分の仕事を振り返ってみると、運用に手間を割くことが多く、正直そんなにコードを書いているわけではない。 自分たちのことを運用チームと呼んでいたりすると、運用チームだから運用に時間を割くのは当然だと思ってしまう。 @rrreeeyyyくんがよく「運用を消したい」って言っているのとつながる。

エンジニアとしての落としどころを作る

本当にすごい人には勝てないんじゃないか、勝てないとだめなのかとか誰しも考える悩みに正面から応えたエントリ。 落としどころを作るというのは、つまるところ、自分はこれでいいのだなと思えるところを発見することなんだなと思えた。

イメージできることを実践する

技術エントリではないけれど、ことあるごとに思い出すエントリ。 他の人がやってるわけではないんだけど、なぜかイメージできるものというのは確かにある。 例えば、会社でいま存在しないんだけど、こういうポジションがあったらうまくやれそうだなとかおもしろくやれそうだとか、ポジションをイメージできたりすることがある。 このエントリを読むと、他の人がやっているかやっていないかより、自分がイメージできるものをやってみようと思える。

今明かされる! シンラ・テクノロジーのインフラへの挑戦と舞台裏

資料はおそらく公開されていないが、JTF 2015の招待講演は圧巻だった。 中身は、シンラ・テクノロジー(「オンラインゲームを支える技術」の著者である中嶋謙互さんが所属されている会社)のプロジェクトの紹介だ。 クラウドにレンダリングサーバを配備することにより、クライアントではハイスペックなマシンを不要にするアーキテクチャの話。(リモートレンダリングアーキテクチャ)

あまり話題にならなかったのが不思議だ。 GPGPUとカーネルのネットワークスタックにある程度明るくないとピンとこない内容だったかもしれない。 ネットワークレイテンシをできるだけさげるために、RDMAを使って、CPUをバイパスして、NICからGPUのメモリに直接パケットをコピーするとかそういう話。 実はオンラインゲームの基盤技術には昔から興味があったので、こういうのやってみたいなと思ったりする。

こちらのエントリにメモが書かれている。 July Tech Festa 2015 - したためなければいきのこれない

オンラインゲームを支える技術  ??壮大なプレイ空間の舞台裏 (WEB+DB PRESS plus)

オンラインゲームを支える技術  ??壮大なプレイ空間の舞台裏 (WEB+DB PRESS plus)

あとがき

id:toya さんが書かれた 2015年にブックマークしたURLでよかったものの中からブクマコメントに代えて - Really Saying Something にインスパイアされて書いてみた。

こうして振り返ると、ここに挙げたエントリの内容は、おもしろいように昨年の自分のブログの文章にも反映されているなと感じる。 何を考えて、この一年を過ごしたのかということが意外とはっきりと現れる。

他人の心に残るということは、それだけ月日がたっても色あせない何かがあるということだと思う。 今年も他人の心に残るようなアウトプットを心がけたい。

2015年も技術しかしてない

日記

今年も技術しかしてない。

やけにブログを書くことに傾倒していた。

26歳になった。

YAPCで発表した。

ISUCONに負けた。

入社2年過ぎた。

振り返ってみると、今年は技術でも仕事でもプライベートでも、ものごとやものの考え方は5年後、10年後はどうなるのか、変わらないものは何か、色褪せないものは何かを考え始めた年だった。 具体的には、例えば、単にブログを書いて、1カ月にN回書いたとかNブクマついたとか、対外発表の数をこなしてたくさん発表したねだけで終わるのではなく、その先に何があるのかを考えるといったことだ。 他には、5年後でも使っている技術はなにかとか、それを見極めるためには何を理解している必要があるのかといったこともある。 去年は若者らしくあまりそういったことは考えなかった。 たぶん、DockerとかHashicorpを使ってモダンなインフラを作るのがかっこいいと思っていた。 結局、いきなりそれらのツールを導入して、仮にメリットが1つ増えたとしてもデメリットが2つ以上増えることがわかり、技術というのはそういうものではないと悟った。 最終的にはそれらのツールの良い思想だけをいただいて、Dockerやめてchrootでいいとか言い始めることになった。 Dockerとchrootを組み合わせたシンプルなコンテナデプロイツール - ゆううきブログ

昨年の目標

2014年、技術しかしてない - ゆううきブログ

今年の目標はどうやら下記の3つだったらしい。

  • ツールを作る
  • 計算機システムの理解
  • インフラ系の若者と交流

ツールを作るというのはあんまりうまくいってない。目標にないはずのブログのアウトプットに大半を費やしていた。

ふたつ目の計算機システムの理解というのもそんなにうまくいかなかった。あまり書籍とか論文とかまとまったものを読めなかった。

インフラ系の若者とは交流成功した。大成功と言ってもよい。

wakateinfra Slackとかあって、毎日なんか会話してる。平和。

f:id:y_uuki:20151231210951p:plain

ブログの振り返り

昨年は28本のエントリを書いた。合計ブクマ数は 5,055 users、年間PVは 172,878 views だった。 今年は13本のエントリを書いた。合計ブクマ数は 5,409 users、年間PVは 198,381 views だった。 1エントリあたりの平均ブクマ数は 416 users / entry 。 去年は東京はもう古いとか書いてたけど、今年は技術しか書いていない。 昔はもっと量を書かないと、とか思ってたけど、量だけあって一ヶ月で廃れる内容を書いても自分で満足できないので、あとで振り返っても色あせないものを目指した。 自分が満足できるアウトプットかどうかが重要だと思う。 採用活動にも奇跡的にうまくつながったので、会社でそんな賞ないはずないのになぜかブログで求人賞みたいなのをいただいた。

順位 エントリ
1位 2015年Webサーバアーキテクチャ序論 - ゆううきブログ
2位 Webシステムにおけるデータベース接続アーキテクチャ概論 - ゆううきブログ
3位 はてなで大規模サービスのインフラを学んだ - ゆううきブログ
4位 Linuxでロードバランサやキャッシュサーバをマルチコアスケールさせるためのカーネルチューニング - ゆううきブログ
5位 Dockerとchrootを組み合わせたシンプルなコンテナデプロイツール - ゆううきブログ
6位 Mackerelを支える時系列データベース技術 - ゆううきブログ
7位 Ansible + Mackerel APIによる1000台規模のサーバオペレーション - ゆううきブログ
8位 パフォーマンスの観点からみるDockerの仕組みと性能検証 #dockerjp - ゆううきブログ
9位 YAPC::Asia 2015で技術ブログを書くことについて発表しました - ゆううきブログ
10位 Serverspec + Mackerel APIによるインフラテストの実運用化 - ゆううきブログ
11位 ISUCON 5予選で5位通過した話 - ゆううきブログ

発表の振り返り

対外発表は確か3件だけだったと思う。

東京へ行く度に結構疲れてしまった反省をこめて、来年はピンポイントで興味のあるカンファレンスや勉強会で発表したい。

去年の感想によると、東京に疲れてた。今年はピンポイント感あってよかった。 セッションオーナーの話などをいただいたこともあったけど、申し訳ないと思いながらお断りしたりもした。

執筆の振り返り

去年まで雑誌に寄稿とかしたことなかったけど、気づけば今年はSoftware DesignとWeb+DBで執筆することになった。

雑誌の次はいつかは単著で書籍を書いてみたい気もするけどそれは来年とかではない。

OSSの振り返り

ツール書くとか言ってあまり書けなかった。

技術以外のことは何もしてない割にはアウトプットが少ない気がする。 発表やブログのアウトプットは、去年と今年でそれなりに満足したので、来年はブログも発表もできるかぎり抑えて、もっとコード書きたい。 みんなが飲み会とか結婚とかいってのんびりしている間にコード書くというのが半分冗談の来年のテーマだ。

今年もお世話になりました。来年もよろしくお願いします。

Serverspec + Mackerel APIによるインフラテストの実運用化

Mackerel Serverspec

この記事は Mackerel Advent Calendar 2015 の24日目の記事です。 前回は、id:hitode909 による 三度の飯より監視と通知!Mackerelで自分の心拍数を監視しよう - hitode909の日記 でした。

今回は、Mackerel APIを用いてServerspecによるサーバ構成テストを実運用化した話を紹介します。 Serverspec単体では手の届かないかゆいところをMackerelでサポートするところがポイントです。 Mackerelはもちろんですが、他のサーバ管理ツールにも通用する汎用的な話になるように心がけています。

続きを読む

Dockerとchrootを組み合わせたシンプルなコンテナデプロイツール

Docker Linux Go

この記事ははてなエンジニアアドベントカレンダー2015の1日目です。今回は、既存の運用フローに乗せやすいDockerイメージへのchrootによるデプロイの考え方と自作のコンセプトツール droot を紹介します。

続きを読む

ISUCON 5予選で5位通過した話

日記

ISUCON 5の予選で2日目3位、全体で5位のスコアで通過した。

メンバーは id:ntakanashi さん, id:astj さんと自分の3人で、「はむちゃん」というかわいいチーム名で参加した。 言語は当然Perl。 役割分担は id:astj さんの記事にも書いてあるけど、だいたい以下のようなものだった。

id:y_uuki : ミドルウェアより下をお任せ / ログ解析して改善ポイントの洗い出し id:ntakanashi : オンメモリにしたりモジュールを入れ替えたり諸々チューニング id:astj : クソクエリやN+1をちまちま潰していく

ISUCON 5の予選に参加して全体5位で通過しました - 平常運転

昨年のISUCON 4に参加したときに、少なくともISUCON予選においてはアプリケーションロジックの改善/改変がスコアに対して支配的だと感じていた。 そこで、インフラ担当の最初の仕事はいかにしてアプリケーションエンジニアにロジックの改善に集中できる環境を作るかということだと考えた。 さらに、インフラエンジニアは普段からシステム全体を俯瞰することを求められるので、インスタンスサイズなど与えられた条件とシステム全体をみてシステムの性質を捉えることが重要だと思う。 今回の指定インスタンスはCPU4コア、メモリ4GB弱と去年よりメモリ搭載量がかなり少なかったので、これはいつものようなオンメモリ勝負は厳しいのではないかとあたりをつけていた。実際、普通に考えるとデータサイズがOSのメモリに乗らない量(一部のテーブルは150万行ぐらい)だったので、初期段階で明らかにMySQLのCPU利用率とディスクI/Oがボトルネックだった。 したがって、今回の出題意図はメモリに乗らないデータをいかに捌くかということにあると判断した。

インフラ担当である自分が具体的にやったことは、インスタンスの構築、デプロイの仕組みの整備、OS/Nginx/MySQL/memcached/アプリサーバのチューニング、topやiostatによるハードウェアリソース利用状況の把握、アクセスログとスロークエリログの解析などだった。 今回はベンチマークをインスタンスのローカルで実行する術がなかったので一回一回のベンチマークを無駄にしないために、どうせ仕込むであろうsysctlやmy.cnf、nginx.confのチューニング、UNIX domain socket化、PlackサーバをGazelleに変更、静的ファイルのnginx配信などは初期の段階で一気にやった。 さすがにやったことのないチューニングをするのは不安なので、過去問で訓練を重ねた。 ちなみにどうせスコアに影響しない(より高req/sな環境では影響するかもしれない)ワーカー数やスレッド数の調整に時間をかけるのも無駄なので、コア数分のワーカーしか立てないと決めていた。 今年はAWSではなくGCPだったので、去年の問題をGCEで構築し一通り癖を把握しておいた。Web UIからの公開鍵の設定やスナップショットの取り方など。 さらにディストリがCentOSからUbuntuに変更されるようだったので、ISUCONに必要なUbuntuのオペレーションも練習しておいた。(といっても普段からDebianをいじってるのであまり差はない)systemdだったのは面くらったけど、やることは大して変わらなかった。

あらかじめチェックリストやオペレーションメモを用意しておいて、それに従ってすばやく足場を組むことを意識していた。 13時すぎまでにはだいたい整えたので、のんびりコードでも眺めるかと思っていたけれど、後述する大きめのトラブルの解決やちょっとインデックス張ったりスコアが変化したときのボトルネックの変化を解析するということをずっとやっていた。 プロファイラとしてDevel::NYTProfの準備を一応していたけど、ディスクI/Oがネックだったので今回はいれなかった。ボトルネックがアプリケーションのCPU利用に移行した段階でいれてたと思う。

しかし、事前にいろいろ準備していたとはいってもやはりトラブルはいろいろある。

トラブル1: MySQL has gone away

PerlのDBIではMySQLとの接続が切断された状態でSQLを投げると、MySQL has gone away というエラーメッセージがでる。 あるタイミングからこのメッセージが頻発するようになって、最初は接続できてるのにベンチ中に接続に失敗することがあった。 スコアが立ち上がる前だったのでとにかく最悪。 これは結局原因がよくわからなくて(原因らしきものは後述)、要は再接続するようにすればよいということで、DBIを Scope::Container::DBI Scope::Container::DBIを書いた - blog.nomadscafe.jp に差し替えて、dbhオブジェクトのキャッシュをやめて、Scope::Container::DBI->connectを毎回呼ぶようにした。

以前にこういうことを書いてた。

少なくとも、PerlのDBIの場合、DBI->connectの返り値であるデータベースハンドラオブジェクトをキャッシュしても、うまくいかない。 キャッシュしている間に、データベースとの接続が切れると、再接続せずにエラーを吐く。 データベース接続まわりのオブジェクトをキャッシュするときは、キャッシュして意図どおりに動作するのかをよく調査したほうがよい。

Webシステムにおけるデータベース接続アーキテクチャ概論 - ゆううきブログ

トラブル2: ALTER TABLEが30分たっても終わらない

entriesテーブルに対するインデックスの作成が2000秒以上かかっていてめちゃくちゃだった。どうみてもディスクI/Oを使いきっていたのでどうしようもなかった。 過去に人数分のインスタンスをたてたりしていたチームがあったようで、それにならってメインのインスタンスのスナップショットからディスクをSSDに変更したインスタンスをたててそちらでALTERを回して、メインのインスタンスに/var/lib/mysqlごとncでとばすということをやった(SSDのインスタンスはもちろんベンチにはかけていない)。今ではSSDが当たり前になってるけど、改めてSSDの速さを実感した。これも最初はスナップショットではなくてVMインスタンスの複製機能みたいなのを使った。これは便利とか言ってたら、数時間前の状態のインスタンスの複製が作られることに気づいて、あわててスナップショットによる複製に切り替えた。

その他、手作り感のある最小限の/etc/my.cnfは読まれずに、debパッケージ付属の /etc/mysql/my.cnf が実は読まれているという罠があった。 これを適当に/etc/mysql/my.cnf/etc/my.cnfに差し替えるとbase dir か data dirあたりがたぶん間違っていてmysqldが起動しなくなる。事前に過去問であれこれ壊したのでハマることはなかった。

立ち上がりはそれほどスコアが伸びなかったことや、途中でトラブルがあって、トラブル解析中に複数の改善をいれていたりしたので、はっきりこの変更がスコアに効いたみたいなのがわからずに進んでいった(failしつつもログの解析はやってた)。 とはいえ、基本はアクセスログ解析とpt-query-digestを丁寧にまわして実行時間の割合が大きい順にクエリを改善していくことを意識していた。 その他は変更の手間が少ないものをやるぐらいで、ボトルネック無視で見当違いのところをチューニングし始めるということはたぶんなかったと思う。 打つ手がなくなってくる終盤はともかく中盤まで1つずつボトルネックをつぶせていった感があった。

最終的には、Nginx - Perl - MySQLの普通の構成でセッションだけmemcachedにいれた。usersのようなメモリ内にキャッシュできるところはアプリケーション起動時にMySQLから引いて親のアプリケーションプロセスのメモリにキャッシュした。あとは普通に各テーブルにインデックスを張り、N+1クエリをなくしていくという感じ。 親プロセスにキャッシュするのは、最初 /initialize でやってたけど、/initialize でキャッシュするとpreforkされた子プロセスのうちの1つだけしかにしかキャッシュされなくて確率的にエラーになるので親プロセスでロードすることにした。

書いてる途中に思い当たったけど、親プロセスでMySQLに接続しつつDBIのattributeでAutoInactiveDestroyが指定されているので子プロセスでdbhオブジェクトが勝手に破棄されて、dbhオブジェクトを使いまわしてる場合うまく動かないかも?と思った。 第30回 データベースプログラミング入門―汎用インタフェースDBIと,O/RマッパTengの使い方(2):Perl Hackers Hub|gihyo.jp … 技術評論社 いずれにしても親プロセスのソケットディスクリプタをforkで引き継いでるところが問題になっていそう。 あとでみてみる。

リポジトリはこちら。https://github.com/yuuki1/isucon5-qualifier

ちなみにMackerelの外形監視でトップページを監視させた。アプリケーションが停止してるときに誤ってベンチしないようにとかいろいろ使いみちがありそう。

blog-ja.mackerel.io

参考

ISUCON予選の準備をするときに特に下記のエントリを参考にさせていただくことが多かった。

あとがき

去年は本戦出場枠に結構ギリギリで滑りこんだので、去年より参加チームの多い今年はかなり厳しいのではと思っていたけど、終わってみれば意外と上位通過でチームメンバーの優秀さをみせつけられた一日だった。 ISUCON、結構メンバーのバランスが重要だと思っていて、全員ある程度サーバをいじれて、ある程度コードを書ける+@みたいなイメージ。 例えば、方針決めたりボトルネック見極めたりはインフラ担当まかせたみたいな感じになりがちのような空気があるけど、ツールさえ置いておけば2人とも勝手にみてくれる。コードだけみて局所最適に走ることが少ない。 同じ会社にいるとその優秀さがだんだん当たり前にみえてくるけど、ISUCONのようなイベントで対外的に評価されることになって、その優秀さは普通じゃなかったんだなということが改めてわかる。

基本はアプリケーションロジックの改善に2人とも集中してもらえたと思うので、スコアにはたいして貢献してないけどとりあえず役目は果たした感がある。 まあまあトラブル多かったわりに意外となんとかなったのは事前準備してやるべきことをわりと早めに終わらせて時間的余裕を稼げたからかなと思う。

インフラエンジニアにとっては複数サーバ使える本戦が本当の力を試されると思う。複数サーバ使うISUCON楽しみすぎる。

ISUCON運営の皆様、すばらしいイベントをありがとうございました。 やりがいのある問題で楽しかった。今回の問題を5台構成で解いたりしてみるとたのしそう。

YAPC::Asia 2015で技術ブログを書くことについて発表しました

日記

YAPC::Asia Tokyo 2015の前夜祭で上記のタイトルで発表しました。 今回が最後のYAPCということで、どのようなテーマで応募するかについてかなり悩みました。 技術的にめぼしい内容はほとんどブログに書いてしまったので、ブログを書くことそのものについて発表してみようと思いました。 内容についても、トークの話の元となる個々の要素についてはほとんど固まっていたものの、どのように構成して取捨選択するかということに時間を使いました。

基本的に難しい話はないので、スライドには極力文字を載せずに口頭の話を聴いていただくという形をとりました。 したがって、スライドだけみても情報量がほとんどなく何の話か全然わからないので、公開はしないでおこうと思います。

トーク内容

トークの内容は前半部分と後半部分に分かれています。 前半は基本的に来ていただいた方々に楽しんでいただくように構成して、トークの主旨は後半部分に集約させています。

前半部分は自分が書いた記事がインターネットで注目されるためにどのような工夫をしていたかというものでした。 工夫といってもそんなに大したことはしていなくて、これまでブログを書いたときに、こういう記事タイトルの付け方を自分はしていましたというものです。 最初から意識していなくてあとで分析したり人に聞いた結果 タイトルというと、タイトル芸や煽りタイトルと呼ばれるようになんとなく揶揄されがちです。しかし、ブログに限らず書籍や雑誌、論文、その他のメディアにおいてもタイトルというのは非常に重要なものだとみなされているはずです。 煽ってタイトルをつけていたこともあったのですが(そんなに伸びるとは思っていなくて驚いたことがあります)煽りタイトルで注目されても、そんなに嬉しくはないなという気持ちが自分にはありました。特にあとで見なおしたときに嬉しいどころか恥ずかしくなるということもあります。 最近では、正統的に内容を表現しつつ、うまく多くの人に読んでもらうためにはどうするかという観点でタイトルをつけています。(このブログの最近の記事を読んでいただければ伝わるかと思います。)

トーク本番では前夜祭ということもあってビールが振る舞われていました。なおかつ最終時間帯ということもあり、結構酔っておられた方が多かったのでオーバーに受け取られた?かもしれません。当日発表者が妙に調子が良かったのでそのせいもあるかもしれませんが。 あまり小手先のテクニックばかりが注目されるのは本意ではないので、具体的な内容は当日トークを聴いて下さった方々の酒の肴にでもしていただければと思います。

後半部分は特にここ半年の月刊ブログ活動において、記事の裏にこめた自分なりの哲学みたいなものを語りました。 サマセット・モームの「どんな髭剃りにも哲学はある」という言葉がありますが、気軽に書ける特性をもつブログにも込められる哲学はあると思っています。 哲学というにはちょっと大げさですが、トーク内容を構成する過程で、僕の場合は6つほどの哲学のようなものを記事に込めているかなということがわかってきました。

知識と感動

「お前が伝えたいのは知識なのか感動なのか?感動がなければどうして知識を伝えられようか」というような言葉を海原雄山という昔の偉い人が言っていました(細部を忘れてしまって多分正確な引用ではないと思います...)。 この言葉は、本当に人に何かを伝えたいときは知識だけでは人には伝わらないから感動を伝えよという意味だと解釈しています。 さすがに今回のコンテキストでは大げさですが、この言葉は自分の心のなかに沈み込んでいるもののうちの1つです。 技術ブログの話に置き換えると、単なる情報だけじゃなくて、どうしてその技術に興味があるのか、どうしてその記事を書こうと思ったのかなどのその人なりの考え方や意見が現れる文章が

ウェブに関する技術情報というのは毎日山のように発信されています。 その中で、単なるツールの使い方のように役に立つけどだれでも書けてしまうものや、バージョンがあがったりすると古くなってときには有害となるようなものもあります。 自分ももちろんそのような内容を書くこともあります。 とにかく発信することが大事だと言われてきましたし、今でもそう思います。 一方で、その人なりの考え方や思想のようなものはもっと息が長いと考えています。 知識は古くなっても、読んだときにこの人おもしろいなとかこのブログおもしろいなと思った気持ちはずっと続くと思います。

ブログ=自己表現の場

人間は褒められた方向にのびると思っています。 もちろん良い面も多いですが、悪い面もあると思うときがたまにあります。 Dockerみたいな新しいツールは若者でも先輩と同等かそれ以上に詳しくなれることがあります。 それがうれしくて新しいツールの使い方をひたすら調べて書きまくるというようなこともあるでしょう。 自分も新しいツールが好きでいろいろ調べてたりしていました。 ただあるとき、新しいツールに詳しいだけの人でいいのかという疑問がではじめました。 アルゴリズムとか計算機そのものの仕組みなど、情報科学の基本的な知識がおろそかになってるんじゃないかといった不安がありました。 今も当然あります。

そんなときに自分の自己表現の場だと思って自分のブログを見返してみて、自分の本来の興味が反映されているかとかを考えてみました。 反映されていなかったらアウトプットの方向性を考えてみてもいいかもしれません。 キャリアとかを見直すきっかけになると思います。

僕の場合、DockerとかGoとか流行っているものに結構飛びついていたんですが、本当はもうちょっとOSとかシステムのアーキテクチャとか、硬派な内容に興味があったはずだと思い直しました。 昔書いた新しいツールの記事は今すでにバージョンが新しくなっていて、あの記事はもう古すぎて意味ないなと感じることもあります。 一方で、OSとかアーキテクチャの話は数年後、がんばれば10年後にも読める内容になるのではないかと思います。 話題に限らず自己表現の場だと思って記事書くと、人間は数年でかわったりしたりないと思うので、勝手に息が長くなるような気がしています。

寝かせる

硬派な内容を書きたいと思っても、硬派な内容というのは得てして難しいのでググって調べたことをそのまま書くだけになりがちでした。 ただ、この技術よくみかけるんだけど、前からよくわからなくてたまに調べてはまだわからん、みたいなことを繰り返して徐々に理解してきてるみたいな内容があるということに気づきました。 自分にとっては、Webサーバアーキテクチャとかコネクションプールがまさにそれでした。 最初にこれらを調べたのが数年前で、その間本を読んだり実際に本番システムの運用経験を積んで学んで寝かせていたことになります。

寝かせることで内容の深みが違ってくると思っています。 例えば、仕事ではPerlとScalaの両方を運用しているので、特定の言語に偏らない話になったとか、もともとつながりのなかった話同士が実は関連していることがわかったりするということがあります。 コネクションプールの文脈で接続コストのTCPだと3-way スライディングウィンドウで輻輳制御のために徐々にウィンドウサイズあげていくみたいな挙動になるから データベースの話にからめて、ネットワークの話をしているみたいな感じですね。

アウトプットベースで考える

ブログを普段から書いていると普段の仕事や趣味をアウトプットベースで考えるようになりました。

突然ですけど、CentOS 5は2017年にサポート切れるという問題がありますよね。 当然、DebianやCentOS 6/7に置き換えていく作業が必要です。 一見めんどくさくてやりたくない最悪の仕事にみえますが、それまで応急処置でメンテナンスしてきたシステムを大幅に刷新できるチャンスだと思いました。 ただし、泥臭いものを単に泥臭く解決すると体面を気にしてアウトプットしづらいため、スマートに解決する方法はないかと考えるようになります。 アウトプットベースで考えることにより、どうすれば技術的におもしろいかを考えて、モチベーションにつなげたりしています。

さらに、なるべく多くの人にみてもらうということを考えるということは、いろんな人に自分のもってる技術をみせられるかということを考えることなので、自分の強みとは何なのかということを客観的に考える機会だと思います。

神は細部に宿る

読みやすさを追求するために、文章自体を書くときに結構細かいことを意識しています。 意識しているのは以下のような内容です。

  • 段落のトピックセンテンスを意識する。その段落で述べることの概略を述べた一文を含める
  • 文をなるべく短くする。とはいえやり過ぎは返って流れにそって読みにくくなるため、きれいに読み下せるなら多少長くなってもよい
  • 箇条書きに頼らない。箇条書きは文と文とつなぐことに向いていないため、あくまで強調したいものを列挙するだけにとどめる
  • 「〜を行う」は冗長な表現なので使わない。大抵は「〜する」でシュッと言い切れる
  • 文の格を揃える。主語と述語が対応しているかを常に意識する
  • 不自然な体言止めを控える。小説やエッセイのようなものには向いているかもしれない
  • 適度にひらがなを混ぜる。漢字ばかりだと日本人には読みにくい。文の密度のバランスをとる
  • 同じ言い回しの連続を避ける。例えば、「〜だと思う」が連続しないようにする
  • 事実と意見を区別する。意見を述べた文の末尾は「〜だと考える。」「〜だと思う。」でくくる
  • 「〜だと考えられる」という表現を避ける。「考えられる」は考えている主体は自分なのに受け身になっていて、考えている主体を曖昧にしている

曖昧な部分やわかりにくかったりぼかしたり部分は突っ込まれることもあるので、細部までこだわって丁寧に書こうとしています。 エンジニアは基本的にそんなに怖い人はいないと思っているので、丁寧に書けば伝わると思います。 もちろん、自分のブログでこれを全てできているわけではなくてブーメランではあるんですが、なるべく意識しようとしています。

文章の書き方については、「理科系の作文技術」をいつも参考にしています。

理科系の作文技術 (中公新書 (624))

理科系の作文技術 (中公新書 (624))

時間をかける

多分数年前の自分がこの文章をみたらブログを書くためだけにこんなのやってるかと考えるでしょう。 もちろんすばやく深い内容を書ける人もいると思いますが、自分のような凡人は記事の品質をあげたかったら時間をかけるしかないと思っています。 1時間で書いた内容はたとえ注目を集めたとしてもやはり1時間の内容でしかありません。 気軽に文章を投稿できるのがブログの良いところです。しかし、ブログに時間をかけてはいけないとは誰も言っていません。 コード書いたり、本を書いたり、論文書いたりするときはやはりそれなりの時間をかけていると思います。 僕の場合は、最近だと調査とか仕込みの部分を除いて1記事書くのに3日から2週間程度かけています。

ただし、2週間もかけて記事を書いて相応のフィードバックをもらえなかったら、自分の場合はモチベーションを維持して書き続けることは難しいと思います。 ちょっとした工夫でモチベーションを持続できるのであれば、それを逃すのはもったいないですよね。 そこで最初の話に戻り、うまく多くの人に読まれる工夫をやってみてもいいんじゃないかなと思います。

もちろんフィードバックとしてインターネットで注目を集めることに興味がなければ別の何かを見つける必要があります。自分の場合も複数のモチベーションをもってブログを書いています。 数値的な指標ももちろんよいのですが、いつも書いた記事を話題にして意見してもらえる身近な人は大事なモチベーションだと最近思っています。

いただいた感想のうちうれしかったもの

yusukebeさんには発表前にも挨拶していただきましたし、はてなブログにも移行していただけて最高という気持ちです。

moznionからもユニークな感想を口頭でいただきました。

あとがき

思い切り自分の内面が全面にだした部分もあるので、人によっては全く考え方が違うということもあると思います。 これは当然のことです。 それでも、「心に響いた」という今までえられなかった感想を何人かの方にいただけました。 技術カンファレンスでこのような話をするのもどうかと多少心配していましたが、発表してよかったと思えました。 ファンだとおっしゃられる方も来ていただいて、数年前書いた記事にも目を通していただいていると聞いて、感激というかそんなこともあるのかという気持ちでした。

本題と直接関係ないですが、ちょうど昨日の夜に@matsumotoryさんが「技術者が研究者のように論文を書くメリットはあるか」というエントリを書かれていました。 実際に論文を書くまでのハードルは高いですが、自分だったらどんな論文をかけるかという観点で自分が持っている技術を見なおしてみるとおもしろいのではないかと思いました。 技術ブログとはまた異なった考え方が見えてきそうな気がします。

運営スタッフの皆様、すばらしいイベントを開催していただき本当にありがとうございました。