ISUCON8(予選)参加記

ISUCON8に参加してきました。 今年から社会人枠ということで絶対本選出てやると思って挑んだわけですが結果は爆死という。

編成

今回は Bremen というチーム名で、前回も一緒に出ていた @Goryudyuma さんと ISHOCON2 で会った @owlworks さんとで参加しました。 言語は Golang を使いました。

  • bgpat: インフラ, アプリケーション
  • Goryudyuma: アプリケーション
  • owlworks: アプリケーション

当日まで

練習としては、個人参加の ISHOCON2Yahoo! JAPAN さんの LODGE に集まって ISUCON7 の予選をやったのと、 突然平日の夜中に始まった ISUCON4 の予選をリモートでやりました。

ISUCON4 予選は OS が CentOS だったというところから選択したのですが、 今問題を作るなら CentOS7 だろうなということでベンチマーカーとアプリケーションだけ使ってインフラ部分は ConoHa の CentOS7 イメージを使いました。 (普段触らないので /tmp にファイルを吐くと他のサービスから触れないとか事前に知れてよかった)

みんな vimmer ということで前回作った bgpat/isucon-boilerplate を使い回しました。 / を git に沈めてソースコードだけでなく設定ファイルもまとめて管理しようと思って作ったリポジトリで、 rootssh ログインすると git commit したときのユーザーがそれぞれの GitHub アカウント名になるのと vimgit add されていないファイルを開いて :w したときに変更前の状態で自動コミットしてくれるというスクリプトが入っています。 昨年は 2FA を有効にしていると git push できなかったので今年は Deploy Key を登録して誰でも push できるように変えました。 github.com

あとは予選から複数台構成が予想されたのでモニタリング環境を整えました。 netdata + Prometheus + Grafana で CPU とメモリの負荷状況は1画面で見れるようにしました。 GitHub - bgpat/isucon-monitoring: Monitoring Environment with Prometheus + Grafana

予選当日

競技前

前日準備する予定が寝落ちしてしまったけど、幸い起床バトルには余裕を持って勝ったので GitHub に競技用のリポジトリを作って自分がやることの issue を立てていった。

github.com

会場は mixi さんのオフィスをお借りしました。 (ありがとうございました)

mixi.connpass.com f:id:bgpat:20180917233336j:plain

競技開始

サーバー全台に bgpat/isucon-boilerplate 流し込んで root にパスワードなしで入れるようにするのと、 いろいろ入れてモニタリング環境を整えたりしていました。

f:id:bgpat:20180917234039p:plain

あとは DB のスローログと Nginx に kataribe を入れる予定だったのですが、まさかの H2O だったので前者だけ入れておきました。 ログについては slackcat で Slack のチャンネルに投げて rotate するスクリプトを書いて、ベンチが終わった後に手動で実行する運用にしました。

f:id:bgpat:20180917234645p:plain

アプリケーションを触り始める

インフラの作業が終わったので2人が読んでくれてたアプリケーションのコードを触っていきました。 まず、複数人で同じファイルを触ると確実に conflict するので app.go を細かく分ける のと ローカルでビルドしたバイナリをサーバーにデプロイするタスクを Makefile に追加しました。

MySQL の CPU 負荷がボトルネックということはすぐにわかったので slow log を見て GetEvents が原因というのも簡単に探せました。 @Goryudyuma とペアプロして N+1 を消していきました。

Makefile が用意されていて運営さん親切!! とか思ったけど慣れていない gb を使いこなせなかったのでdep に置き換えたりもした。

中盤

やることがなくなって暇になったので OpenCensus を入れて Jaeger でトレーシングできるようにしたりしてた。 (真面目にアプリケーション読んでおけばよかった)

f:id:bgpat:20180918000931p:plain

きれい

後半

reservation の処理が重かったので Redis にのせて早く裁こうとしたけど気付いたのが遅すぎた。 結局実装しきれずタイムアップ。

最終的には GetEvents も消しきれず Redis を使ったのも効果が出るところまで行かずで とりあえず形だけ複数台構成にしておきました。

  1. nginx + DB
  2. application
  3. application

