眠すぎて明日が見えない

我が人生、眠さに勝るもの無し

ISUCON7 オンライン予選に参加しました

先程人生二回目のISUCONに参戦してきました! 今回やったことと所感を簡単にブログに残します。

isucon.net

事前準備

今回は前職の同僚の id:karia , id:naught00 と参加しました。私は過去一回、二人は今回がISUCON参加はじめてで、全員右も左もわからないかんじだったので本戦に向けて準備は色々しました。やったことは ISUCON6 -> ISUCON4 -> pixiv社内ISUCONの過去問をみんなでやり、ISUCONとはどういうものなのかという雰囲気の把握と過去のボトルネックの改善方法をみたりしました。過去問を通してやっぱり当日は色々準備する時間がもったないよねという話がでて事前にツール等は準備していました。用意したものとしては

  • alpをよしなに使えるshell
  • slack通知shell
  • newrelic
  • mackerel
  • チューニングしたnginx conf
  • 使いそうな実装のリファレンス実装とドキュメント
  • etc...

みたいなものは準備しました。(ほとんど他のチームメンバーが用意してくれました!!! 感謝!!!)

予選

結果から言うとベストスコアは9万4千点ぐらいで、最後の方はベンチ回すごとに上がったり下がったり不安定な感じで結果7万9千点くらいがラストスコアになりました。いろんな実装試しましたが、何がどのぐらい効いたか詳細に残してなかったのでやったことのみ書いていきます。今回の実装の役割分担としては、id:karia がインフラ担当で、id:naught00 と私がアプリ担当でした。自分が予選通してやったこととしては

  • githubへコードをpush
  • image, messageのテーブルにindexはる
  • channelリストを取ってくる処理をキャッシュに乗せて効率化
  • ログイン後のリダイレクト先をchannelに変更
  • pumaをsocketに変更してthread数を変更
  • ユーザ作成時のパスワードのsaltを固定値にする
  • 画像キャッシュが効いてなかったところのバグ取り
  • fetchの効率化 -> redisつかっていい感じにN+1削ろうとしたけど修正方針あやまりあまり効かなかった
  • 残り時間でSELECT * FROMですべてのカラムを取ってきていたので必要なカラムのみにして効率化

ぐらいですかね。あとはエラーの調査とかその辺みたりしてました。画像のキャッシュ化とかサーバー構成周りの変更詳細は 他のお二方がきっと書いてくれるはず...!

心残り

大きくスコアをあげるにはどうすればいいかというところを考えすぎたあまりに、自分の実装の間違いや他の効率が悪いちょっとした処理など見過ごしていた点が多々あったのが悔しいです。今回選択した言語への理解が浅かったところももちろんあるとおもうけど、以前やったisuconの実装の良い部分をちゃんとみていたらわかっていたこともあったのでそこに気づけなかったのが心残りですね...

最後に

本戦に行くことはできなかったけど、また今回自分にたりなかったことへの気づきを持ち帰ることができとても学びがおおかったです! 運営の皆様お疲れ様でした、そしてありがとうございました!

「多動力」読んだ

ふとしたことで購入することになったので読んでみた。

 

多動力 (NewsPicks Book)

 

色々と思うところはあるけど、堀江さんが楽しいと思うことに前向きに取り組むためのノウハウが書かれている本といったところでしょうか。

少し宣伝っぽさがある内容にも取れたけど、好奇心から生じる行動力が多動力となるのかーという感想(小並感)

esaの記事更新を促すchrome extensionを作った

私の周りで情報共有のためのツールとしてesa.ioというサービスを深く愛用させていただいております。最近使い始めて1年が経ちました。サービスを使っていく中で最近あったちょっとした出来事とそれを改善するために作ったchrome extensionについて紹介します。

esaについて

esaというサービスは、公式サイトに書いてある通りチームで情報を育てていくサービスです。各人で記事を作成・共有など行い、皆でその記事の情報を更新し育てていきます。

情報を育てるため・育てやすくするための仕組みとして、

  • 複数人での同時編集
  • 書いている途中でも周りに共有し易くするためのWIP機能
  • リアルタイムプレビュー
  • markdownサポート
  • タイトルと連動したカテゴリの整理方法
  • リビジョン機能
  • etc…

などの様々なサポートがあります。また提供されているchrrome extensionを使用することで、markdown入力時のサポートが受けれて記事作成も楽に行なえます。こちらのextensionはesaのサイト以外でも使えて大変便利です。esarea - Chrome ウェブストア

