おれ、エンジニアになるよ。

エンジニア志望の大学生だった若造がISUCON7を通して見事就職した後、今度は一人前のエンジニアになることを目指す成長物語

SRE サイトリライアビリティエンジニアリング

こんばんは。

またまたお久しぶりです。

 

早速近況報告ですが、本日、「面白い会社」のインターンが決まりました。

超憧れのインフラエンジニアの方がいる会社です。

 

インターン内容はまだ決まってないのですが、ぼくの要望を聞いていたただきまして、インフラ関連の業務をやらせていただけるとのことです。

 

なのですが

 

 

 

 

インフラの経験がありません!!www

 

 

そもそもなんでインフラやりたいのかと言うと、

「ISUCONでミドルウェアとか触っているから」っていうのが一つ。

 

あとは、ぼくの勝手なイメージですが、インフラエンジニアの方って職人さんみたいで渋くてかっこいいんですよねwww

ぼくも昔職人やってたというのもあって、そういう人には憧れがあるのですよw

 

 

 

ってことでお師匠さんからオススメいただいた、とある本を読んでいこうと思います。

 

それがこちら。

 

SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム

SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム

 

 

GoogleのSREチームが書いた本で、Google社内の事例を交えながらSREとはどんなことをやるのか、スキルセット、管理方法など、SREに関する全てが網羅されています。

 

 

!?

 

SREとは?????

 

 

 

 

 

 

SRE(サイトリライアビリティエンジニアリング)

 

訳すと、

サイト信頼性エンジニアリング

 

 

ようわからんのでざっくり言うと、

 

サイト・サービスの性能やセキュリティを向上させるエンジニア。

 

(で、いいのかな??)

 

はたまた、

 

インフラエンジニアの進化系。

 

というイメージです。

 

 

Googleが提唱したこの言葉は、今や日本ではメルカリとかが採用しているみたいです。

 

tech.mercari.com

 

 

こんな感じでSREの紹介はこのぐらいにして、これからガンガン読み進めていこうと思います。

 

 

ではでは、今日はこの辺で。

 

 

 

 

ISUCON夏期講習@LINE本社に参加してきました

こんばんは。

 

先ほど沖縄に帰還したぼくです。

やっと帰って来れて、やっぱ沖縄がいいなぁと感じてます。

東京はクソ暑いので1日3回ぐらい着替えるし、渋谷駅で線路に靴落とすしで割と散々でしたwww

 

今回は、8月25日に参加してきたISUCON夏期講習の内容について。

場所はLINE本社。

f:id:matsuda-juri:20170827040723j:plain

 

 

中の様子はこんな感じ。

 

f:id:matsuda-juri:20170826220522j:plain

 

(ぼくがどこにいるか当てることができたら、お礼にチューします)

 

 

 

講師は面白法人カヤックfujiwara組長さん

日本のインフラエンジニア界のリビングレジェンドです。

www.kayac.com

 

過去のISUCON戦績は、

ISUCON1 優勝

ISUCON2 優勝

ISUCON3 出題

ISUCON4 3位

ISUCON5 優勝

ISUCON6 準優勝

 

つえぇぇぇぇぇぇぇ。

かっこよすぎる.......。

正直抱かれてもいいです。

 

そんなfujiwara組長さんを講師に迎えてのISUCON夏期講習。

めっちゃ面白かったです。

ではその内容を!!

 

 

1.ISUCONで戦うためには

 

まず、ISUCONで勝ち上がるためにはいくつかの要素が必要であると。

 

・OS、ミドルウェアのチューニングのみでは絶対に勝てない

・アプリケーションを書き替えるスキルは必須

・DBの知識

・効率の良いアーキテクチャの知識

ボトルネックを的確に発見する能力

 

こうしてみると、今ぼくら「仕事ください」に足りないものがはっきりしてくる。

(あえてここでは言わないので過去記事から探してくださいww)

 

 

これに加えてチームのメンバー構成も重要。

fujiwara組長さんがオススメするメンバー構成がこちら。

 

・OSやミドルウェアに強い人:1名

・アプリケーションに強い人:2名

 

f:id:matsuda-juri:20170826221338j:plain

 

ここは前回の第4回模擬ISUCONで痛感した部分でもありました。

そうなんです。

アプリケーション触らないと点数が伸びないのです。

これは大いに納得。

 

 

そしてこの3人でどうチューニングするか。

その例をいくつかご紹介頂きました。

 

・1リクエスト当たりのレスを短くする

・静的ファイルはwebサーバで配信

・appからstorageへのクエリを減らす

・storageでdiskアクセスを減らす

・そもそもクライアントからリクエストさせない

・並列度を上げてレイテンシを隠蔽する

 