f:id:bgpat:20180918001445p:plain

点数は 出すのも恥ずかしいくらい とだけ書いておきます。

感想

途中アプリケーションの中身を見ずに使いもしないトレーシング入れたのは戦犯だったなと思います。反省します。 ただ、他のメンバーが取り組みやすいようなインフラは結構いい感じに作れたんじゃないかなと思っています。

ダッシュボードが高機能化してたり問題のコード量がめちゃくちゃ多かったりベンチマーカーが席順がランダムじゃないとか怒ってきたり運営さんほんとにすごいなと思いました。 面白い問題を提供してもらって本当にありがとうございました。

OpenLDAP + Postfix でメール転送サーバーを建てたかった話

qiita.com

この記事はkstmアドベントカレンダーの21日目です。

僕が所属している kstm はいろんな情報系のコンテストに参加しているのですが、ほとんどの場合は代表者のメールアドレスを運営に伝えて連絡をとります。 これ、致命的なミスに繋がったことがあって、

このときは遅刻した人からメールアカウントのログイン情報教えてもらってロスは少なく済んだのですが、信用している相手とはいえ他人のログイン情報とか触りたくないわけですよ。

Google Groups とか使ってメーリス作ればいいんでしょうけど、-ml がつくのカッコ悪いし、勉強のためにも自分で作ってみようってことでメール転送サーバー的なものが欲しいなーって話をしています。 受信ボックスを用意してもいいんですが、以前メールサーバー運用をしていたときにみんなGmailに転送設定していて誰もIMAPとかPOPとか使ってくれなかったので今回はSMTPサーバーだけあればいいです。 メールアドレスくらいみんな持ってるし困らないよね。

あとは、メンバー管理とかも兼ねて LDAP 使いたいなと。 ネットワーク機器がそこそこの量あるので RADIUS と連携させれば認証情報を集約できて幸せになれる気がする。

ってことで作ってみた。

github.com

OpenLDAP + Postfix (+ saslauthd) の構成。 どうせならDockerで動かしたいなと思って探してみたけどよさげなのがなかったのでDockerfileから書いた。 git clone して docker-compose up -d すればサンプルっぽいのが動くはず。

LDAPのデータ構造はこんな感じです。

f:id:bgpat:20171221164009p:plain

Groupの子要素ひとつひとつがメーリスになっていて、Peopleの中に登録したユーザーをメーリスの下にエイリアスを張って所属を表現しています。 メーリスとユーザーにはそれぞれメールアドレスを登録しておいて、メーリスのメールアドレス宛にメールが届いたときはメンバーのメールアドレスに転送するという仕組みです。

LDAPとか運用したことがないので 所属関係 をどうすればいいのかわからずエイリアス使った感じです。 この辺りどうすればいいのか分かってないので詳しい人いたら教えてほしいです。

LDAPのデータをPostfixで扱うときは ldap_table を使えばよさそうです。 エイリアスを使ってるため dereference=1 にしておかないとグループのメンバーにはたどり着けないので注意。

あと、メーリスのアドレスを使ってメール送信もしたかったので、saslauthdを使って認証できるようにしました。 こここのへん の設定で認証したユーザーがメーリスのメンバでなかったときに弾いています。

saslauthdはデーモンとして動くのにUNIXソケットしか待ち受けできないので扱いを迷ったのですが、 Dockerの1コンテナ1プロセスの原則に従ってイメージを分けました。 entrypoint.sh にごちゃごちゃ書くより volume mount 使えばいいやって結論になりました。

という感じで、動かすまであと一歩のところまでは作ったのですが、 今話題のKubernetesで運用したいなーとかやってるといろいろハマって結局Docker化したところで止まってます。 (どうやらオンプレでやろうとしているのが原因らしい、GCPとかAWSみたいなクラウド使えばすぐ動かせそう)

@kstmの部員 だれか動かしてくれませんか

ISUCON7参加記

3回目のISUCON本選に学生枠で出場しました。

カッコイイ名札。

机が狭かったので目立たなかったですが、今年も参加してたわにさん。

一緒に出たメンバー