またここ1年の間esaを使って情報共有をしてきましたが、カテゴリを基準をもって切っていけば様々なケースに使用できて汎用性もあり大変扱いやすいです。現状では日報、議事録、企画案の共有、約束事など様々な用途に使用されています。 ※個人的にはUIが大変親しみやすく、また使いやすいところが大変気に入っています。

最近の出来事

1年近く使うとそれなりにたくさんの記事が溜まっていきます。そんな中最近よくあるのが過去作成された記事で最新の情報が反映されていないものが少しずつ増えてきたということです。読んでいる人は早い段階で気づけばいいのですが、気づくのが遅くなってしまった場合に時間のロスにつながることもあります。

対応

その記事が信頼足り得るものかどうかを図るための指標として、記事の最後の更新時間と現在時刻の差分が大きいかどうかみたらいけるのでは?と考えました。githubでいう 直近数ヶ月何もcommit履歴がないリポジトリ ≒ メンテナンスがされいないかもしれないのような1つの判断基準は、esaにも当てはまるであろうと思った次第です。記事の更新が一定期間ない場合に注意書きを出すことで、ユーザに古い記事かもしれないという示唆を行う。注意書きをみたユーザは「記事更新チャーンス!」といわんばかりに記事の更新を行い常にアップデートされていく記事がesaに溜まっていくみたいな方針をぼんやりと考えました。記事の更新期間があいている時に注意文言を出すのは、qiitaDevelopers.ioなどではかなり前から導入されているもので、今回はそれらをオマージュしました。

作ったもの

esa-cautionerというchrome extensionを作成しました。

chrome.google.com

github.com

※コードはjsの経験ほぼゼロの初心者が組んだようなものなのでPRお待ちしております。

仕組みは画面右端に下のスクショのように記事作成時刻と記事更新時刻がでているのでタグから記事更新時刻を取ってきて現在時刻と比較します。

f:id:Maco_Tasu:20170726211307p:plain

比較してみて半年間更新がなければ注意文言を記事トップに表示するといったシンプルなものです。

f:id:Maco_Tasu:20170726211639p:plain

半年間というのは今の利用状況に合わせて決めた値なのでnヶ月みたいな設定ができるような改善が今後必要そうかなと思います。

簡単な実装のchrome extentionですがesaの記事を有用な状態に保っていくには地味に効果を発揮してくれそうな感じ。

そうなるといいなー

nginxでメンテナンスモード時の503と通常時の503でhtmlを分ける方法

nginxでメンテモードを実装した。機能としては/tmp/503ファイルがあったら、nginxがメンテナンス画面を出すというもの。

最初は503のstatusだったらメンテナンス画面をだすという実装だったけど、メンテナンス以外の時で503の場合は別のviewを出したかったので下記のようなconfigファイルにした。

