モヒカンメモ

髪色が定期的に変わることに定評のある(比較的)若者Webエンジニアの備忘録

ISUCON11予選 31位で惜しくも本戦出場ならず〜〜〜

今年もISUCON 予選に参加し、527チーム中31位で惜しくも本戦出場なりませんでした、くやしい〜〜〜〜〜〜〜。

f:id:pinkumohikan:20210822220237p:plain

ISUCONとは

Iikanjini Speed Up CONtest。LINE社主催、お題となるWebアプリケーションをガツガツゴリゴリいじくり回して超たくさんの人が同時に使っても死なないチョッパヤ仕様にするソフトウェアエンジニア向けのエクストリームイベント。

isucon.net

今回のオンライン予選は598チーム、1421名の方にご参加いただきました。

チームメンバー紹介

今回はチーム 「牡蠣に当たるときの効果音→カキーン」 として、下記メンバーで参加しました。

cureseven

  • アプリの改修頑張った
  • 練習熱心
  • すぐ歌い出す

shiningcureseven.hatenablog.com

nekodaisuki

  • 猫がだいすき
  • インフラがちゃがちゃマン
  • SQLの魔術師

sinnderu.hatenablog.com

pinkumohikan

  • 色々指図するマン
  • やったこととスコアをIssueに書かないとキレる担当

主な施策

やったことの全容↓ github.com

1. index追加

Slow query logを見ながらindexが必要そうなところへペタペタ。 降順インデックスの罠は 進研ゼミ ISUUMOでやったやつ。

2. インフラ構成の変更

最初は1台のインスタンスに全盛りで、CPUをnginx, app, dbで食い合っていたのでDBサーバを別インスタンスへお引越し。 MariaDBには慣れてないからMySQL 5.7に変更、後に降順インデックス使いたかったのでMySQL 8へ。

最終的にはappサーバのCPUがフィーバーしていたのでappだけのサーバも用意して下記のような構成に。

サーバ 役割
1 nginx, varnish, app
2 app
3 DB

3. dropProbabilityの調整

チューニングが進み、リソースに余裕が出てきたタイミングでいじいじ。 5%刻みで設定変えてベンチ回して、最もスコアが良かった 0.95 に設定。

ただこれは13:30に設定して以降ずっとそのままだったのである程度チューニングが進んだ段階で見直したほうが良かったと反省。

4. lastなIsuConditionをメモリに持たせる改修

最新のIsuConditionを取得しているところやN+1があり、クエリで一括取得するようにしても良いけどDB負荷高めだったのと最新レコードだけならデータ量的にも行けそうだったのでアプリのメモリに持たせる方向で解決。

結構重要な仕事を無事成し遂げられたcureseven氏に拍手。ベースとなるデータを作る部分ではnekodaisuki氏のSQL力がいかんなく発揮された。

5. リバースプロキシでのコンテンツキャッシュ

最初はnginxのproxy cacheでキャッシュしてたけど最小キャッシュ時間が1sなのでタイミングによって鮮度古いよエラーが出ちゃう問題があり、途中からvarnishを挟んだ。

が、varnishは全然練習してなかったので手こずってた模様。自分も最後にvarnish触ったのは7年前とかなのでnekodaisuki氏に血を吐いてもらった。

振り返り

一言で表すと、去年と比べてチームとしても個人としても良い感じに進められ、チームビルディングや練習の甲斐あって成長が感じられる良い回でした。

競技中は終始良い雰囲気で進められたし、みんながしっかりログを見ながら「この辺が遅そう」みたいな当たりを付けながら進められていたので来年は誰がリーダーになってもやっていけそう。スコアも頻繁にリーダーボードに乗るぐらいには健闘していた。

去年本戦に出場できたのはまぐれじゃないぞと証明するため今年もチームで10回ぐらい練習会をしたものの、最終スコアは92336点 31位でわずかに25位に届かず予選敗退。 5万点ぐらい足りなかったら実力不足だと割り切れるけど予選通過ラインが106094点ぽく、競技終盤のスコアは10.7万ぐらいだったのでワンチャン届いていたなーと思えてしまって大変悔しい。

f:id:pinkumohikan:20210823010925p:plain

とは言え運も実力の内、むしろ運に左右されない強靭なスコアが必要。また来年がんばるぞ。

今回の問題も大変良い問題でした。 大きなボトルネックがドーンと構えている感じではなく、改善すべきポイントが各所にあって改善のたびに着実にスコアが伸びてコツコツとスコアを積み上げていけるタイプの問題。ベテランはもちろん、ISUCON初心者でも楽しめる課題だったと思います。ISUCON入門イベントとかに使えそう。

来年も対戦宜しくお願いします!

AmazonLinux2にMySQLクライアントのみをインストールする