準備

予選が終わってから ISUCON7予選, ISUCON4決勝 をみんなで練習、あとは本番に向けてファイルシステム全体を git で管理するためのテンプレを作ったりしました。

練習は ISUCON5決勝 もやりたかったけどプロビジョニングがうまくできなくてパス、懇親会で動かせた人がいたと聞いたので是非公開してほしいです。

あとは、GitHubでやりとりする予定だったのでテンプレを import して当日用のリポジトリを作っておきました。 github.com

やったこと

  • / を git の管理下に沈める
  • 全員分のSSH鍵を入れる
  • fail2ban を殺して回る
  • 初期実装のままベンチ回してtopで負荷率見る
  • 実装言語をgolangに切り替えてベンチ回す
  • 2,3台目のサーバーにバイナリをコピーして systemctl restart するタスクを Makefile に書く
  • make しなおしてベンチ回す
  • @fono09 に入れてもらった kataribe を眺めたり、 mysqlslowdump を見るが WebSocket 以外のボトルネックがわからない
  • WebSocket まわりのコード読み始める
  • DBを調べてた @Goryudyuma と相談して room_name ごとに決まったサーバーで処理する方針に決める
  • なんかバグる
  • またバグる
  • 結局直らずどこが悪いかもわからなくなったのでほぼ初期実装にもどす
  • @Goryudyuma が書いてた big.Int 周りの最適化を手伝いながらやり直したら通った
  • 4台目のサーバーでもアプリケーションを動かし始める
  • pprof で見た感じ big.Int が遅すぎるのでいろいろ触ってみるがバグったり変化がなかったりで時間切れ

構成

3台動いていたアプリケーションサーバーを4台目にも入れて、それぞれ localhost のDBを見に行くようにしました。 すべてのサーバーが同じ構成で app と mysql が動いています。

ポータルに指定する先は1台目のサーバーのみチェックを入れていましたが、 負荷走行自体はすべてのサーバーに分散されるので、どれかひとつでもチェックがついていればいいという状況でした。 ただし、ルーム名で振り分けているので負荷が偏ってスコア誤差が±5,000点という超運任せ。

Redis や golang でオンメモリ化しようみたいな話も出ましたが、 トランザクションが面倒くさそうだったのと、CPUとメモリに余裕があったので諦めました。

感想

CPU・メモリ・ネットワークのどれも詰まっていないのに点数があがらない、 kataribe は通用しないし、スローログもトランザクションのコミットばっかりで問題がわからない、 big.Int が重そうみたいなのがわかってもどう対処すればいいかわからず手が付けられない、 みたいな状況がずっと続いていてかなり苦しいコンテストでした。 コードもあんまり書けなかったし…

優勝チームが対策していた big.Int のメモリアロケートのところとか、 見直せば pprof でちゃんと見えてたんだよなーってなるので悔しいです。

結果は全体12位で半分よりは上なので、まぁよかった(?) 学生枠では4位で、2,3位と僅差だったのでベンチマーカーにはもうちょっと空気読んでほしかったですね。(負け惜しみ)

就職するので学生としての出場はこれでラストですが、次があればまた出たいです。

強いkstm部員になるために(技術編)

この記事はkstm Advent Calendar 2016 24日目の記事です。

qiita.com

どうも、11月からkstmのサークル長になったbgpatです。

先日の Advent Calendar でこんな記事がありました。
toritoeikenken.hatenablog.com
まぁ、20人もいれば食う側の人間と食われる側の人間に分かれてしまっても仕方ないかなと思うところですが、それでよしとされてしまってはサークル全体の成長を望む僕としては辛いところです。

強いkstm部員になるには暴力体力とか煽り力とかいろいろあるわけですが、今回はその中でも技術力にフォーカスを当てて紹介したいと思います。

1. 体力

まず、いちばん大事なのは体力。わりとまじで。
技術を身につけるのって結構体力いるんですよ、ただし筋肉とかは別になくてもいいです。

kstmにいて一番技術力が身につくのは強い先輩についていくこと。
ただ、わからないことが出てくると諦めたくなるもんで、これが結構大変。