server {
  listen 80;
  server_name  _;

  error_page 503 @503_error;
  set $maintenance 0;

  if (-f "/tmp/503") {
    set $maintenance 1;
  }

  if ($maintenance = 1) {
     return 503;
  }

  location @503_error {
    root /etc/nginx/html;
    internal;
    expires 0;
    if ($maintenance = 1) {
      rewrite ^(.*)$ /maintenance/503.html break;
    }

    if ($maintenance != 1) {
      rewrite ^(.*)$ /503.html break;
    }
  }

  location / {
    ...
  }

ポイントとしては、

  • 503のstatusの時はカスタムエラーページを出せるように error_page 503 @503_error;を設定すること
  • location @503_errorの内部では
    • キャッシュさせないようにexpires 0を指定する
    • ifとrewriteを使いviewの出し分けを実装しているが、302になってしまうとSEO的に困るのでinternalを指定して内部的な処理にしているところ

かなと。

最初 location /503.htmlのような指定を使っていたけど、これだと上手くlocationに入らないケースがあって、そこは正直良く挙動の理解ができないです..

@でlocationの指定を行うようにしたら意図した挙動になりました。うーん違いがよくわらん

Nginxのngx_http_sub_module#sub_filterの挙動

nginxには定義した特定のcontent-typeの時にレスポンスの中の文字列を書き換えるsub_filterという機能があります。

こちらですね。Module ngx_http_sub_module

できることは文字列の書き換えで、

sub_filter 'example.com' 'www.example.com'; 

と定義するとレスポンスの中のexample.comという文字列をwww.example.comに書き換えてくれます。sub_filter_onceのon,offで繰り返し置換するかどうかの設定をすることができ、sub_filter_typesで置換の対象とするcontent-typeを複数指定できます。利用シーンとしては、特定のURLにアクセスしたときだけでリクエストの中身書き換えたいとか、アプリケーション側の変更無しでサイトドメイン等変更したい時などが考えられます。

sub_filterを使っていて少しハマった挙動としては、例えば hoge.example.comfuga.example.comwww.example.comに書き換えたいという時は、

sub_filter `hoge.example.com` `fuga.example.com`;
sub_filter `fuga.example.com` `www.example.com`;

みたいな書き方をするとhoge.example.comfuga.example.comに書き換わった後に、書き換わったfuga.example.comwww.example.comには書き換わらないのでちゃんと

sub_filter `hoge.example.com` `www.example.com`;
sub_filter `fuga.example.com` `www.example.com`;

と丁寧に書いてあげる必要があります。またgzip圧縮指定をしているとレスポンスの中身の書き換えが正常に行われないので置換したいURLへのアクセスには proxy_set_header Accept-Encoding "";を指定のlocationなりにつけてあげる必要があります。

「データベース技術 実践入門」読了

GW中どうせなら積んでいた本を読もうと思い、2012年ごろに出版された「データベース技術 実践入門」を読んだ。書いてあった内容は、実践入門というより広く薄い内容ではあったけど、自分が気にしていなかったことや知らなかったことなどもあったし、技術の振返りとして読んで面白かった。印象に残ったことは下記の内容。

  • innodb_log_file_size
    • サイズ大: 更新処理の劣化はないが、クラッシュ時のリカバリが低速になる
    • サイズ小: チェックポイントが頻繁に起こるため更新処理は劣化するが、クラッシュ時のリカバリが高速になる
  • クエリが詰まってレスポンスが一時的に返らなく現象には「ストール」という名称がある
  • データーベースのコピーを取った時にデータの一致性を見るにはchecksumを見る方法もある
  • ステートメントベースでのレプリケーションだとUUID()NOW()がそのまま実行されるため、必ずしも同じデータになるとは限らない
  • mysqlbinlogを使う場合に1つのトランザクションが複数のbinlogにまたがる状態がある。mysqlbinlogは最後にROLLBACKを行うので、中途半端な状態になることがある
  • binlogファイルの削除はrmで削除するとmysqlからは認識したままになるので、PURGE MASTER LOGS TOで行う
  • MyISAMでバックアップを取る時は、データベースにロックを掛けた後にsyncを実行して、ディスクに書き出された状態でバックアップを行う
  • 単純なSELECT文を実行するときには、HandlerSocketPluginを使うことでクエリ実行時の無駄なコストを削減できる
  • B-Treeはブランチにデータを持つので、カウントの処理がB+Treeとくらべて遅い
  • MySQLの実装思想について
  • MySQL-Pluginの実装方法まとめ

これらが気になった点。本を読んでいてMySQL5.6が出たぐらいのころの本なので現状とは少し違ってきている点もあるかもしれない。だけど時代的背景からみるMySQLの使い方や基本的な内容の振返りなどまんべんなく見れて良かった。

フロントエンドについて全く詳しくない自分がReactを使ってみた感想

ここ2ヶ月色々あって毎日終電まで作業していたせいもあってブログの更新がなかなかできてなかった。まだ山を超えてないのだけれど息抜きとちょっと気になることがあったのでブログ書こうかなとなった次第です。

先日とある時に、「Reactちょっと触ってみました」みたいな会話から「Reactどうです?」って聞かれて「C#みたい雰囲気でしっくりきた」って返したのだけれど、思い返すとまったく言いたいこと伝えられてないし、意味わからなすぎるよ!!ってなったので冷静に思っていることを文字で書きます。

Webのフロントエンドはほっっとんど触ったことがなく、ちょっと触れたよーっていうものだとjs, reactぐらいなので、その両方からみた時にReactがいいなーっておもったところは以下でした。

  • classとして扱えスコープが小さいので、同名の関数がぶつかったりせずにオブジェクト思考的に扱える
  • componentとしてviewを小さなパーツで区切れるので、dryなコードを作りやすく扱いやすい
  • webpackを使ってビルドできるので、環境依存になりにくい
  • eventhandlerなども書きやすかった(これは完全な主観)

みたいなところがあるかなと。バックエンドの出身の私から見るとオブジェクト思考的に扱えて、LL言語のような手軽さでコーディングできるのですごくしっくりきて入りやすいなって思いました。

みたいなことを伝えたかったのですが、どうも言葉がでてこなかった…変に緊張したりするとたまにやっちゃうので意識的に気をつけるようにしていきたいなと。

これからも頑張るぞい