f:id:matsuda-juri:20170826222031j:plain

 

正直、目から鱗です.....

ちなみにISUCON1で優勝したときの1秒当たりのリクエストのスコアは、

1500req/sec

だそうです。(よくわからないけどなんかすごそう)

 

 

さらにISUCONで優勝するための必勝法を伝授して頂きました。

それがこちら。

 

1.ボトルネックを探す

2.解消して計測

3.1と2の繰り返し

4.優勝

 

ほう、わかりやすくていい。

まさに「Simple is the BEST !!」

 

 

最後にあの名言を残します。

 

f:id:matsuda-juri:20170826222735j:plain

 

「推測するな計測せよ」

 

はい、いただきましたー。

肝に命じておきます!!

 

 

ここからハンズオン形式の実践編に入ります。

 

 

 

2.実践編

 

扱う問題はISUCON6予選。

第4回模擬ISUCONでやりましたね。

 

matsuda-juri.hatenablog.com

 

基本的にお師匠さんが教えてくれた通りと同じ。

けど計測方法や手順が少し違ったのでちょこっと紹介します。

 

まずはレギュレーションをよく読むこと。

ISUCONはここから全てが始まる。

 

「あれ、初期実装はどの言語??」

 

なんてことはレギュレーションを読めば書いてある。

センター試験の現代文と同じです。(違うか)

お師匠さんからも耳にタコができるくらい言われました。

 

 

お次はバックアップを取ること。

特にサーバーをいじる前にやるべし。

過去の大会では、サーバー上の画像ファイルが消えたら強制的に試合終了だったとか...

安西先生も真っ青です。

git管理は言うまでもなく。

 

 

これらの準備を終えてやっと計測に入ります。

fujiwara組長さんは基本的にalpで整形したnginxのログと、mysqlのスロークエリでボトルネックを探すみたいです。

(プロファイラは使わないって言ってたかな)

 

そして中でも一番の新たな知見だったのがnetdata。 

 

f:id:matsuda-juri:20170826224326p:plain

 

f:id:matsuda-juri:20170827025833p:plain

 

ポート番号を19999にしてブラウザ叩くとこんな感じでCPUの使用率とかが細かく確認できるってもの。

fujiwara組長曰く、topコマンドやhtopコマンドでもいいのだが、若者ウケしないらしいwww

(ちなみにぼくはhtopコマンド使う)

 

 

あとはpt-query-digest

スロークエリを集計して解析するのに便利なやつ。

pt-query-digest

 

 

これらを駆使してボトルネックが見つかったらやっとチューニングが始まります。

ISUCONではボトルネック一つ潰したら、また次のボトルネック、そのまた次...みたいな感じに計算されて作られているので確実に潰していきます。

 

 

一つ潰したら、gitで管理。

もちろん動いてるプロセスも確実に再起動させる。

途中で絶対に再起動コマンド叩くのが面倒になるので、そこはMakefileなどを用意しておくのがいいとのこと。

 

 

最初の1、2時間はスコアにこだわらず、ログやコードの解析に時間を費やすともおっしゃっておりました。

逆にその時間内にスコア出るほうがおかしい。

たしかにそうですよね。

 

 

最後にアプリケーションに関して言うと、

ループしている箇所があったら確実に潰すべし

とのアドバイスを頂きました。

 

ちなみに最後にベンチ回したらスコア7272

模擬ISUCONの時よりも1500点ぐらい上がった感じ。

f:id:matsuda-juri:20170827034831p:plain

 

 

 

3.感想

 

めっちゃ面白かったし楽しかった。(小学生並みの感想ww)

新たな知見も得られつつ、今までやってきたことにさらに自信が持てた。

ほんとにあとはアプリケーション触る時間をどれだけ増やすことができるか。

そこにかかっていると思います。

 

 

ってのも、ぼくの隣の席の人、お師匠さんの記事見てましたwww

 

saboyutaka.hatenablog.com

 

 

 

4.おまけ

 

アフターではピザやらチキンやら盛りだくさんのフードとビールで乾杯。

(余ったビールは持って帰りましたww)

割と主催の941さんとお話してたんですが、琉大情報工チームのメンバーはどうやら有名人らしいですww

 

あと、うちのお師匠さんのこと知ってました。

なので勝手にギークハウス沖縄を宣伝w

941さん、9月にオープン記念イベントあるので来てください!!

(行かないって言ってたけど)

 

 

 

こんな感じでかなり楽しめたISUCON夏期講習会。

主催のLINE株式会社さん、941さん、講師の面白法人カヤックfujiwara組長さん、貴重な機会をありがとうございました!!

本戦出場できるように、また明日から精進していきます!!!

 

 

 

 

 

 