AmazonLinux2にMySQLクライアントのみをインストールしたくなって方法を調べたのでまとめておく。

前提

1. OS

$ grep PRETTY_NAME /etc/os-release
PRETTY_NAME="Amazon Linux 2"

2. 初期状態ではAmazonLinux2にはMySQLクライアントは入っていない

$ mysql --version
-bash: mysql: コマンドが見つかりません

3. 接続先はAurora MySQL 2系

4. 2021/07/27 (火) 15:00時点の情報

インストール手順

1. MySQLのyumリポジトリをインストール

AmazonLinux2のデフォルトyumリポジトリではMySQLクライアントパッケージがどこにあるかが分からない。在り処を教えるためにMySQLのyumリポジトリをインストールする。

$ sudo yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
...
インストール:
  mysql80-community-release.noarch 0:el7-3

完了しました!

上記のURLはAmazonLinux2 (Red Hat Enterprise Linux 7 / Oracle Linux 7) 用なことに注意。AmazonLinux 1系やCentOS 8系にインストールする場合は上記URLではダメなので、下記から対応するURLを取得すること。

dev.mysql.com

2. MySQL 8系のリポジトリを無効にする

初期状態ではMySQL 8系のリポジトリが有効になっている。

今回はAurora MySQL 2系に接続したくて、Aurora MySQL2系はMySQL 5.7系互換。ゆえに、MySQL 8系よりもMySQL 5.7系用のMySQLクライアントを使ったほうが不都合が少ない。

$ sudo yum-config-manager --disable mysql80-community
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
=============================================== repo: mysql80-community ===============================================
[mysql80-community]
...

$ sudo yum-config-manager --enable mysql57-community
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
=============================================== repo: mysql57-community ===============================================
...

ちなみに、どっちも無効にしておいてMySQLクライアントをインストールするときに --enablerepo=mysql57-community みたいに指定する方法もある。

3. MySQLクライアントをインストールする

MySQLクライアントは mysql-community-client というパッケージ名で登録されている。あとはyum installを叩くだけ。

$ sudo yum install -y mysql-community-client
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
mysql-connectors-community                                                                      | 2.6 kB  00:00:00
mysql-tools-community                                                                           | 2.6 kB  00:00:00
mysql57-community                                                                               | 2.6 kB  00:00:00
mysql57-community/x86_64/primary_db                                                             | 279 kB  00:00:00
45 packages excluded due to repository priority protections
依存性の解決をしています
...
インストール:
  mysql-community-client.x86_64 0:5.7.35-1.el7                  mysql-community-libs.x86_64 0:5.7.35-1.el7
  mysql-community-libs-compat.x86_64 0:5.7.35-1.el7

依存性関連をインストールしました:
  mysql-community-common.x86_64 0:5.7.35-1.el7          ncurses-compat-libs.x86_64 0:6.0-8.20170212.amzn2.1.3

置換:
  mariadb-libs.x86_64 1:5.5.68-1.amzn2

完了しました!
[ec2-user@ip-10-0-101-190 ~]$ mysql --version
mysql  Ver 14.14 Distrib 5.7.35, for Linux (x86_64) using  EditLine wrapper

じゃじゃーーん!

参考にした資料

dev.mysql.com

docs.aws.amazon.com

IPA 情報処理安全確保支援士試験に合格しました

IPA主催のサイバーセキュリティ知識の認定試験「情報処理安全確保支援士試験」(旧 セキュリティスペシャリスト試験)に合格しました 🎉

f:id:pinkumohikan:20210718150045p:plain

情報処理安全確保支援士試験とは

「情報処理安全確保支援士試験(SC)」はIPA 情報処理推進機構 主催のIT認定試験で、「応用情報技術者」の上位に位置してサイバーセキュリティ分野での専門知識について認定する試験。

www.jitec.ipa.go.jp

サイバーセキュリティリスクを分析・評価し、組織の事業、サービス及び情報システムの安全を確保するセキュリティエンジニアや、技術・管理の両面から有効な対策を助言・提案して経営層を支援するセキュリティコンサルタントを目指す方に最適です。

制度改定により今は「情報処理安全確保支援士試験」と呼ばれているが、昔は「セキュリティスペシャリスト試験」という名前だった。

IPA 高度系試験のなかでは比較的合格しやすいと言われているが、合格率で言うと20%ちょいなのでそれなりには難しい。

f:id:pinkumohikan:20210708133816p:plain
合格率

IPA 高度系試験にしては唯一、春期と秋期の両方で受験可能なのが素晴らしい。

f:id:pinkumohikan:20210708133601p:plain 出典: https://www.jitec.ipa.go.jp/1_13download/youkou_ver4_6.pdf