ここで大切なのはやるぞって決めたときに最後までやり通して、多少無理しても次の日とかに響かないように調整する能力。
ようするに体調管理ができてりゃいいです。

そんなに難しいことではないと思いますが、一人暮らし率の多い信州大学生にとっては管理してくれる人がいないパターンが多いので一度崩すと持ち直すのが結構大変なんですよね。

2. 環境

kstmは"ものづくりサークル"って名乗ってる通り、ソフトウェアから肉体までビルドするサークルです。
とはいえ、肉体ビルドはサークル活動の中でほんのわずかで、ほとんどは情報分野が占めます。

さて、情報技術を学ぶための環境ですが、僕が思う一番重要な環境は"端末"だと思います。
要するに普段使うパソコンです。

kstmの情報リソースとしてはラックマウントサーバーとかスイッチなどのネットワーク機器とかRasPiみたいなIoTデバイスがあります。
これらを有効活用して使いこなすにはUnix系のOSが簡単に使えるのが近道です。

現部員はMac使いが多いですが、Linuxがマトモに動くPCならどれでも問題ないです。(まともに動くPC自体が少ない)

ちなみに、信州大学ではWindows専用PCが推奨パソコンになっていますが、あれはLinuxを運用しようとするとディスプレイのバックライトが真っ暗になったりBluetoothが使えなかったりいろいろ問題が起こるのでオススメしません。
買う前にはちゃんと調べようね。

3. 実績

kstmの活動に限ったことではないですが、実績としてアピールできるものがあれば強いです。

出れそうなコンテストとかあれば積極的に参加しましょう。
参加するだけでも実績になります、結果が残れば尚よし。

あと、継続したことも評価されることが多いです。
ただし、証拠が残せないとアピールはしにくいかも。

そういう意味ではだいたい毎週開かれてるAtCoderとか、コード書いたことが全部残るGitHubとかすごくいいです。

そういえばGitHubについてはどっかで見た気がしますね。

goryudyuma.hatenablog.jp

4. 得意分野

kstmの強い人達を見てみると、なんか一つは得意分野があります。
全体的にまんべんなくできるってのもいいですが、○○について聞くならあの人!みたいに言われるようになるとそれだけで強いです。

できるだけ他の人とは被らないほうが得な気がします。(ニッチすぎても使い道に困るけど)
ちなみに今いる強い人達の得意分野を上げてみるとこんな感じ。

リストアップしてみるとB4率高い。B2とB3勢にはもうちょい頑張ってほしい。

5. アウトプット

集めた情報は発信してこそ意味があると思うんですよね。
どれだけ周りに価値が提供できるかってことではなくて(これはこれで重要だけど、どっちかというと実績になる気がする)、人に見られてるのを意識するだけでもぜんぜん違うと思います。
情報の整理整頓みたいに考えるといいかも。

方法はなんでもいいですが、一番のオススメはTwitter
気軽に情報発信できる雰囲気がいいです。
もちろん公開アカウントね。

この Advent Calendar もいいですね。
思ってた以上にみんな参加してるし、毎月あれば結構な量の記事が揃うんじゃないかなって。
こういうの続けていきたいね、うん。

まとめ

kstmに入るために技術力を問うようなことはしませんが、入ったからには強くなって欲しい。

タイトルに(技術編)とか付けてしまったので誰か別のも書いてくれると嬉しいなー。

ISUCON6参加記

kstm(カスタム)でISUCON6の本選に参加してきた。今回も学生枠。

サークル部屋にあったわにさんも一緒に参加

予選はDBオンメモリ化とかやって(あんまり効果なかったけど)なんとか学生枠の9番目に滑り込んだ

10:00 - 11:00

競技が始まっても問題がデプロイできなかったのでレギュレーション読んでた。修正後も1回デプロイに失敗してちゃんと動くようになったのがたしか11時くらいだった気がする。

11:00 - 12:00

docker-compose.yml 見たり Node.jsのサーバー読んだりして構成把握してた。Node.jsでHTTPS使ってたりappにリバースプロキシしたりしてたのでとりあえずNginx入れる方針に。