あ、お土産のLINEのステッカー忘れてた。

まぁいっか。

 

ではでは、今日はこの辺でー。

 

 

 

 

第4回模擬ISUCONやりました

こんばんは。

昨日から東京に来てるぼくです。

実は明日の8月25日にLINE本社で行われる学生限定のISUCON夏期講習のためにきております。

isucon.net

 

チーム「仕事ください」の代表として、沖縄の風を吹かしてやろうかなと。

 

 

あ、あと先日メルカリでアラレちゃんステッカーを買いました。

 

 

 

.......はい、そうなんです。アラレちゃん大好きマンです。

届いたらPCに貼ってお披露目しよっと。

 

 

では、近況報告はこのくらいにして本題の方へ!

 

 

 

第4回模擬ISUCON開催

 

先にマサの記事はっつけておきます。

masa-world.hateblo.jp

 

 

 

そしてごめんなさい。進歩がなかった第3回はなかったことにしますww

一応過去のやつ貼り付けておきます。

 

第1回

matsuda-juri.hatenablog.com

 

 

第2回 

matsuda-juri.hatenablog.com

 

 

 

そして今回の問題はISUCON6予選。

GitHub - isucon/isucon6-qualify

 

久しぶりにチーム「仕事ください」4人全員集合 + お師匠さん参戦。

もちろん場所はギークハウス沖縄。

ぼくはキャバクラにあるようなソファで参戦しますwww

f:id:matsuda-juri:20170823223619j:plain

 

 

 

今回もAzureで立ち上げます。

なのですが、プロビジョニングがうまくいかないのお師匠さんが修正してくれました。

それがこちら。

GitHub - saboyutaka/isucon6-qualify

 

 

 

1.いつもと同じです

 

はい。ログやらツールやらはいつもと同じです。

上の過去記事で割愛ww

 

 

 

2.仕様がいつもと違うぞ

 

今までの仕様はアプリケーション1つ。

けど今回は3つもありました。

 

・isuda

viewが表示するメインの部分

 

・isutar

ふぁぼった時にぽちぽちされる星の挙動を制御する部分

 

・isupam

keywordをpostする時に不適切な言葉が入ってないかチェックする部分

 

 

これら3つをsystemctlで起動させて初めてスタートします。

今までになかった構成なので少し戸惑う。

 

あと初期実装はPerl

なので実装言語をRubyに切り替える必要あった。

 

 

3.毎回恒例、ボトルネックを探せ!

 

まずはnginxのログでボトルネックを探します。

もちろんalpで整形したログをね。

※すいません、またもやキャプチャ忘れました

 

特に重いのが

get " / "

 

たしか4000msもかかってた。

クエリも13ぐらいだったのでN + 1もなさそう。

 

よって最初のボトルネックとなるのは、どうやらトップページとなりそうです。

 

 

 

4.rack-mini-profiler登場

 

アプリケーションのチューニングを行う時、ぼくらはいつもローカル環境でいじいじします。

そこでいつも使っていたのがrack-lineprof

GitHub - kainosnoema/rack-lineprof: Rack middleware for easy line-by-line profiling using rblineprof

 

とあるリクエストに対して、どの処理に何秒かかっているかがわかるので一発でボトルネック探すことができる。

これはめっちゃ便利なのですが、今回はお師匠さんのススメで、

rack-mini-profilerというgemを使います。

GitHub - MiniProfiler/rack-mini-profiler: Profiler for your development and production Ruby rack apps.

 

まぁ好みだとは思うんですが、ぼくはmini-profiler、マサはlineprofでやります。

 

この時点で

・ぼくはnginxを見ながらマサとアプリーションコードの解析

・diskとディックス君でDB周りとその他もろもろ

 

こんな感じでやっております。

ちなみにスコアは0で、初期スコアのまんま。

 

 

5.スコア0地獄脱出

 

今回のボトルネックはトップページです。

マサとコードの解析をやりましたが、前回の反省を踏まえて、

「コードと実際の挙動(ブラウザ)を照らし合わせる」

 

を意識。

今までよりも丁寧にコードを読んでいった感じです。

 

 

プロファイラからもわかるのですが、犯人はこいつ。

 