受験の動機

  • Webエンジニアの強みとしてセキュリティ知識を深めたい
  • Webエンジニアとして競争力を維持するために、能力の向上と証明をしておきたい
  • IPA 高度試験合格という響きがカッコいい
  • 同時期にWebセキュリティ実務知識試験 (通称: 徳丸実務知識試験) を受けたので続けて受けると学習効率が良かった

実は春期ではデータベーススペシャリストを受けるつもりだったが新型コロナウイルスの影響で試験時期が半期ズレたらしく春期では受けられなかったので急遽、情報処理安全確保支援士試験に変更したという裏話もあったり。

受験勉強としてやったこと

受験勉強としては過去問道場でひたすら過去問を解きながら分からないことや事例をググり、仕上げとしてTACの本を軽く読んだ。

振り返り

受験勉強をしたことで応用情報範囲の復習ができたり、サイバーセキュリティ周辺の知識が増えたり、サイドチャネル攻撃みたいな「言われてみれば確かにそういうことできそう」みたいな面白い攻撃手法について知れたことは良かった。

サイバーセキュリティの知識については徳丸試験対策やら過去問道場やらTAC本やらでそれなりに対策ができていたが、試験3日前ぐらいに午前Ⅰ試験の出題範囲が全然違うことに気づいて大急ぎで応用情報対策を始めたのは失敗だった。ちゃんと出題範囲を確認しましょう(遠い目)。

あと勉強の進め方として、TACの本は思っていたよりもしっかりと個々の技術について解説がされていたので最初にこっちを通読してから過去問道場で修行するほうがが学習効率が良さそうに思った。

余談

これから同試験を受けられるかたで過去問道場を使われるかたは、試験が近づくにつれて過去問道場が重くなっていくことに注意されたし。

前日ぐらいからページ読み込みに2 - 3秒かかるようになり、試験当日は30秒待っても開かないぐらいでまともに使えなくなる。過去問道場には間違った問題を再出題してくれる便利機能があるので試験直前の追い込みに使おうと思っていたのに、当日使い物にならなくて予定が狂った。

余談2

最近はエンジニア採用のお手伝いもしているので「技術力があること」をどうやって見極めるかについて関心がある。今回受験してみて、同試験の合格者なら運用保守(障害対応)の技術力について一定の担保が出来るんじゃないかなーって思ったりした。

f:id:pinkumohikan:20210726124038p:plain
情報処理安全確保支援士合格証書

ウェブセキュリティ実務知識試験 (徳丸実務試験) に合格しました

Webセキュリティ界隈で有名な徳丸さん監修の「ウェブセキュリティ実務知識試験 (通称: 徳丸実務試験)」に合格しました 🎉

f:id:pinkumohikan:20210610055423j:plain
徳丸実務試験

ウェブセキュリティ実務知識試験

ウェブセキュリティ実務知識試験 (通称: 徳丸実務試験) は一般社団法人BOSS-CON JAPAN PHP技術者認定機構が主催する、安全なWebアプリケーションを作っていく上で必要な知識を有していることの認定試験。Webセキュリティにおいて定番と言える「安全なWebアプリケーションの作り方」が指定教材となっており、かつその著者の徳丸さんが試験の監修をしているらしい。

www.phpexam.jp

今回自分が受験したのは2/7に開催された記念すべき1回目の試験。

tokumarukaiden.peatix.com

1回目ということもあって過去問とか先人の体験記は存在しないのでワクワクドキドキ。

受験の動機

自分はWebアプリケーションを開発・保守することでご飯を食べているのでWebセキュリティについても職責の範囲。受験勉強を通じてWebセキュリティについて改めて勉強したかった。

あとは合格すれば単純に能力の証明になって転職等の文脈で1mmぐらいは役立つのではという淡い期待、そして何より第一号合格者という響きがカッコいい。

この辺は過去に「ウェブセキュリティ基礎試験 (通称: 徳丸基礎試験)」を受験したときから変わっていない。

blog.pinkumohikan.com

試験対策

参考書は指定教材の徳丸本のほか、読書会をやったことがある徳丸赤本も再度読んだ。

f:id:pinkumohikan:20210610050028j:plain

勉強法はひらすら通読して「良く分からなかったところ」「学びがあったところ」に付箋を貼り、一通り読み終わったら付箋の有るところを重点的に再度読み直す、というもの。良く分からないトピックは個別にググったり、それによる被害事例を調べたりもした。

今回の受験に当たって費やした勉強時間はだいたい2 - 30時間ぐらい。徳丸本を2週くらい + 付箋つけたところをさらに2 - 3週ぐらい読んだ。

試験当日

試験開始の約2時間前に試験会場のコワーキングスペースへ到着。ショートタイムのドロップインで最後の試験対策をした。

f:id:pinkumohikan:20210610051436j:plain
CO-EDO