前回みたい(学生チーム全Fail)にはなりたくなかったので5台あるサーバーの1つ目だけ使ってました。(実はwebappが1つ目のサーバーにしかなかったことには後で気づいた)

appをgolang実装に切り替えてスコアが4,174=>6,630に

12:00 - 13:00

appは全部馬さんに任せて、NginxからNodeとappにリバースプロキシする設定をした。

まずNginxいれて80番ポート開けてみたものの、外から接続できないという事態に。どうやらAzureのファイアウォールのせいだったみたいなんですが、このときは気づかなくて2つ目のサーバーにNginxいれて443ポートで接続できるのを確認。NodeのTLSの処理を全部Nginxに移して、あとはgzip圧縮したファイルを静的配信とかした。

このあたりでスコアが9,000くらいまで上がるようになって1位2位あたりをうろうろ。

13:00 - 14:00

ベンチ回しながらtopを眺めてるとMySQLとNodeが結構CPU食ってたのでそれぞれ3つ目4つ目のサーバーに移した。ディレクトリごとscpでコピーして`docker-compose up -d`すればいいだけなのでめっちゃ楽だった。

13:30くらいにスコア16,000を超えて全体で1位に。

14:00 - 15:00

/img/:idが重かったのでなんとかキャッシュできないかなーと。

馬さんがstrokeのキャッシュ、ふぉのさんがNginxでキャッシュ、僕は馬さんがコード書いてるのを見ながら頷くみたいな担当で動いてた。

NodeがCPU使いきれてなかったのでdocker-compose.ymlに同じコンテナをもう一つ建てるように書いた。

このときスコア18,000くらい。

15:00 - 16:00

Nginxでのキャッシュがうまくいかず、点数があがらない

strokeのキャッシュが実装完了して20,000点くらい。

16:00 - 17:00

ちょっと早めの再起動試験。

systemdの設定とか書くの忘れててDockerがあがってこなかった。このタイミングで再起動試験しててよかった。

なんかやることもなくなってきたのでDBのオンメモリキャッシュとか書き始めた。

17:00 - 18:00

DBのオンメモリキャッシュは何故かFailするのでボツ。

17:20にはもう一回再起動試験をしてちゃんと上がってくるのを確認。あとはベンチガチャ何回か引いて20,000点以上が出たらそのまま放置してFinish!
するつもりだったのだが...

結果

f:id:bgpat:20161028080205p:plain

おまけ

pixiv冬インターン参加記

ssl.pixiv.net

pixivにインターンに行ってきました。

まだ就活とかする時期でもないんですが、「東京に行ける!新幹線!報酬まで出る!」という不純な動機で応募したら通っちゃいました。

選考

選考はgithubだけでした。選考でやったことはこんな感じです。

https://github.com/pixiv/intern2015w/pull/7

 

1日目

まず、開発環境のセットアップ。結構複雑な作業のはずですが、特に詰まることなくすらすらできたので、インフラの人すごいなと思いました。

メインのバグ修正は、修正してプルリク送ると、メンターからフィードバックが貰えるというもの。バグごとに難易度がつけられていて、まずいちばん簡単なものから取り掛かりましたが、なかなかの量のソースコードなのでどこを触ればいいのかわからないまま時間が・・・。もっと積極的に質問しまくればよかった。

特にバグ修正もできず、お昼休憩。🍣でした。おいしかった。

午後は本格的にバグ修正に取り掛かりました。修正して、commitして、プルリク投げて、"脱出"タグ付けられて「よっしゃああ!!」ってなりました。ただ、ここまですんなり行ったのは最初だけで、ブランチ変え忘れてたり、あんまりコード読まずに修正して無駄な部分指摘されたり、なかなか脱出できなくて現実は甘くないなと感じました。

2日目

1日目の反省から、分からないことがあったらすぐ聞く のスタンスで挑みました。聞いてみたらすごく丁寧に教えてもらえたので、本当に助かりました。午後はちょっと重いバグをずっとやってました。コード読んで修正して、上手くいかなかったらメンターさんに方針を相談して、という感じでした。結局時間内に修正できなくて、時間があればなんとかなりそうだったので後悔はありますが、pixivのソースのかなりの部分が読めたので満足です。