def htmlify(content)
keywords = db.xquery(%| select * from entry order by character_length(keyword) desc |)
pattern = keywords.map {|k| Regexp.escape(k[:keyword]) }.join('|')
kw2hash = {}
hashed_content = content.gsub(/(#{pattern})/) {|m|
matched_keyword = $1
"isuda_#{Digest::SHA1.hexdigest(matched_keyword)}".tap do |hash|
kw2hash[matched_keyword] = hash
end
}
escaped_content = Rack::Utils.escape_html(hashed_content)
kw2hash.each do |(keyword, hash)|
keyword_url = url("/keyword/#{Rack::Utils.escape_path(keyword)}")
anchor = '<a href="%s">%s</a>' % [keyword_url, Rack::Utils.escape_html(keyword)]
escaped_content.gsub!(hash, anchor)
end
escaped_content.gsub(/\n/, "<br />\n")
end

 

このhtmlfyは、ユーザーが投稿したワードを全件取得して色々分解して組み立てなおして、最終的にキーワードにしてリンクを作るというもの。(多分)

gsubとかRegexpとかよくわからんが。

 

まぁ、最終的にキーワードのデータがほしいとのことなので、全件取得する必要がないと判断。

isuconではお決まりのパターンやね。全件取得作戦は。

 

keywords = db.xquery(%| select * from entry order by character_length(keyword) desc |)

 

なのでこれを

 

keywords = db.xquery(%| select keyword from entry order by character_length(keyword) desc |)

 

こう。

* を keywordに変えただけ。

 

f:id:matsuda-juri:20170824155147p:plain

 

すると3000msも縮まっていい感じ。

このままベンチ走らせます。

 

 

"fail":0の4583点!!

 

念願のスコア0地獄から抜け出せた。

 

 

再度ベンチ走らすとタイムアウトしたりするのでnginxのkeepaliveあげたりと色々いじいじ。

女将さん(nginx)をナイスバディにしてあげて5700点くらいまで上がりました。

 

 

 

6.静的ファイルどうにかしたい

 

alpでnginxのログを確認します。

 

f:id:matsuda-juri:20170824160316p:plain

 

jsとかcssが厄介だったのでどうにかしたい。

なのでnginxで対処しようと思いました。

 

参考にしたのがこれ。

blog.shibayu36.org

 

単にexpiresつけるだけだったんだけど、なぜかうまくいかずハマった。

気づいたらタイムアップ。(オワタ....)

 

終了後にさぼさんからもらったアドバイスとしては「キャッシュ作戦」

 

 

 

7.反省

 

Done

f:id:matsuda-juri:20170824162020j:plain

 

ToDo

f:id:matsuda-juri:20170824162055j:plain

 

今回のISUCON6予選問題は今までやってきた中で一番ムズかった。

てかよくわからなかったwww

DBはそんな重くないし、N+1問題はないし、とにかく過去の経験がほとんど通用しない今回であった。

 

よかった点としては、まずスコアが出せたこと。

これは嬉しかった。

落ち着いて丁寧にコード解析していけばいい感じ。

 

あとは各設定とかかな。

自分のとこは今回素早くできたので手空いたらサポートに回れるようにしたい。

 

 

一番の反省は

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

 

今回はsinatraが激重だったのでより痛感した感じ。

やっぱりここがっつり触らないと点数伸びないね。

 

あとは自分の女将さん(nginx)愛が強すぎてずっと女将さんとイチャイチャしてしまうところww

結果論だけど、あのままnginxをもっとチューニングしてもスコア伸びなかったぽい。

もっと女将さんを理解して、「nginxよりもsinatra」っていう優先順位をつけていきたい。

 

 

色んな反省点がある中で、今後の取り組み方も見えてきた。

 

・1人がログファイルやconfなどの各種設定

・2人でソースコードの解析

 

nginxのログとrubyのprofilerでだいたいのボトルネックは推測できることがわかった。

いつもそうだけど、ログファイルの設定とかconfファイルの設定に時間がかかりすぎるんだよねぼくたち。

なのでここらは1人でやって、残りの2人でアプリケーション本体を触っていくほうがよさそう。

 

 

とまぁ、こんな感じです。

肝心のアプリケーション頑張りまする。

 

最後に、お師匠さんがまとめてくれたisuconで使うツールのまとめ記事をはっつけて置きます。

これでアプリケーション触る以外の逃げ道がなくなったwww

 

saboyutaka.hatenablog.com

 

 

ではでは、今日はこの辺で。

 

 

 

第2回模擬ISUCONやりました

こんにちは。

今回は、一昨日行った第2回模擬ISUCONの模様をお届けします。

題材はISUCON5予選問題。

github.com

 

マニュアルがこちら。

ISUCON5予選マニュアル · GitHub

 

そして会場は、沖縄で一番インターネットに近い場所、ぼくらのお師匠さんであるさぼさんの城、ギークハウス沖縄

f:id:matsuda-juri:20170801150732j:plain

 

 

 

前置きはこれぐらいにして、早速内容の方に。

 

 

1.Azure童貞卒業

 

はい、卒業しました。

今回はAWSではなく、さぼさんの提案でMicrosoftのAzureを使いました。

 

ってことでAWSと同じく、サーバーにSSHでログインできるユーザーとしてマサとディックス君を追加します。

 

.ssh下にあるauthorized_keysに、2人の公開鍵を登録します。

これでおっけー。

 

 

 

2.ログファイルの設定

 

前回のハッカーズチャンプルーで行ったpixivさんの第1回模擬ISUCON同様、ログファイルの設定を行なっていく。

過去記事にて割愛。

 

matsuda-juri.hatenablog.com

 

 

Nginxのログファイルは前回よりスムーズにできた。

「}(閉じ括弧)」忘れによるエラーが出たこともあったけどww

 