試験直後の手応えは4ヶ月前なので正直あまり覚えてなかったけど、Evernoteに日記が残っていた。

f:id:pinkumohikan:20210610051702p:plain
2021/02/07の日記

これは自分の経験則だけど、不安な問題は正答率50%、解けたと思う問題は正答率90%で数えると大体それっぽい正答数が出る。

試験結果

合格です、やったー🎉

ただ正答率は86%というなんとも微妙な数字。悪くはないけどある程度間違えてますね、的な。ていうか、正答率85%を予想していたのでほぼドンピシャでワロタw

カテゴリごとの正答率が「受験レポート」で見えるので正答率が低かったところは別途復習をしておきたい。

f:id:pinkumohikan:20210610051234j:plain
受験レポート

文字コードの辺りは確かに苦手意識あるけどそれにしても正当率0%は笑うw(笑えない)

感想

とりあえず合格してよかった〜。 割としっかり試験対策はしていたし手応え的にも合格はしてるだろうと思っていたけど、万が一ということもあり得るので結果が届くまでドキドキだった。

試験の難易度としては、前回受験した「ウェブセキュリティ基礎試験 (通称: 徳丸基礎試験)」よりは確かに難易度が上がっていそうに思った。 とは言え突飛な問題は出なかったのでしっかりと勉強していれば合格できそう。

余談

個人的には知識よりも技能を測る試験があると面白いなと思う。お題となるWebアプリケーションに潜む脆弱性を見つけ対策する、みたいな試験を是非企画して欲しいところ。「知っている」ことにももちろん価値はあるけど、「知っている」と「使える」には大きな隔たりがあると思うので。

たじーさんが紹介してたOFFENSIVE Security WEB-300とやらがそれっぽい?(立ちはだかる英語の壁)

DBでdateとdatetimeを扱うときのカラム名suffixの使い分け

結論

  • 扱うデータが日付 (date) なら、 registered_on のようにsuffixには on を使うべし
  • 扱うデータが日時 (datetime) なら、 registered_at のようにsuffixには at を使うべし

背景

これまでデータベースのカラム名を命名する際、日付 (date) でも日時 (datetime) でもsuffixには at を使っていた。 だが先日、英語的には日付と時間で明確に使い分けがあって日付の場合は at よりも on のほうが適切である、と教えてもらった。

english-club.jp

端的にまとめると、 at は点を示す前置詞なので時間を厳密に表す場合に適切、 on は曜日や日など(時間に比べて)幅のあるものを表す場合に適切、ということらしい。

コーディング規約的にはどうなのか

理屈としては理解できたが、これまで聞いたことがない使い分けだったため従うべきかどうかは迷った。そのため、先の使い分けを肯定しているコーディング規約等があればそうすべき根拠が増えて従いやすいので調べた。

軽く調べた限りでは本件について明確に定義しているルールはあまりなかったが、Thoughtbot社のRailsスタイルガイドには下記のような記述があった。

Name date columns with _on suffixes.
Name datetime columns with _at suffixes.

github.com

今後

自分としては使い分けの理屈には異論ないのでdateカラムならonを、datetimeカラムならatをsuffixとして使っていくことにする。

jqを使ってjsonの差分をスマートに確認する

jsonを比較する際にkeyとvalueの組が同じでもkeyの並びが微妙に違っていたりして余計な差分が出てキレそうなとき、jqを使ってkeyでソートしてからdiffを取ったりすると便利だよっていう小ネタを紹介する。

jq

jqはjsonをいい感じに整形したり、色付け表示したり、フィルタリングしたり、集計したりできる人気のCLIパッケージ。

stedolan.github.io

Web APIから返ってきたjsonを見やすく表示したり、特定keyのvalueが◯◯なエントリだけを抽出する、といった用途で自分は良く使っている。

minifyされたjson読みづらい問題

Web APIなどから返ってくるJSONはminifyされていることが多く、そのままでは読みづらいがjqに食わせることでいい感じに整形 & 色付け表示してくれる。

生json:

{"name": "pinkumohikan", "age": 99999999, "bio": "天才天才天才天才天才天才天才天才天才天才天才天才天才天才天才天才天才技術者", "location": "Japan", "hobby": ["AirsoftGun", "Programming", "EC", "Bowling", "Darts"]}

jqに食わせたもの:

f:id:pinkumohikan:20201231035231p:plain
jsonはとりあえずjqにぶち込めば読みやすくなる :100:

jsonのkeyの並びが地味に違っていてdiff取りづらい問題

2つのjsonが同一であるかを検証したいとき、愚直にdiffを取るとkeyの順序で悩まされることがある。

例:

$ cat a.json b.json
{
  "tako": "wasa",
  "banana": "dayo",
  "akkan": "be"
}
{
  "akkan": "be",
  "banana": "dayo",
  "tako": "wasa"
}