懇親会では、エディタの話とか、普段はなかなかできないマニアックな話ができて楽しかったです。splatoonほしい。

まとめ

インターン行ってよかったです。Web開発の現実が見れた気がします。参加していた人もみんなレベルが高くて、もっと勉強しないと、と感じました。

pixivの皆さん、インターン生の皆さん、2日間ありがとうございました。

ISUCON5本選に学生枠で参加しました

bgpatです。
所属しているサークルの先輩2人(@fono09, @Goryudyuma)とチーム名kstmでISUCON5の本選に参加してきました。

午前

まず、予選の教訓からapt-get purge apparmorしました。初回ベンチかけてる間に環境の確認。使い慣れてるMySQLじゃなくて全く使ったことのないPostgresqlが入っていて、コレどうしよう状態。psqlコマンドはこのとき初めて使いました。ベンチ終わってnginxのログとかブラウザで確認したりして、/dataが重いなーということでコード読み始めました。一緒にコード読んでた@Goryudyumaが外部サーバーに対してHTTPリクエスト送ってるのが原因と教えてくれたので、このあたりを調べることに。ローカル環境からAPIのホストを叩いても案の定名前解決できなかったので、サーバー内の/etc/hostsを見るとAPIサーバーのアドレスが書かれていました。ローカルのhostsに同じ設定を書くとブラウザからAPIを叩けるようになったのでメンバーにも共有。とりあえずAPIのリクエストをキャッシュすれば早くなるのでは?と提案だけして、@fono09にredisの設定とかやってもらい、golang書けないのでコードは@Goryudyumaに書いてもらいました。

13:00〜17:00

何も考えずとりあえず全部キャッシュするコードが完成したのでベンチ回してみるとよくわからないエラーを吐いてfail。ブラウザでAPI叩いて確認すると、tenkiは高頻度で更新されているみたいなので、キャッシュから除外するように修正するがfail。このあともいろいろ触ってみたけど最終的にはnullしか表示されなくなって、せっかくGO言語使ってるんだしということで、APIリクエストの並列処理のほうをやってみることに。並列化処理完成してブラウザでチェック、よし問題なさそう と張り切ってベンチ回すもなぜかfail。しかもapp.goが死んでる。ログを見るとJSONのパースで落ちてるらしいことが分かり、Resp.Bodyをログに吐き出すようにすると、何も入ってなくてイミガワカラナイ。懇親会で聞いたところによると、ちょっと工夫してログに出せば"Too Many Requests"が見れたんだとか。このあともキャッシュがうまくいかない原因を考えてみたり並列処理なんとかできないか触ってみましたが、ことごとくfailしまくってお通夜状態でした。

17:00〜終了

結局打てる手もなくなり、同じサーバーの中にAPサーバーいっぱい立てれば並列処理になって少しは早くなるかもとか考え出して、やってみてもうまく動かず結局ほぼ初期状態に戻す感じでフィニッシュ。時間もなく、ほぼ初期状態だったので再起動確認はしませんでした。学生チームが全チームfailになると知っていれば再起動確認の時間残したのに。

反省

大体どのチームとも方針は変わらなかったのに、考察しきれてない部分が多くて全く点数が伸びず、最終的にfailに終わってしまいました。予選のときは、ほぼノー勉で挑んで、たまたま自分たちに合った環境が問題になってスコアが伸びたけど、本選で惨敗して、甘くないなーと実感しました。来年もISUCONがあるなら、運ではなくて実力で予選突破できるように練習とかちゃんとしたいです。

まとめ

コンテスト自体はボロボロでしたが、長時間パソコンに向かってみんなで考えたり、プロが書いたコードが見れたり、懇親会ですごい人たちと話したり、東京見物したり、ほんとに楽しい充実した日となりました。運営のみなさん、本当にありがとうございました。

おまけ

会場に着いてから暇だったのでこんなもの書いてました。せっかくなので置いておきます。