mysqlは、myprofilerを使ってのスロークエリの監視が最後までできなかった。

原因は、ディックス君がインストールしたものが古いバージョンだったためww

バージョンって大事ね。

 

 

 

3.ボトルネックはどこだ!?

 

とりあえずnginxのログtopコマンドで怪しそうなところを探った。

 

f:id:matsuda-juri:20170801164421p:plain

 

まずはnginxのaccess.log。

alpで整形したらこんな感じ。

下のほうを見ていくと、

 

f:id:matsuda-juri:20170801164551p:plain

 

ん、何か重そうなのがある!?

/initializeとはなんぞや。

 

get '/initialize' do
db.query("DELETE FROM relations WHERE id > 500000")
db.query("DELETE FROM footprints WHERE id > 500000")
db.query("DELETE FROM entries WHERE id > 500000")
db.query("DELETE FROM comments WHERE id > 1500000")
end

 

初期化を行なってるみたい。

でもなんだろう、なんかイケてない感じがするのはぼくだけだろうか。

 

とりあえずもうちょっとログ見てみることに。

 

f:id:matsuda-juri:20170801165009p:plain

 

お、"/"がなんか大変だぞ。

ってことでソースコードに。

 

get '/' do
authenticated!

profile = db.xquery('SELECT * FROM profiles WHERE user_id = ?', current_user[:id]).first

entries_query = 'SELECT * FROM entries WHERE user_id = ? ORDER BY created_at LIMIT 5'
entries = db.xquery(entries_query, current_user[:id])
.map{ |entry| entry[:is_private] = (entry[:private] == 1); entry[:title], entry[:content] = entry[:body].split(/\n/, 2); entry }

comments_for_me_query = <<SQL
SELECT c.id AS id, c.entry_id AS entry_id, c.user_id AS user_id, c.comment AS comment, c.created_at AS created_at
FROM comments c
JOIN entries e ON c.entry_id = e.id
WHERE e.user_id = ?
ORDER BY c.created_at DESC
LIMIT 10
SQL
comments_for_me = db.xquery(comments_for_me_query, current_user[:id])

entries_of_friends = []
db.query('SELECT * FROM entries ORDER BY created_at DESC LIMIT 1000').each do |entry|
next unless is_friend?(entry[:user_id])
entry[:title] = entry[:body].split(/\n/).first
entries_of_friends << entry
break if entries_of_friends.size >= 10
end

comments_of_friends = []
db.query('SELECT * FROM comments ORDER BY created_at DESC LIMIT 1000').each do |comment|
next unless is_friend?(comment[:user_id])
entry = db.xquery('SELECT * FROM entries WHERE id = ?', comment[:entry_id]).first
entry[:is_private] = (entry[:private] == 1)
next if entry[:is_private] && !permitted?(entry[:user_id])
comments_of_friends << comment
break if comments_of_friends.size >= 10
end

friends_query = 'SELECT * FROM relations WHERE one = ? OR another = ? ORDER BY created_at DESC'
friends_map = {}
db.xquery(friends_query, current_user[:id], current_user[:id]).each do |rel|
key = (rel[:one] == current_user[:id] ? :another : :one)
friends_map[rel[key]] ||= rel[:created_at]
end
friends = friends_map.map{|user_id, created_at| [user_id, created_at]}

query = <<SQL
SELECT user_id, owner_id, DATE(created_at) AS date, MAX(created_at) AS updated
FROM footprints
WHERE user_id = ?
GROUP BY user_id, owner_id, DATE(created_at)
ORDER BY updated DESC
LIMIT 10
SQL
footprints = db.xquery(query, current_user[:id])

locals = {
profile: profile || {},
entries: entries,
comments_for_me: comments_for_me,
entries_of_friends: entries_of_friends,
comments_of_friends: comments_of_friends,
friends: friends,
footprints: footprints
}
erb :index, locals: locals
end

 

 

"/"のモリモリ感がすごい。

ここでとりあえずベンチマークを走らせるのだが、同じようなクエリがめっちゃ走ってることに気づく。(キャプチャするの忘れてました。)