$ diff a.json b.json
2c2
<   "tako": "wasa",
---
>   "akkan": "be",
4c4
<   "akkan": "be"
---
>   "tako": "wasa"

これらはkeyとvalueの組み合わせで考えると同じなので差分として出ないようにしたい。

jsonのkeyでソートすれば差分を抑えられる

jqにはkeyでソートしてくれる機能があるので、それを使ってkeyでソートしたあとdiffを取れば余計な差分を抑えることができる。

オプションは --sort-keys または -S

man:

       o   --sort-keys / -S:
           Output the fields of each object with the keys in sorted order.

例:

$ jq --sort-keys . a.json b.json
{
  "akkan": "be",
  "banana": "dayo",
  "tako": "wasa"
}
{
  "akkan": "be",
  "banana": "dayo",
  "tako": "wasa"
}

これらをdiffに食わせれば...

$ diff <(jq --sort-keys . a.json) <(jq --sort-keys . b.json)

余計なdiffを抑えられる。

php-fpmはリクエストが中断されても処理中のプログラムを中断しない

nginxでリクエストを受けてphp-fpmにpassするというPHPアプリケーションではスタンダードな構成において、リクエストが中断されたときphp-fpmの処理って中断されるんだっけ?されないんだっけ?というのが気になったので調べた。

ざっくりまとめ

  • クライアントがリクエストを中断すると、WebサーバはFCGI_ABORT_REQUESTレコードを発出する
  • php-fpmではFCGI_ABORT_REQUESTレコードをサポートしていない
  • 先の理由のため、クライアントがリクエストを中断してもphp-fpmが処理中のプログラムは中断されない

f:id:pinkumohikan:20201119020348p:plain
PHP

FastCGIとphp-fpm

nginxはクライアントからリクエストを受け取ると待機しているphp-fpmプロセスへFastCGIという仕様に基づいて処理を依頼する。

ja.wikipedia.org

php-fpmはPHPのFastCGI実装で、nginxより依頼されたCGI処理を行って結果をnginxへ返す。

www.php.net

FCGI_ABORT_REQUESTレコード

クライアントからのリクエストが中断される (コネクションが切れる) と、nginxから FCGI_ABORT_REQUEST レコードが発出される。

fastcgi-archives.github.io

5.4 FCGI_ABORT_REQUEST

The Web server sends a FCGI_ABORT_REQUEST record to abort a request.

A Web server aborts a FastCGI request when an HTTP client closes its transport connection while the FastCGI request is running on behalf of that client.

php-fpmはFCGI_ABORT_REQUESTレコードをサポートしていない

少なくとも PHP 7.4.12 に付随するphp-fpmでは FCGI_ABORT_REQUEST レコードをサポートしていない。そのため、Webサーバ (nginx) がクライアントとのコネクション切断を検知するなどして FCGI_ABORT_REQUEST レコードを発出したとしても、php-fpmはそれを無視して処理を続行する。

github.com

FCGI_ABORT_REQUEST = 2, / [in] (not supported) /

かんたんなテストでもphp-fpmによる処理は中断されないことを確認した (10秒後にログを書き込みレスポンスを返すAPIを用意して、クライアントからリクエスト後、10秒経つ前にリクエストを中断してみた)。

まだ分かっていないこと、関連する疑問

  • apache モジュール版PHPで動かすと中断された気がするが、認識は合っているか
  • php-fpmでFCGI_ABORT_REQUESTをサポートしていない背景、サポートする予定はないのか
  • php-fpm以外のFastCGI実装はあるのか

知っている人がいれば是非教えて欲しい。

Special thanks

@Danack

stackoverflow.com

@yowatari

ISUCON10本戦へ出場して「またあいま賞」を受賞しました

10/3 (土) に開催されたパフォーマンスチューニングコンテスト「ISUCON10」のオンライン本戦にて、チーム「 牡蠣の鋭利な殻が指に突き刺さり利き手を負傷 」として33チーム中20位でフィニッシュし「またあいま賞」を頂きました 🎉

f:id:pinkumohikan:20201110235918j:plain
ISUCON10 FINALISTの証

ISUCONとは何なのか (再び)

Iikanjini Speed Up CONtest。お題となるWebアプリケーションをガツガツゴリゴリいじくり回して、超たくさんの人が同時に使っても死なないチョッパヤ仕様にするエクストリームイベント。

isucon.net

イカれたメンバーを紹介するぜ (再び)

平均年齢26歳の若手キャピキャピチームです!

cureseven

  • キャピキャピ隊長!
  • 湾曲したiPadがお気に入り!

twitter.com

shiningcureseven.hatenablog.com

nekodaisuki

  • もうそろそろ中年!
  • 壁のぼり過ぎて指紋が無いので悪い事し放題!!!!

