ハッカーズチャンプルーで模擬ISUCON
こんにちは。
一昨日、ハッカーズチャンプルーでのISUCON合宿が終了しました。
3日間で10時間くらいしか寝てないので多少お疲れ気味ですw
今回は3日目に行った模擬ISUCONの模様をダイジェストでお伝えしようと思います。
時間は本戦と同じの10:00~18:00の8時間。
参加チームは3つ。
・anpanman (ぼく・disk)
・fukumoto (マサ・ディックス)
・penpen(琉大情報工)
そして題材はこれ。
pixivの社内イスコン。
カタツイさん、ありがとうございます。
では見ていきましょう。
チーム戦になるので、サーバーにログインできるユーザーとしてdiskを追加する必要がありました。
具体的には、authorized_keysにdiskの公開鍵を追加しておくこと。
参照記事がこちら。
ここで手こずり1時間が経過www
この時点で他の2チームはすでにベンチマークを走らせています。
ちなみにチューニングなしでベンチ走らせた場合、Rubyでは3000点弱がスタート。
2.データベースのチューニング
DBの管理は「Sequel Pro」を使う。
ここではインデックスが貼られてなかったので、とりあえずcommentsテーブルにpost_idとuser_idというインデックスを貼っとく。
GUIでインデックス貼れるSequel Proめっちゃ便利。
さぼさんが提供してくれた参考サイト:
なぜ、SQLは重たくなるのか?──『SQLパフォーマンス詳解』の翻訳者が教える原因と対策 - エンジニアHub|若手Webエンジニアのキャリアを考える!
とりあえずここでベンチ走らせたら、3000点→10000点くらいに。
3.アプリケーションのチューニング
まずはUnicornのチューニング。
unicorn_config.rbを開き、worker_processesを4に設定。
これでunicornが連れてくる職人さんが4人に増えた。
次はapp.rb。
実はこのソースコードは何回も見ているので、どこがボトルネックになりそうかはわかっていた。それがこれ。
今回のキモであるmake_postsメソッド。
まずpostsというarrayを用意して、色々ごちゃごちゃかき回して最後にまたpostsに入れてる。
どんどんハッシュを大きくしているイメージかな。
そして最初にresultsという変数がeachで回っているので、そいつの宣言元に行ってみる。
あったあった。
DBからのデータの取り方がよくない。
この処理は「/」にアクセスしたときのもの。
そもそもpostsは1ページに20件表示することになっている。
POSTS_PER_PAGE = 20
あと、deleteされたユーザも考慮に入れてデータを取ってくるようにする。
また純粋なSQL文に書き換える。それがこれ。
get '/' do
me = get_session_user()
results = db.query('SELECT `posts`.`id`, `user_id`, `body`, `posts`.`created_at`, `mime`
FROM `posts`
JOIN `users` ON `posts`.`user_id` = `users`.`id`
WHERE `users`.`del_flg` = 0
ORDER BY `posts`.`created_at` DESC
LIMIT 20')
posts = make_posts(results)
erb :index, layout: :layout, locals: { posts: posts, me: me }
end
クエリのテストはSequel Proで。(もちろんちゃんと走りました)
ここでベンチ走らす。
10000点→23000点
うん、いい感じ。
4.ログファイルの監視設定
とりあえずnginx(女将さん)でもイジイジしとこうかと思ったが、DBにある画像データをpublicに逃がさなきゃ静的配信できないので、ひとまずは女将さんは後回し。
そこで最初に設定するはずのログファイルの監視設定を行う。
tailコマンドで監視できる。
・nginx
nginxのログは
/var/log/nginx/access.log
に吐き出される。
このログを、「alp」を使って整形する。
参考はこちら。
ISUCON 5でalpを使ってNginxのログを解析した話 - Masteries
alpとnginxを連携する作業が必要なのだが、最新版をインストールした場合、ltsvの設定は公式通りにやらないとうまく動かなかった。
動くとこんな感じ。
unicornはaccess.logとerror.logを監視する。
(今回ここはやってないので割愛。どこかで記事書きます。)
まずはgenaral_logをtailコマンドで監視できるように設定。
MySQL :: MySQL 5.6 リファレンスマニュアル :: 5.2.3 一般クエリーログ
もう一つ。
「my profiler」というものを使ってスロークエリを監視する。
KLabさんのgithubに公開されているので、それを参考に。
またこちらも勝手にご紹介。
5.nginxのチューニング
やっときたきた女将さん。
今回ぼくがめっちゃイジイジしたかった女将さん。
ナイスバディにしてあげようと気合い入れて、さぁいざ!
まずはKLabさんの記事を参考にworker_processesを1に、keepaliveを32にしてみた。
ここでベンチ走らせると1000点くらい伸びた。
やっぱり静的配信実現してからじゃないと伸びなさそうと凹む。
ここまでで多分4時間くらいが経過。
6.ググる、焦る、終了
データベースに突っ込んである画像データを逃すことを優先し、diskにバトンタッチ。
しかし
なぜだかうまくできないwwwww
前日はちゃんとできてたのに.....。
途中アクシデントに見舞われ、githubは諦めることに。
diskの方もなかなか苦戦している模様。
とりあえずベンチ走らすが、スコアがほぼ0になる始末。
そんなこんなで、あーだこーだしているうちに18:00。
終了!
最終スコアがこちら。
さぼさんwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
残り時間半分くらいから参戦してこのスコア。
さすが、お師匠さんです。
ぼくら学生チームはというと、まぁ僅差ですねwww
どうやらこの差はベンチ走らす時間とタイミングの差らしい。
ネット環境によって多少の誤差は生じるとのこと。
7.模擬 ISUCONを終えて
正直、スコア的には満足いくものではなかった。
が、得るものはスコア以上に大きかった。
一つ目に、「ISUCONがどんな感じなのか」ということ。
意外にも8時間は短いような気がした。
ぼくの場合、めっちゃ飯食うし、うんこ何回もするのでどうにかしないと...。
二つ目、「ログファイルの設定の重要性」。
ぼくらはまだ経験が浅いので、直感でどこ触ればいいのかまだわからない。
そのガイドをしてくれるログファイルは、時間をかけてでも用意しておくべきだった。
目標は開始から1時間くらいで全て揃えられること。
三つ目、「やっぱりまだ全然力不足だね」。
「あれ、なんでここできないんだろう?」ということが多々あった。
正直難しいことはしてないんじゃないかと思ったりもしたが、やはりそこは基礎ができてない証拠。
また一から出直してきます。
また、今回ぼくの個人的な目標として、
「できるだけ多くのエラーにあたる」
があった。
まぁぼくの場合何してもエラー出るので、目標ってほどのものでもないが、ここの経験を得られたのはかなりよかった。
正直、動くもの作るより、エラー解決したりする方が好きなのかもしれない。
実りの多かった模擬ISUCON。
次回は15万点目指して、また一から精進します。
ハッカーズチャンプルー2017 〜1日目〜
おはようございます。
お久しぶりです。
しばらく更新が途絶えてましたが、ちゃんと生きてます。
最近何してたかというと、初心に戻って基礎を勉強しておりました。
そしてハッカーズチャンプルーに参加しております。
この3泊4日の開発合宿を通して、スキルアップを図ろうというわけです。
最終目標は模擬ISUCONを行って、1ミリでもスコアアップする。
今は2日目の朝。
初日は開会式?を行い、参加者で交流会。
クラフトビール屋に行ったのですが、志賀高原と湘南のビール2杯だけで2500円...。
でも美味しかったなぁ。
と、初日はゆるゆるでしたが、今日(2日目)から気合い入れようと思います。
そして重大な報告。
今までぼく、マサ、ディックスの3人でチームを組んでましたが、この合宿からもう一人加わることになりました。
DSKです。
(後ほど詳しく紹介するかな...)
ISUCONは3人で1チームですので、誰か1人は出れません。
ってことで出場エントリーまでのどこかで、出場できる3人を決めるチーム内ISUCONを行います。
あ、もう9時。
ぼくも必死なのでそろそろ作業開始したいと思います。
AWSまで触るでぇぇぇぇぇ!!!!!!!!!!!!!!
ではまた。
さぼさんのGit講座を受けました 〜Git〜
こんばんは。
先ほどココイチで「馬モツ煮込みスクランブルエッグカレー500g」を食べて今日という1日を終了させようとうしています。
ですが
昨夜はさぼさんの3.5時間にも及ぶGit講座を受けたので、これをまとめないわけにはいかない。
ってことで、今回はGitのまとめしまーす。
と、その前に
先にマサが書いているのでそちらもどうぞー。
Gitってなぁに??
Gitとは、ソースコードの変更履歴を管理するもの。
実は、Gitを作ったのはLinuxの開発者なんです。
その開発者が、Linuxを全世界の人と共有し、開発してブラッシュアップしていこうってことでGitができた背景があるみたいです。
Gitを使った一連の流れ
ここから実際にさぼさんに教わったGitの使い方をまとめていきやす。
まずはターミナルを開きます。
$cd でホームディレクトリに移動し、
$mkdir Git_practice でディレクトリを作り、そこに移動。
移動できたら上のコマンド。
この 「git init」はそのディレクトリ配下をGitの管理下にする。
つまり、このディレクトリで変更したり、追加・削除したファイルは履歴に残せるというわけ。
また、ディレクトリ直下にgitファイルがつくられる。
※test.txtは作っておきます
すると、「.git」が作られてるのがわかりますね。
ここでtest.txtをてきとーに変更し保存。
ターミナルに戻り、
これでcommitの準備完了。
そしていざcommit!
この時メッセージを添えますが、その内容は変更点の内容がざっくりわかるようなものがいい。
例えば、「ログイン機能実装」とか「バグ修正」とか。
これで変更履歴をローカルに残すことができました。
ここで $tig というコマンド打ってみよう。
すると
こんな画面が出ます。
これは、commitのログ的なやつ。
的なやつというか、それですww
ここで追加したコードとか差分が見れる。
例えば、緑文字の
「+ISUCON2017」
は、「ISUCON」が「+」、つまり追加されたということがわかる。
このtigの使い方は、
「あれ、あの時どんな変更したっけ?」
とか
「あの時のコードに戻したい」
みたいなときに使える。
使い方はvimみたいな感じで、
j:下に進む
k:上に進む
q:終了・戻る
で操作する。
ここまでが一連の流れ。
おさらいすると、
1. 「git init」 でgit使えるようにする
2. ファイル変更
3. 「git add 変更したファイル」でcommitの準備
4. 「git commit -m "メッセージ"」で履歴登録完了
こんな感じですかね。
もうちょいGit使いこなそうぜ
さっきの続きから。
Atomを開いて、てきとーに変更して保存。
ここでは add も commit もまだしていない状態。
ここでgitの状態を確認したい。
そんなときは $git status
するとこの画面。
赤文字で「modified」と出てる。
これは「変更してるファイルがあるよけど、まだaddしてないよー」って意味。
ここで
「あれ、どこ変更したんだっけ?」
ってなったらどうするか。
そんなときは、 $git diff
これは、直前のcommitから現在の変更した部分の差分を見るもの。
これでOKだったらaddしてcommitすれば完了。
ファイルの状態ってどうなってんの
「untracked」ってのは、「gitがまだ知らないよー」ってこと。
つまりファイルを新しく作った時とかやね。
「unmodified」は「変更なし」。コミット直後とかこうなるね。
「modified」は「変更した」。
「staged」は、「addはしてるけどcommitまだやねー」。
つまり「commit準備完了」ってとこかな。
今回はさぼさんによる基本的なGitの使い方をまとめました。
今までなんとなくGit使ってたけど、コマンド叩くだけであんま理解してなかったなぁww
そんな頭空っぽのぼくにGitを叩きこんでくれたさぼさん、超絶アザッス!!!!!!
ってことで、次回は「GitHubの使い方」。
ではでは、今日はこの辺で。
「中間テーブル」ってなんぞや
こんばんは。
今日は、今朝に就活先の会社から「次の選考に進んでください」連絡が入り、さっきさぼさんに大学近くの油そばご馳走になって、お腹も気分も満たされた良い1日でした。
と言いたいところですが、1つだけ満たされないことが。
そう、タイトルの通り、「中間テーブルってなんぞや」問題です。
今日締め切りだった課題の「LINEを作る」は、この中間テーブルに手こずって未完成となってしまいましたが、なぜか次の選考に進めるみたいですww
(冒頭に書いた会社とは別です)
もちろん、このまま未完成に終わるのは悔しいので最後まで完成させます。
ってことで今回は「中間テーブル」についてまとめていきます。
中間テーブルってなんぞや
例えばの話。
学校の授業を思い出してください。
国語やら算数やら体育やらありますよね。
んで、もちろん生徒は1人ではなく30人ぐらいいます。
マサは国語と算数と理科と社会の授業に出てる。
ディックスくんは国語と算数と体育と図工。
(おめーらもっと授業出ろよww)
このとき、「isucon_school」というデータベースには
・studentsテーブル(学籍番号、学年、名前、性別、etc)
・lessonsテーブル(科目名、先生の名前、教室、etc)
があるのはなんとなくわかりますね。
さて、先生は「どの授業に誰が出てるか」を知りたい時どうすればよいのか?
そもそも、1つのレコードに対して各データ項目は1つしか入らないんです。
けど、国語の授業にはマサとディックくんの複数人がいる。
逆に、マサは4つの授業受けてるし、ディックスくんもそう。
つまり、「多:多」の関係なんです。
(かなり説明省いてます。すいませんww)
ってことで、あら困った。
これを解決してくれるのが、やっと出てきた
「中間テーブル」
なんです。
話を戻すと、先生が知りたかったのは、
「どの授業に誰が出てるか」
でした。
ってことで、「studentsテーブルの名前」と「lessonsテーブルの科目名」を紐付ければよさそうです。
この紐付けによってできたテーブルが「students_lessonsテーブル」で、「科目名」と「名前」のデータを持つ中間テーブルとなるわけです。
と、理解できたのはここまでww
実際に開発していこうとすると分からなくなり発狂しそうです。
ってことで、今回は中間テーブルについてでしたが、ぼくとしてはDB設計の大切さについて学んだ感じでした。
ではでは、今日はこの辺で。
松田、LINEを作るってよ
こんばんは。
夜中の2時でもギンギンのビンビンで開発してます。
何を作ってるかと言うと、「LINE」
というのも、就活先の企業の選考課題なんです。
本来ならRailsで作りたいところですが、あくまでISUCONの勉強として今回はSinatraを使います。
これがまたむずい。
特にデータベース。
今回mysqlを使っていますが、今までほぼ触ってなかったので全然わからん。
ちょうど今、1:1のトークができるように複数のテーブルを繋ぐみたいなことしてますが、「中間テーブル」なるものの存在を初めて知り、悪戦苦闘中です...。
そしてもっとわからないのが「Pry」
完全にここでハマったので、気分転換にこれを書いてる次第ですww
自分でもあんまりわかってないけど、やっぱり動くと嬉しいし、コードが読めて書けるようになるのは成長の実感が湧くからいいですね。
提出期限は5月15日の昼12時まで。
この場で披露できるように頑張ります。
あ、せっかくなのでGitHub載せまーす。
よし、もう少しやろう。
R.I.P.マギー, Welcome ディックス
こんばんは。
本日2度目の投稿ですwww
突然ではありますが、早速メンバーの入れ替え事案が発生しました。
マギー、逝く
タイトルの通り、マギーが逝きました。
「逝った」と言っても、彼は死んだわけではありませんwww
やりたいことがあるんだと。
まぁ、こういうことですwww
あ、やりたいことってのはラーメン屋じゃなくて、もっと大っきくて壮大なことらしいです。
我々としても彼のやりたいことはできるだけ応援したい。
君の分まで頑張るからね。
R.I.P. マギー。
さて、1人いなくなってしまった。
どうする。
ようこそディックス
なんてことはございません。
マギー脱退が決定して数秒後の様子がこちらです。
はい、即確保wwwwwwwwwwwww
その名もディックス
由来は...はい、「dick」からきてますwwwwwww
「正真正銘のディックス」
彼はこのTシャツを着てきましたwwwwwwwww
実はディックス、マサの高校の後輩なんですよ。
あと色々話聞いてると、すでに大学の単位150ぐらい取ってるとか、エストニア留学するために休学中とか、パソコン教室通ってるとか。
色々と活動的な面白いやつです。
ってことでディックスを迎え入れました!
すでに正式メンバーとして、着々と課題をこなしています。
そしてチーム名も決まりました。
その名も
「仕事ください」
ww
新体制となったチーム「仕事ください」。
みなさまにはどうかまた、温かく見守っていただけるとありがたいです。
よろしくお願い申し上げます。
・ディックス
「Webを支える技術」を読んで 〜HTTPの基本〜
こんにちは。
世間はGWですが、人権のないぼくにそんなものはありませんww
ここ最近滞っていたアウトプットを一気にしたいと思います。
あと、メンバーの小ネタも別記事で書いていこうかなと.....wwww
では、いきまぁっぁあぁぁす!!!!
前回は「URI」のお話でした。
今回からはwebを支える技術の3本柱の1つ、「HTTP」についてまとめます。
HTTPの基本
ここで1冊目の「プロになるためのWeb技術入門」をおさらいすると、
TCP/IPは郵便屋さんの役割やったね。
情報をパケットという単位に分けて送受信しているんやった。
ここら辺の話をもうちょっと詳しくすると、インターネットのネットワークプロトコルは階層型になってるそうな。
んで、その階層ごとに担当するプロトコルがある。
どういうことかと言うと
・アプリケーション層
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
・インターネット層
→ IP
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
・ネットワークインターフェース層
→ イーサネット
IPが担当するのは下から2番目の「インターネット層」。
ここでは、パケットという単位に分割してデータを実際にやりとりするんや。
ちなみにこいつは「データを送り出すだけ」しかやらないらしいwww
そしてTCP 。
こいつはその上の「トランスポート層」を担当。
ここでは、IPが送り出したデータをTCPが転送する。
TCPでは接続先の相手に対してコネクションを張る。
このコネクションを使ってデータの抜け漏れをチェックしているんや。
んで、接続したコネクションで転送するデータが、どのアプリケーションに渡るかを決定するのがポート番号 。
ちなみにHTTPは80番やったね。
ここまでまとめると、
①インターネット層でIPがデータをトランスポート層に送り出す、
②トランスポート層に渡ってきたデータを、TCPがポート番号で指定されたアプリケーションに転送する
こうやね。
HTTPの仕組み
基本的な仕組みは、「クライアント/サーバ」。
クライアントが出したリクエストをサーバで処理してレスポンスを返すというもの 。
この時、クライアントがやっているのは、
・リクエストメッセージの構築
・リクエストメッセージの送信
・(レスポンスが返るまでの待機)
・レスポンスメッセージの受信
・レスポンスメッセージの解析
・クライアントの目的を達成するために必要な処理
めっちゃ色々やっとるやんw
んで、同じくサーバがやっているのは、
・(リクエストの待機)
・リクエストメッセージの受信
・リクエストメッセージの解析
・適切なアプリケーションプログラムへの処理の委譲
・アプリケーションプログラムから結果を取得
・レスポンスメッセージの構築
・レスポンスメッセージの送信
HTTPの性質
HTTPの重要な性質の「ステートフル性」。
Cookieとかセッション状態とか出てきたけどもうちょっと詳しく。
ハンバーガーショップの例。
・ステートフルなやりとり
店員:「いらっしゃいませ。ご注文は?」
マサ:「セブバーガーセットで。」
店員:「サイドメニューは?」
マサ:「ポテト」
店員:「ドリンクは?」
〜〜〜〜省略〜〜〜〜
店員:「以上でよろしいですか?」
マサ:「はい。」
店員:「かしこまりました。」
.....うん、普通やねwww
ぼくらの日常会話はステートフルな会話ってことやな。
んじゃ、ステートレスなやりとりとは?
・ステートレスなやりとり
店員:「いらっしゃいませ。ご注文は?」
マサ:「セブバーガーセットで。」
店員:「サイドメニューは?」
マサ:「セブバーガーセットをポテトで。」
店員:「ドリンクは?」
マサ:「セブバーガーセットをポテトとコーラで。」
〜〜〜〜〜〜〜〜〜〜〜省略〜〜〜〜〜〜〜〜〜〜〜
!?、マサがめんどくさい&ラリってるwwww
なるほど、ステートレスなやりとりってのは、毎回全ての注文を繰り返さないといけないわけやな。
一方のステートフルなやりとりでは、店員が毎回の注文を覚えているんやね。
このやりとりはweb上だと、クライアント(マサ)/サーバ(店員)になる。
一見ステートフルなやりとりの方がイケてるように見えるが、実はそうでないらしい。
ステートフルの欠点は、クライアントが増えるにしたがって、サーバが毎回のリクエストを覚えることが難しくなってくる。
ステートレスはこの点を解消している。
最終的なリクエストは、「セブバーガーセットのポテトとコーラ」。
それまでのやりとりをサーバが忘れていても、リクエストメッセージにこれがあれば、サーバはちゃんと認識してくれるってわけやね。
けど、ステートレスにも欠点がある。
それは、いちいちリクエストを送らなければならないので
「送信するデータが多くなる」。
これはパフォーマンス低下につながる。
まとめると、
ステートレスなアーキテクチャはスケーラビティの面でめっちゃ優秀だけど、パフォーマンス低下の欠点もある。
ってことやな。
次回は「HTTPのメソッド」について。
ではでは、今日はこの辺で。