この時思ったのが、「N+1問題」

 

確信はなかったが、DBのボトルネックになりがちなのがどうやらこの「N+1問題」らしい。

qiita.com

 

ここも臭いと思いつつももうちょい探る。

"/"に戻るけど、このブロック内で使われてるメソッドを見てみる。

やはり臭そうなところがあった。

 

def get_user(user_id)
user = db.xquery('SELECT * FROM users WHERE id = ?', user_id).first
raise Isucon5::ContentNotFound unless user
user
end

 

f:id:matsuda-juri:20170801170537p:plain

 

topコマンドからもわかるように、mysqlがまず最初のボトルネックだったみたい。

 

第1回模擬ISUCONで学んだのは、

「DBから取ってくる情報は必要なやつだけ」

 

この get_userメソッドではユーザー情報を全部取ってきてるのがイケてない。

よって、"/"がモリモリになっちゃうって予測。

 

とりあえずキャッシュさせてみるが変わらず。(試しにやってみただけww)

 

次にやろうとしたのがsql文の書き換え。

さっきの「N+1問題」の記事に書いてあるが、テーブル同士をJOINさせようというもの。

 

なんですが、ここで終了間際wwwww

「ベンチ行ってらっしゃぁぁぁぁい!!!」

 

f:id:matsuda-juri:20170801172547p:plain

 

19.8点wwwwwwwwwwwwwwww

しかもタマキって誰や。勝手に出てくんなよ。

 

最後にもう一回ベンチ走らせるが、最悪の0点.....。

キャプチャはあえて憚らさせていただきます....。

 

 

............................終了。

 

 

 

4.反省

 

最初のサーバー立ち上げはスムーズにできたのでよかったかなと。

ユーザー追加も難なくできたので、前回のAWS触った経験が活きててよかった。

あとはもっと早くできるようになること。

 

実際のチューニング作業に移るまでに相当の時間がかかった。

それもログファイルの設定。

バージョン違いによる動作不良は、本番では勘弁したい。

よってここの設定をいかに早くできるかが重要。

そもそもボトルネックはまずぼくらにあった感じwww

 

第2回模擬ISUCONのソースコードは初見。(本番環境とほぼ同じ)

じっくりソースコードを読んでる時間はないので、やはりログ解析をしっかり行えることが先決かな。ログは嘘つかないので。

 

個人的に、今回はエディタを使わずにvimを使ってイジイジしてた。

こうでもしないと慣れないのでwww

結果的にまぁまぁ使えるようになったのでよかったかな。

 

あとは、分業できるところは分業させて効率化を図りたいところ。

なんだけど、やはり初歩的なミスがまだ多いので、お互いフォロー・チェックし合いながらの方がよさそう。

 

 

とまぁ、こんな感じです。

スコア0はさすがに面喰らったwww

 

自戒

お久しぶりです。

エンジニアとしての自分の名前をあれこれ考えていた今日この頃です。

今日はちょっと頭から離れない事があったので、それについてちょこっと。

 

 

いつも行く作業場にいる人から、

「他人の目線を上げるにはどうしたらいいんだろ?」

と、割と無理難題を突きつけられましたww

 

正直、咄嗟に口から出る言葉は本質的な回答だとは自分でも思っておらず、あれこれ考えた結果、結局答えは出ず....。

これが今日のモヤモヤ。

他にも、就活で苦しんでる友達の話をちょこっと聞いてまたムズムズ....。

 

 

「目線を上げる」

 

今こうしてこのブログ書いてるときに、ふと思いました。

 

”それ、今のわいのことやん”

 

 

 

エンジニアとして生きる道を選択した時は、がむしゃらに本とかコード読み漁ってた。

それじゃ今は、将来どうなりたいとか、あの会社に行きたいとか、こういうことやりたいと考えるばかりで全く初心を忘れていたのですよ。

 

もちろん未来のことを考えるのは重要。

けど、ぼくが今やるべきことはそれじゃない。

そうだと分かっているのは、過去に野球をやっていた経験があるから。

 

 

 

ぼくが初めてホームランを打ったのは小学5年生の時。

今でも鮮明に覚えているけど、高めのボールをレフト場外まで飛ばした。

それ以来、学校が終わったら友達と公園で野球したり、家にある鏡の前で素振りしたりした。

学校では、授業中に鉛筆何本かを束ねてバットのグリップにして素振りみたいなことした。

もちろん先生には怒られたけどww

 

 

そんなこと続けてたら、小学6年生の時は地区で最強の1番バッターになってた。

試合では遊び半分で木製バット使ってホームラン打ったり、少年野球の試合なのに敬遠されたりもした。