twitter.com

sinnderu.hatenablog.com

pinkumohikan

  • TeamCapacityの設定を見落として、「TeamCapacityはコントローラビリティないよ」って言っちゃった人 💀

twitter.com

blog.pinkumohikan.com

チーム名の由来

今回、「牡蠣の鋭利な殻が指に突き刺さり利き手を負傷」という物騒なチーム名で出場しました。

命名としては、

  • Oystersという(比較的)若手エンジニアコミュニティのメンバーで構成されたチームなので「牡蠣」って入れたかった
  • ブランディングやカッコよさよりも奇をてらう方向へ全振りしたい

辺りを加味して、特に相談せず僕が勝手に決めました!!!!(どや!!!)

ちなみに指は負傷しておりません、心配して下さった方々ありがとうございました! でも牡蠣の殻はウイルスが残留している可能性があり危ないのでくれぐれもお気をつけ下さい。

やったこと

本戦前

9/12 (土) に予選通過が分かってから、4回ほどチームで時間を取って本戦対策をしました。時間換算すると合計で25時間ぐらいな? 競合するベテランチームに比べるとまだまだ経験も知識も負けているので、予選と同様に練習量でカバーする作戦です。

予選も100点の振る舞いは出来なかったので予選の振り返り (KPT) をやったり、過去の本戦問題の講評を読んで本戦の雰囲気や傾向を読み取ろうとしたり、過去の本戦問題を実際に解いてみたり。「予選は練習量にものを言わせて正面突破で通過出来たけど、本戦は必殺技を用意しておかないと太刀打ちできなさそうだよね」、みたいなことを考えてVarnishやらOpenRestyやらLua Scriptやらの予習もしました。

本戦中

(正直もう1ヶ月前のことなのであんまり覚えてないんですが) ビルドやらサービスの再起動やらログの退避やらの便利コマンドをまとめたMakefileに不備があってビルドしたバイナリが使われていなかったり (死)、いわゆる負荷レベルに相当する TeamCapacity という概念を見落とす (死) という極めて初歩的なミスのせいでコードに手を入れても全然スコアが変わらず、終始「アレー・・・?」って思いながら手を進めました。リソースには余裕があるはずなのにスコアが伸びないぞ・・・?的なやつ。極めてつらい。穴があったら入りたいし、無いなら掘りたい。それもシャベルとかじゃなくてユンボでガッツリ掘りたい。

isucon.net

ただ、スコアが全然伸びないながらも険悪なムードにならず、最後まで冗談を言い合ったり一緒になって調べたり出来たのはとても良かったと思います。競技である以上は順位も大事だけど、楽しければまあおっけー!

個人的な技術トピックとしては EnvoygRPC あたりがあり、これらはまだ全然触ったことがなかったのでその場で調べながら対応しました。普段使わない技術に遭遇すると上手く立ち回れなくてヒヤヒヤするけど、無理矢理にでも幅が広がるのでこういう機会はマジで尊いですね。これだからISUCONは辞められないぜ。

本戦後

完全にやっちまったなパーリナイ (つまるところの反省会) はもちろん、毎日就業後に参加出来る人で延長戦をするという負けん気を発揮しました。延長戦ではビルド周りの修正をしたり、TeamCapacityの辺りをイジイジしたらシュッと25,000点ぐらいまで上がり、これが本番中に出来てたらもっと楽しめただろうな〜って言い合いましたw

結果的に順位は振るわなかったものの、LINEさんから「またあいま賞」を頂きました 🎉

f:id:pinkumohikan:20201111000519j:plain
またあいま賞をゲット

ありがとうございます!

感想と来年への意気込み

ISUCON本戦には今回が初挑戦でしたが、見事に砕け散りました。プライドはスタボロ、強化ガラスが砕けたときぐらいに粉々! ナイス出題、 今回は 完全に負けました。ぴえん、ぱおん。

一緒にプレイしてくれたcureseven氏、nekodaisuki氏、あざました!

来年は今年よりも順位上げるぞ〜〜〜

P.S.

f:id:pinkumohikan:20201111114553p:plain
cureseven氏が来年に向けてアップを始めたようです

ストイック杉井〜〜

ISUCON10予選を何とか突破出来たンゴ〜〜〜

9/12 (土) に開催されたパフォーマンスチューニングコンテスト「ISUCON10」のオンライン予選にて、チーム「牡蠣の鋭利な殻が指に突き刺さり利き手を負傷」として予選18位で予選突破しました 🎉

f:id:pinkumohikan:20201002200217j:plain
ISUCON10 FINALIST認定証

isucon.net

ISUCONとは何なのか

Iikanjini Speed Up CONtest。お題となるWebアプリケーションをガツガツゴリゴリいじくり回して、超たくさんの人が同時に使っても死なないチョッパヤ仕様にするエクストリームイベント。

