インターン生向けのISUCON CM

（esaのプレゼンモードで当日は発表しました）

## 突然ですが、質問です

* MySQLなどにデータを保存するWebアプリケーションを作ったことはありますか？
* Linuxサーバーにsshしたことはありますか？
* AWSやGCPやさくらのVPSやさくらのクラウドなどなど、そういったサービスを使って自分専用のサーバーを作ったことはありますか？

あっても、なくても、皆さんにおすすめな情報があります！！

## ISUCONとは

> お題となるWebサービスを決められたレギュレーションの中で限界まで高速化を図るチューニングバトル、それがISUCONです

* 優勝賞金は100万円！
    * 学生枠なら2位まで賞金が出ます！
* 予選が9/17,18（土日）のどちらか（リモート参加）
  * 予選で上位チームに入れば本戦出場
* 本戦は10/22（土）
  * 会場はLINE本社。遠方の学生は旅費負担！
  * [ISUCON6 学生限定で本選参加時の旅費負担を実施いたします！ : ISUCON公式Blog](http://isucon.net/archives/48239334.html)
* 3人チーム（2人でも可だが、1人はダメ）

## ISUCONについて

* [ISUCON6 出題チームに聞く！今年のISUCONどうなんですか？学生にこそ参加してほしいってどういうこと？ : ISUCON公式Blog](http://isucon.net/archives/48241450.html)
* [「ISUCONの楽しさや参加するメリット、得られる経験って何？」ISUCON5 出題チームインタビュー : ISUCON公式Blog](http://isucon.net/archives/44869745.html)
* [ISUCON 夏期講習 2014 を開催しました : ISUCON公式Blog](http://isucon.net/archives/39768356.html)

## Webアプリケーションのチューニング

* やったことがある人いますか？
* どういったところがチューニングする必要があると思いますか？

## 実際のWebアプリケーション

* 実際のWebアプリケーションでも、様々な事情でパフォーマンスに問題が出ます
* アクセスが少ない時は問題が無くても、アクセスが増えた途端に問題が起こることもあります
* そういったWebアプリケーションのチューニングを競技にして競い合うのがISUCONです

## 実際のISUCONの問題と流れについて

* 過去問について話すと練習問題が減ってしまうのと、一般論みたいなものを話すと自分が出題者側ということもあり、だいぶ危険なので、pixiv社内ISUCONを解く際の導入部分のみ話します
  * [ISUCON6出題チームが社内ISUCONを開催！AMIも公開！！ - pixiv inside](http://inside.pixiv.net/entry/2016/05/18/115206)
* ISUCONの予選問題に問題傾向や難易度を似せてあるので流れは分かるはず
* [ISUCON予選突破を支えたオペレーション技術 - ゆううきブログ](http://blog.yuuk.io/entry/web-operations-isucon)
  * 今回の話とかぶる部分があるので必読
* この話でISUCONのおもしろさが少しでも伝わって、出てみたくなったら幸いです

## ポータルサイトでスコアを計測する

* ポータルサイトがあり、ベンチマークを実行することができる
  * 自分のスコアを計測できる
  * 自分のサーバーに対してリクエストが来る
  * このスコアが一番高かったチームの勝利！

<img width="512" alt="3cb985e1-8bf8-4972-8612-0ae0a98847c3.png" src="https://qiita-image-store.s3.amazonaws.com/0/9930/d3ab4320-5cba-4f3e-0630-965426b23704.png">


* スコアの計測ができてから言語実装の切り替えなどを行う（重要）
  * 構成を変える毎にスコアを計測しないと、スコアを計測できなくなったときに何が原因か分からなくなる
    * 極力差し戻せるような作業を意識する
  * 社内ISUCONは初期実装がRubyだったのでRubyを選択した人は必要なかった
  * 切り替え方法はアナウンスがあるので従う
* 実装を切り替えてスコア計測までできたら、構成を変える

## ボトルネックの調べ方

* 大きいところから絞っていく
  * チューニング全てにおいて言えること
  * どのページでどれだけ時間を使っているのか？から調べるのがよい
  * どう調べるか？
* フロントサーバーにnginxを使用しているので、nginxのアクセスログからベンチマーカーのアクセス傾向を調べる
  * 各ページの実行回数と実行時間が取りたい

## nginxとアプリケーション

* nginxはアプリケーションの前段に置かれている
  * ユーザー => nginx => APP
* アプリケーションにもよるが、PHPやRuby(unicorn)などの場合はアプリケーションサーバーはマルチプロセスモデルで動く
  * 1reqを1プロセスが担当するというアーキテクチャ
  * 1プロセスのメモリ消費量がそれなりに大きいので、1台のサーバー上に大量のプロセスを起動できない
  * CSS・JSなど静的ファイルの配信などでも1プロセス占有される
  * アプリケーションは動的に生成する必要があるコンテンツを返すために用意されたもので、静的ファイルで使う必要は無い
  * クライアントが遅い回線を使用していた場合、クライアントにリクエストを送りきるまで1プロセスが占有される
* nginxはイベント駆動のアーキテクチャ
  * 1プロセスが複数リクエストを受けられる
  * ロジックは書けない（luaやmrubyを除く）が、高速にレスポンスを返せる
  * 静的ファイル配信のようなアプリケーションを通す必要がないものはnginxから直接返してしまえば良い
  * 遅いクライアントに対してレスポンスを返す時はnginxがバッファリングしてくれるので、アプリケーションはnginxに対してレスポンスを返すことだけに注力すれば良い
* nginxでログを取る
  * アプリケーションからレスポンスが返ってくるまでに何秒かかったのかログを取ることができるので、それを使うことでアプリケーションのボトルネックやリクエスト数が多いページなどを調べることが容易にできる
  * ログファイルはLTSVにすると集計スクリプトを書きやすい
    * [Labeled Tab-separated Values (LTSV)](http://ltsv.org/)
    * nginxだとlog_formatで、`$path`と`$upstream_response_time`を出力すればよい
  * 集計スクリプトは事前に作るか、ツールがいくつか公開されているので使い方を調べて使う
    * IDなどURLは変わっても同一と見なしたいものがあるので、正規表現などを使ってまとめられるようにする

参考：

* [Reverse Proxy がなぜ必要か - naoyaのはてなダイアリー](http://d.hatena.ne.jp/naoya/20140826/1409024573)
* [nginx実践入門 (WEB+DB PRESS plus) : 久保 達彦, 道井 俊介 : 本 : Amazon.co.jp](https://www.amazon.co.jp/dp/4774178667)

## アクセスログの解析結果

```
sort by total_time
    avg     total   count   method  path
    0.31    256.54  820     GET     /image/:id.jpg
    0.42    78.17   188     GET     /
    0.32    48.55   152     GET     /image/:id.png
    0.56    39.45   71      GET     /posts/:id
    0.27    36.40   134     POST    /login
    0.54    27.13   50      GET     /@:user
    0.37    23.32   63      GET     /js/jquery.timeago.js
    0.35    21.83   63      GET     /favicon.ico
    0.32    20.40   63      GET     /js/jquery.timeago.ja.js
    0.32    20.24   63      GET     /js/jquery-2.2.0.js
    0.29    17.82   62      GET     /css/style.css
    0.27    16.92   62      GET     /js/main.js
    0.28    12.58   45      POST    /
    1.25    9.98    8       GET     /posts?max_created_at=xxx
    0.36    9.84    27      GET     /image/:id.gif
    0.14    5.13    36      POST    /register
    0.14    4.91    35      GET     /admin/banned
    0.37    3.74    10      GET     /login
    0.09    3.14    35      POST    /comment
    0.42    2.93    7       GET     /logout
    0.02    0.02    1       GET     /initialize
```

* `GET /image/:id.(jpg|png|gif)`をなんとかしないと行けない
* `GET /`も重い
* とりあえず静的ファイルはnginxから直接配信した方がよさそう


## ベンチマーク実行中のプロセスの様子を確認する

* topを見る

![75eb7310-dd3c-4272-a951-cf65bc698653.png](https://qiita-image-store.s3.amazonaws.com/0/9930/8645d30c-82d0-efb2-16ba-cb073b70ed0b.png)

* CPUが200%とっている。 CPUがボトルネック
* mysqlが200%maxのうちの150%を占めている

## 実行されているSQLを知る

* 言語ごとのSQLのライブラリ
  * 各自調べてください
* MySQLのgeneral_logやslow query logを使う方法
  * slow_query_logをONにしてlong_query_timeを0にすると、全てのSQLがスロークエリログへ出力されるので、動作させながら確認すれば、ページ内で実行されるSQLが簡単にわかる
  * long_query_timeを0.001とかに調整してtailしながらベンチマークをかけると、重いクエリだけを効率的に見ることができる
  * slow_query_logを集計してくれるツールとしては、percona-toolkitのpt-query-digestが有名

## MySQLのインデックス

```sql
-- TABLE構造
CREATE TABLE comments (
  `id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `post_id` int NOT NULL,
  `user_id` int NOT NULL,
  `comment` text NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) DEFAULT CHARSET=utf8mb4;

-- 流されていたクエリ
SELECT * FROM `comments` WHERE `post_id` = 4391 ORDER BY `created_at` DESC LIMIT 3
SELECT COUNT(*) AS `count` FROM `comments` WHERE `post_id` = 10123
SELECT * FROM `comments` WHERE `post_id` = 8314 ORDER BY `created_at` DESC
SELECT COUNT(*) AS count FROM `comments` WHERE `post_id` IN (451,2755,3634,3657,3799,4564,6249,6852,7683,8521,8915,9247,9572,9875)
```

* インデックスを使えるSQLを書けば高速にアクセスできる
  * ぜんぶpost_idのINDEXがない
  * INDEXを使うとB Treeを使って効率よく探索することができる

![4d087213-1a59-4e95-aeb1-4f691da8ef5d.png](https://qiita-image-store.s3.amazonaws.com/0/9930/de61e5e0-5e39-e7bb-66cb-3518f6cb78a6.png)

cf: https://ja.wikipedia.org/wiki/B%E6%9C%A8

## ここから先は実際にやってみましょう

* 今回紹介したのは最初のさわりです
* まだまだ先はあるので是非解いてみて欲しい！！

## 今年のISUCONについて

* ISUCON4はAWS、ISUCON5はGCPでしたが、今年のISUCON6はAzureです
* Azure登録時にもらえるクーポンで基本やるので、お金はかからないはずです
    * （もしチーム全員がクレジットカードを持っていなければ運営に相談してください）
* 最新情報はtwitterを見ていれば流れてくるはずです
* 参加登録締め切りは __2016年9月9日(金) 12:00:00 JST__ です
    * 登録は早めにしてくれると喜びます

＿人人人人人人人＿
＞ __今すぐフォロー__ ＜
＞ [@isucon_official](https://twitter.com/isucon_official) ＜
＞ __今すぐフォロー__ ＜
￣Y^Y^Y^ Y^Y^Y^￣

## ISUCONで学生枠1位を取るためには

（自分がやるならこうするという話です）

* ISUCONの過去問をチーム全員で解いてみる
  * ここ数年のISUCONの過去問はAMIなどで公開されているのですぐに試すことができます
  * pixivの社内ISUCONもAMIが公開されています
  * VagrantやDockerでも試すことができるので個人でやるときはこちらでも良いかも（チーム練習は本番に近い環境がおすすめ）
    * [matsuu/vagrant-isucon: ISUCON過去問を構築するためのVagrantfile集](https://github.com/matsuu/vagrant-isucon)
    * [matsuu/docker-isucon: Dockerfile for isucon](https://github.com/matsuu/docker-isucon)
  * 本番の時間に極力合わせてやる（10時〜18時）と、細かいことも分かっておすすめです（どれくらいでお腹が空くかなど）
* 解きながらか、解いた後に作戦会議をして役割を決めておく
  * 最初の30分から1時間くらいはやることが大体決まっているので、あらかじめ役割分担を決めておきましょう
  * ISUCONは時間との勝負なので最初の方は話し合っている時間もコスト
  * 開発手法（手元で構築するか、インスタンス上でやるかなど）も決めておく
    * 参考：自分たちのチームは手元で構築していました（過去に手元では容易に開発できない問題も出題されたことがあるので要注意）
  * 予選はリモートで行うので場所やご飯をどうするかなども決めておきましょう
* 選んだ言語のプロファイリングの取り方を確認して、必ず使ってみる
  * 基本的にやったことがないことをISUCON当日にやるのは危険です
  * 他にも使う可能性がありそうなツールやライブラリは過去問などを使って、実際に使ってみましょう

## ISUCONに

* そろそろ出たくなってきましたか？
* 質問したいことも出てきたと思います
* なのでここから質問タイムにしたいと思います
    * その前に予想FAQを話します

## 予想FAQ

* インフラの知識がありません
  * そもそもアプリケーション側を変更しなければ、基本的に上位に食い込めないのでインフラだけをやればよいという大会ではないです
  * 過去のISUCONの問題は全て公開されており、ここ数年のものならばAMIなども公開されていて簡単に試せるようになっているので、必ず練習しておきましょう
  * 新卒研修用のハンズオンの資料もあるので、それもおすすめ
    * [ハンズオン講義](https://gist.github.com/edvakf/dc50f8cabf8d452e47ac63156245a296)
  * 過去のISUCONの問題を解いていれば、最初でつまずくことはないはず
* 大学内に一緒にチームを組んでくれる人がいません
  * インターン生同士で組みましょう
  * Web系の会社のインターンに参加するメリットは、Webに興味のある同世代と出会えることです
* 勝てる気がしません
  * 無料のお祭りなので勝ち負け気にせず参加しましょう
  * 実は学生枠から本戦に参加できるチーム数が去年の倍の10チームになりました
  * 一般枠の激戦ぶりに比べると、学生枠で本戦に行くことは桁違いに簡単なので、チームで一緒に過去問を解くなど練習をしておけば十分狙えます
  * 学生枠なら2位まで賞金があるので頑張ってください！
* Webアプリケーションを作った経験がない OR 参考実装に得意な言語がありません（ISUCON6の予選で実装予定の言語実装：Ruby/PHP/Go/Perl/Python/Node.js）
  * いい機会なので勉強してみることをおすすめします
  * ISUCONではRuby on Railsのような重厚なフレームワークは使われず、例年の参考実装はRubyの場合はSinatraのような薄いフレームワークが使われています
  * 極力フレームワーク固有の知識などは必要が無いように、例年作られている（というかそうしないと他言語の実装を用意できない）ので挑戦しやすいです