蓋を開けてみると、年間の最終打率は4割超えてた。

(人生で唯一自慢できるネタ。つまりピークwww)

 

当時は単にどうやったら打てるのかしか考えてなくて、ただただがむしゃらにバット握ってるだけだった。

甲子園出たいとか、プロになるとかそんな思ってなかった気がする。

(ちょっとは思ってたかもしんないけどww)

要は目の前のことに集中するだけだった。

 

 

 

そんな昔のことを思いながら、エンジニアに変わっても同じことだと気付き始めた。

エンジニアのコード書くとか読むとかは、野球の素振りと一緒のような気がする。

 

素振りは本当に地味。

けどそれやらないと上手くならなかった。

やると打てるようになるし、打てる状態が続くともっと遠くにボール飛ばしたいとか、全打席ホームラン打ったろとか、自然と目線が上がってた気がする。

だから上手くなれたと思う。

 

 

そうと分かった今、エンジニアの素振りをサボってたぼくは何なんだって話。

ぼくの目線はまっすぐ上ではなく、斜め上だった。

やるべきことやらずに将来についてうだうだ言うなってことやね。

人目とか他人のことなんていいのよ。

素振りしとけば結果は後から付いてくるものだと思ってる。

だからやることやれ。地味かもしんないけど。

 

 

なんてことを考えながらこれ書いてますが、ISUCONまで残り3ヶ月。

大きなホームラン打てるように、また一から精進する。

 

 

 

 

あれ、最初の質問の答え出せてないやwwwwwww

まぁいっか。

 

 

ハッカーズチャンプルーで模擬ISUCON

こんにちは。

一昨日、ハッカーズチャンプルーでのISUCON合宿が終了しました。

3日間で10時間くらいしか寝てないので多少お疲れ気味ですw

今回は3日目に行った模擬ISUCONの模様をダイジェストでお伝えしようと思います。

 

時間は本戦と同じの10:00~18:00の8時間。

参加チームは3つ。

 ・anpanman (ぼく・disk)

 ・fukumoto (マサ・ディックス)

 ・penpen(琉大情報工)

そして題材はこれ。

github.com

 

pixivの社内イスコン。

カタツイさん、ありがとうございます。

では見ていきましょう。

 

 

1.AWSインスタンスを立ち上げる

 

チーム戦になるので、サーバーにログインできるユーザーとしてdiskを追加する必要がありました。

具体的には、authorized_keysdiskの公開鍵を追加しておくこと。

参照記事がこちら。

qiita.com

 

ここで手こずり1時間が経過www

 

f:id:matsuda-juri:20170626114612p:plain

 

この時点で他の2チームはすでにベンチマークを走らせています。

ちなみにチューニングなしでベンチ走らせた場合、Rubyでは3000点弱がスタート。

 

 

 

2.データベースのチューニング

 

f:id:matsuda-juri:20170626125649p:plain

 

 

DBの管理は「Sequel Pro」を使う。

ここではインデックスが貼られてなかったので、とりあえずcommentsテーブルにpost_iduser_idというインデックスを貼っとく。

GUIでインデックス貼れるSequel Proめっちゃ便利。

 

参考:データベースにindexを張る方法 - Qiita

 

さぼさんが提供してくれた参考サイト:

なぜ、SQLは重たくなるのか?──『SQLパフォーマンス詳解』の翻訳者が教える原因と対策 - エンジニアHub|若手Webエンジニアのキャリアを考える!

 

とりあえずここでベンチ走らせたら、3000点→10000点くらいに。

 

 

 

3.アプリケーションのチューニング

 

まずはUnicornのチューニング。

unicorn_config.rbを開き、worker_processesを4に設定。

f:id:matsuda-juri:20170626201502p:plain

 

これでunicornが連れてくる職人さんが4人に増えた。

 

 

次はapp.rb。

実はこのソースコードは何回も見ているので、どこがボトルネックになりそうかはわかっていた。それがこれ。

f:id:matsuda-juri:20170626202319p:plain

 

今回のキモであるmake_postsメソッド

まずpostsというarrayを用意して、色々ごちゃごちゃかき回して最後にまたpostsに入れてる。

どんどんハッシュを大きくしているイメージかな。

そして最初にresultsという変数がeachで回っているので、そいつの宣言元に行ってみる。

 

f:id:matsuda-juri:20170626202900p:plain

 

あったあった。

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の設定は公式通りにやらないとうまく動かなかった。

github.com

 

動くとこんな感じ。

f:id:matsuda-juri:20170627133817p:plain

 

 

 

unicorn

unicornaccess.logとerror.logを監視する。

(今回ここはやってないので割愛。どこかで記事書きます。)

 

 

mysql