isucon.net

今年で10回目となるISUCON10には490チーム、1,209人が参加したらしい。

俺とISUCON

俺とヤツとの出会いは、そう… (割愛)

イカれたメンバーを紹介するぜ

平均年齢26歳の若手キャピキャピチームです!

cureseven

  • 歴史や思いが溢れてしまっているクエリをいい感じにしたりアプリをいじくり回す担当
  • あと何か盛り上げたりとか
  •  Go言語歴は3ヶ月ぐらい
  • リアルでは半年以上会ってなかったけど先週会った
  • 最近転職したらしい

twitter.com

shiningcureseven.hatenablog.com

nekodaisuki

  • 担当: インフラをバンバンしばき回す担当...なはずだったけど最終的にコードを書くことになりがち担当
  • pinkumohikanと白熱バトルをしてcuresevenを引かせること多数
  • インフラ歴は4ヶ月ぐらい
  • リアルではもう半年以上会ってない
  • 予選における本チームのMVP。例のなぞって検索を論文読んでチューニングしたすごいやつ
  • 最近転職したらしい

twitter.com

sinnderu.hatenablog.com

pinkumohikan

  • どこをいい感じにするのが良さそうか調べたり考えたり祈ったりする担当
  • ISUCON歴は多分チーム内で一番長いので敬って欲しい
  • 最近転職していない

twitter.com

やっていきのスタンスとか

もう講評も出ているのでどこを直したかとかはあんまり書いてもしょうがないので施策についての紹介は割愛するんですが、基本戦略としてはパフォーマンスチューニングの原則に従っていろいろ「計測」して、「遅いところを改修」して、「早くなったか確認」、をガンガン回していく感じで臨みました。

講評で紹介されていたDBサーバを増やす、nazotteをいい感じにする、indexいい感じにする、あたりは概ね出来ていたかと思います。nazotteをいい感じにする辺りはnekodaisuki氏が論文を読んでアプリケーション側で解決するようなコードに書き直していて草でした。Generated columnとか空間indexは知らなかったので純粋に学びが有った。

isucon.net

これは秘密なんですが、限られた時間でいい感じにしていくにはN+1や露骨なロックみたいな "いかにも" な点を見つけても そこがその時点でのボトルネックとなっていなければスルー するのが大事です。

0点のまま突き進んだ3時間

実は、ベンチマーカーの不具合により弊チームは最後の3時間ぐらいはずっとスコア0点の状態で競技を続けて、最終スコアも0点だったんですよねw

大きめな施策の準備が終わってベンチ回したところ、特にエラーは出ていないもののベンチがfailするようになりました。何も情報が出てなくて謎なので運営に問い合わせると詳細なログを出してくれたんですが、ログにはsearch系endpointのタイムアウトしか出ておらず。当日マニュアルの スコア計算 ルールによればこの場合はfailとはならないはずなので、その旨を運営に連絡して競技を続けました。

ISUCON10 予選マニュアル · GitHub

また、一定時間内にレスポンスが返却されない場合はリクエストが中断され、最後に (タイムアウトしました) の付いたメッセージが表示されます。 これによるイス・物件の CSV 入稿以外の API での失格・減点はありません。

その後「状況を確認して対応を検討する」旨の返答がありました。「ルール的にはfailでないが、競技開始後なので公平性のためベンチマーカーは改修しない」とされる可能性はあったものの、15時ぐらいにベンチマーカーが一度改修がされていた実績があるので一度あることは二度あるやろ!と思って競技を続けました。結果、そうなったのでよかったーーー。

isucon.net

予選レギュレーション上は、"競技時間内の最後に記録されたスコア" (最終スコア) を本選出場チームの選出に利用する、と定めています。しかし、本不具合を鑑み、最終スコアが 0 点であったが、再起動を伴う追試にて予選最終結果 25 位のスコアを上回ったチームについて、最終スコアが本不具合によるものではないかを確認しました。

その結果、以下のチームについて、本不具合がなければ最終スコアが 0 点となっておらず、本来であれば本選出場チームに含まれていたと考えられるため、運営チームで協議の結果、別途本選出場チームとして選出することにいたしました。

博打といえば博打なんですが、failしない状態のまま終えてもスコア的に予選通過出来る見込みが無かったのでダメ元で賭けてみた感じです。

…7割ぐらいはダメだろうなって思ってたので、下記のようなtweetもしていますw

やる気アゲアゲマックスだった二人に感謝

弊チームはチーム結成から予選当日までの約3ヶ月間で、合計9回の練習をしました。

f:id:pinkumohikan:20201002200833j:plain
GitHub Repositories