まずはgenaral_logをtailコマンドで監視できるように設定。

こちらを参考。
qiita.com

 

MySQL :: MySQL 5.6 リファレンスマニュアル :: 5.2.3 一般クエリーログ

 

もう一つ。

「my profiler」というものを使ってスロークエリを監視する。

KLabさんのgithubに公開されているので、それを参考に。

github.com

 

またこちらも勝手にご紹介。

dsas.blog.klab.org

 

 

 

5.nginxのチューニング

やっときたきた女将さん。

今回ぼくがめっちゃイジイジしたかった女将さん。

ナイスバディにしてあげようと気合い入れて、さぁいざ!

 

まずはKLabさんの記事を参考にworker_processesを1に、keepaliveを32にしてみた。

ここでベンチ走らせると1000点くらい伸びた。

 

やっぱり静的配信実現してからじゃないと伸びなさそうと凹む。

 

ここまでで多分4時間くらいが経過。

 

 

6.ググる、焦る、終了

データベースに突っ込んである画像データを逃すことを優先し、diskにバトンタッチ。

その間にぼくはgithubリポジトリを作る作業に。

 

しかし

なぜだかうまくできないwwwww

前日はちゃんとできてたのに.....。

 

途中アクシデントに見舞われ、githubは諦めることに。

diskの方もなかなか苦戦している模様。

 

とりあえずベンチ走らすが、スコアがほぼ0になる始末。

 

そんなこんなで、あーだこーだしているうちに18:00。

終了!

 

最終スコアがこちら。

 

f:id:matsuda-juri:20170627140353p:plain

 

さぼさんwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

残り時間半分くらいから参戦してこのスコア。

さすが、お師匠さんです。

 

ぼくら学生チームはというと、まぁ僅差ですねwww

どうやらこの差はベンチ走らす時間とタイミングの差らしい。

ネット環境によって多少の誤差は生じるとのこと。

 

 

7.模擬 ISUCONを終えて

正直、スコア的には満足いくものではなかった。

が、得るものはスコア以上に大きかった。

 

一つ目に、「ISUCONがどんな感じなのか」ということ。

意外にも8時間は短いような気がした。

ぼくの場合、めっちゃ飯食うし、うんこ何回もするのでどうにかしないと...。

 

二つ目、「ログファイルの設定の重要性」

ぼくらはまだ経験が浅いので、直感でどこ触ればいいのかまだわからない。

そのガイドをしてくれるログファイルは、時間をかけてでも用意しておくべきだった。

目標は開始から1時間くらいで全て揃えられること。

 

三つ目、「やっぱりまだ全然力不足だね」

「あれ、なんでここできないんだろう?」ということが多々あった。

正直難しいことはしてないんじゃないかと思ったりもしたが、やはりそこは基礎ができてない証拠。

また一から出直してきます。

 

 

また、今回ぼくの個人的な目標として、

「できるだけ多くのエラーにあたる」

があった。

まぁぼくの場合何してもエラー出るので、目標ってほどのものでもないが、ここの経験を得られたのはかなりよかった。

正直、動くもの作るより、エラー解決したりする方が好きなのかもしれない。

 

実りの多かった模擬ISUCON。

次回は15万点目指して、また一から精進します。

 

 

 

 

ハッカーズチャンプルー2017 〜1日目〜

おはようございます。

お久しぶりです。

しばらく更新が途絶えてましたが、ちゃんと生きてます。

最近何してたかというと、初心に戻って基礎を勉強しておりました。

 

そしてハッカーズチャンプルーに参加しております。

沖縄県北谷町美浜のホテルで強化合宿。

hackers-champloo.org

 

この3泊4日の開発合宿を通して、スキルアップを図ろうというわけです。

最終目標は模擬ISUCONを行って、1ミリでもスコアアップする。

 

今は2日目の朝。

初日は開会式?を行い、参加者で交流会。

クラフトビール屋に行ったのですが、志賀高原と湘南のビール2杯だけで2500円...。

でも美味しかったなぁ。

 

と、初日はゆるゆるでしたが、今日(2日目)から気合い入れようと思います。

 

 

そして重大な報告

 

今までぼく、マサ、ディックスの3人でチームを組んでましたが、この合宿からもう一人加わることになりました。

DSKです。

(後ほど詳しく紹介するかな...)

 

ISUCONは3人で1チームですので、誰か1人は出れません。

ってことで出場エントリーまでのどこかで、出場できる3人を決めるチーム内ISUCONを行います。

 

 

あ、もう9時。

ぼくも必死なのでそろそろ作業開始したいと思います。

AWSまで触るでぇぇぇぇぇ!!!!!!!!!!!!!!

 

ではまた。