正直僕はここまで練習頑張るモチベーションは無かったんですが (爆弾発言)、cureseven氏とnekodaisuki氏が「やるぞ!!!!」「うおおおおおおおお!100万円!!!」みたいなテンションだったのでそれに引っ張られる形で毎週末練習をしていたら徐々にみんなの改修力がいい感じにレベルアップしていき、いい感じの成果を出せるようになっていました。

地道な練習が功を成していて、いい話だなあ。

おじさん ベテランチームには負けないぞ〜〜〜

本戦への意気込み

僕は「行けるところまで行こう!」って感じなんですが、cureseven氏とnekodaisuki氏の二人は燃えています。

また引っ張ってもらいます。

f:id:pinkumohikan:20201002202738p:plain
おまけ

なんかおこられたw

CentOS8へremiリポジトリを使ってPHP7.4をインストールする

デフォルトリポジトリを使ってPHPをインストールするとCentOS 7系では5.4が、CentOS8系ではPHP 7.2が入る。それよりも新しめなバージョンのPHPを使いたいときの王道的な方法として、remiリポジトリを使う方法を紹介する。

f:id:pinkumohikan:20200920002804p:plain
PHP 7.4

前提

  • 2020/09/20 (日) 時点の情報
# cat /etc/redhat-release
CentOS Linux release 8.2.2004 (Core)

本記事ではCentOS 8を前提に書いているが、CentOS 7 / Amazon Linux 2でも大体同じような手順でインストールできる。CentOS 7で行う場合は dnfyum と読み替えればOK。

ざっくり手順

  1. remiリポジトリを使えるようにする
  2. remiリポジトリを使って、PHP 7.4をインストールする
  3. "php" で呼べるようにする

コマンドまとめ

sudo dnf install https://rpms.remirepo.net/enterprise/remi-release-8.rpm

sudo dnf install php74

sudo alternatives --install /usr/bin/php php /usr/bin/php74 1

一つづつ解説していく。

解説

1. remiリポジトリを使えるようにする

rpms.remirepo.net

remiはイカしたサードパーティ製ライブラリを提供するrpmリポジトリ。ガンガン行こうぜ系OSのFedoraで使われているような新しいバージョンのソフトウェアをCentOSとかでも使えるようにしてくれている。

$ sudo dnf install https://rpms.remirepo.net/enterprise/remi-release-8.rpm
...
インストール済み:
  remi-release-8.1-2.el8.remi.noarch

完了しました!

URLでお察しの通りCentOSのメジャーバージョンごとにRPMファイルが違うので、CentOS 7とかの場合は remi-release-7.rpm とする。詳しくは下記を参照。

English : Repository Configuration - Remi's RPM repository - Blog

2. PHP 7.4を入れる

あとはお目当てのものをインストールしていくだけ。remiリポジトリでインストール可能なパッケージのいくつかはデフォルトリポジトリとコンフリクトしうるので無効化されていて、以前はPHP 7.4も --enablerepo=remi のように明示的に有効化する必要があった。今は remi-safe にカテゴライズされたことによって、特にオプションなしでインストールできる。

$ sudo dnf install php74
...

インストール済み:
  environment-modules-4.1.4-4.el8.x86_64                      php74-1.0-3.el8.remi.x86_64
  php74-php-cli-7.4.10-1.el8.remi.x86_64                      php74-php-common-7.4.10-1.el8.remi.x86_64
  php74-php-json-7.4.10-1.el8.remi.x86_64                     php74-runtime-1.0-3.el8.remi.x86_64
  policycoreutils-python-utils-2.9-9.el8.noarch               scl-utils-1:2.0.2-12.el8.x86_64

完了しました!

php74 というコマンド名でインストールされていることが確認できる。

$ php -v
-bash: php: コマンドが見つかりません

$ php74 -v
PHP 7.4.10 (cli) (built: Sep  1 2020 13:58:08) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies

php-mbstring などのPHP拡張を入れたいときは php74- というprefixをつける。例えば php-mbstring の場合は php74-php-mbstring といった具合。

$ dnf install php74-php-mbstring
...

インストール済み:
  oniguruma5php-6.9.5+rev1-2.el8.remi.x86_64                php74-php-mbstring-7.4.10-1.el8.remi.x86_64

完了しました!

3. "php" で呼べるようにする

PHPを使いたいときに php74 って読み替えるのは面倒なので php で呼べようにしたい。alternativesでエイリアスを設定しておくのがオススメ。

www.redhat.com

syntaxは

alternatives --install <リンク> <名前> <パス> <優先度>

なので、こんな感じにすればOK。

$ which php74
/usr/bin/php74

$ sudo alternatives --install /usr/bin/php php /usr/bin/php74 1

$ php --version
PHP 7.4.10 (cli) (built: Sep  1 2020 13:58:08) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies