Magnolia Tech

いつもコードのことばかり考えている人のために。

技術を学ぶ、学ばせる

自分が技術を学ぶために、プライベートの時間を使うべきか、みたいな話は自分で考えよう、としか言えないんだけど、人に学んでもらうためにどうするか?というと、思いつくのはこれくらいなんだよなぁ。

学びは強制できないよね。

ISUCON12予選問題をdocker-composeで起動する

説明のために手順を確認したので、その覚書。

作業環境にリポジトリを用意する

github.com

$ git clone git@github.com:isucon/isucon12-qualify.git

Dockerをインストールする

www.docker.com

値上げが最近話題になりましたが、個人利用は無料です。

www.docker.com

次回はRancher Desktopを試してみます。

rancherdesktop.io

docker-compose.ymlを書き換える

一箇所だけ書き換えないと、起動しません。

Docker Hubから「mysql/mysql-server:8.0.29」のイメージが無くなっていて、MySQLが起動できません。8.0.30以降のバージョンを指定しましょう(無くなった理由は探せませんでした...)。

2022/11/06追記

mysql-serverのバージョンを上げるPRを作って、それが取り込まれたので、これからクローンした場合は、上記の修正は不要となっています。

github.com

また、Go言語以外の言語で動かす場合は、webappのサービスに指定されているbuildのパスを言語に合わせて書き換えます。

コンテナを起動します。

$ docker-compose up

initial_dataを展開する

初期データを展開します。

benchのコンテナにrootでログインします。

$ docker exec -u 0 -it isucon12-qualify-bench-1 bash

isuconディレクトリへ移動して、initial_data.tar.gzをダウンロードします。

$ cd /home/isucon
$ curl -LO https://github.com/isucon/isucon12-qualify/releases/download/data%2F20220712_1505-745a3fdfb5783afc048ecaebd054acd20151872d/initial_data.tar.gz
$ tar xvf initial_data.tar.gz

docker-compose.ymlのvolumesセクションで用意したストレージの権限がrootになっていて、このままだとアプリの実行時に権限エラーになるので、まとめて書き換えておきます。

$ chown -R isucon:isucon /home/isucon

一回抜けて、isuconユーザーで再ログインする。

$ docker exec -it isucon12-qualify-bench-1 bash

最後に、初期データを準備する。

$ cd /home/isucon/data
$ make build-for-docker-compose

これで準備完了。

最初のベンチマークを取得する

$ cd bench
$ ./bench

初期スコアを確認して、あとはチューニングを始めましょう。

チューニングの準備

当日のマニュアルは熟読しましょう。

ISUCON12 予選当日マニュアル · GitHub

そもそもアプリケーションの仕様が分からないと何もできないので、じっくり読みましょう。

github.com

webapp以下のディレクトリは、ビルドのたびにホストマシンのリポジトリの内容がコンテナ内のストレージにコピーされてからビルドが開始されます。 なので、アプリケーションコードの修正は、慣れた手元の環境でやると良いでしょう。

ISUCON本を用意する

用意ができたらISUCON本を見ながら、チューニングを始めましょう。

その他

  • Docker Desktop for Macではnetwork_modehost指定すると、本当のホストマシンであるmacから見えなくなってしまいます。せっかく作り込まれたフロントエンドの画面が見れないのはちょっと寂しいので、別の手段で環境を構築してみましょう。ネットワーク構成を作り直しても良いでしょう。
  • docker-compose.ymlや、Dockerfileの読み方は最低限理解しておくと良いでしょう。アプリケーションの切り替えや、再ビルドの方法がわからないとチューニングしても意味がないので。
  • 用意されている参照実装は一通り実行してみましょう。全部のソースを見るのは大変だけど、3種類くらい比較して見てみると面白いです。
  • useraddコマンドでグループ名を指定しない時の挙動が分からなかったので、調べたところ、/etc/default/useraddに書かれていました。そこなんだ?
# The default behavior (when -n and -g are not specified) is to create a
# primary user group with the same name as the user being added to the
# system.

2022/11/6 追記

MySQL 8.0.29の件、いくつか情報をいただきました。なるほどー酷いバグだ......

というわけで、PRを作成しておきました。

github.com

あと、Docker Desktop for Macのネットワークについても情報をいただきました。

docker-composeと、docker composeは違うとは......こちらも引き続き調べてみたいと思います。


現在では、docker-composeと、docker composeは同じV2を向いているようです。

qiita.com

Docker Desktop for Mac 4.13.1をクリーンインストールしたところ、docker-composeもV2を使う設定が最初からオンになっていました。

設計の「why」を言語化する

設計において、すべての決定について仔細に「なぜ、そうしたか?」を言えるべきなのだけど、これを上手く言語化できない人は多い。「このプロジェクトでは以前からそうしているから」「そうするのが当たり前だと思っていた」などなど、本当に理解してないまま「設計という作業」を進めている人もいれば、上手く自分の行為を言語化できないだけの人もいる。

また、必ずしも自分が設計したことについて説明する場面ばかりとも限らない。既に存在する設計から「なぜ」を類推するしかない場面もある。他人のコードを読み取るときに、振る舞いだけでなく、「なぜそうしたのか?」が分からないと、その後にどんな改修を加えれば適切になるのかは分からないからだ。「振る舞い」と「根拠」を同時に読み取る必要性が出てくる場面が多々ある。

だからこそ、設計の「why」を言語化するために、そもそも「なぜ?」が言えること、それを表現するテクニックを持っている人は設計における強い人と認識される。

「設計を取り巻く環境・構造」を正しく認識できていることにレビュアーと、レビュイーが合意できれば、そこでレビューはほぼ終わったも同然な訳です。

で、それがコミュニケーション力と言えるのかもしれないけど、これは完全に「教育と経験」で一定の底上げができるものなので、意識的にやっていくとよいのです。


そして引用RTでいただいたご意見がまた興味深いので、貼っておきます。みなさま、ありがとうございます。

『Fluentd実践入門』で設計を学ぶ

今までFluentdは全然使ったことが無かったこともあり、先日出版された『Fluentd実践入門』を読み始めました。

入門と謳われていますが、単なるインストール方法から基本的な使い方までを一通り説明して終わり、というような内容ではなく、そもそも「Fluentdとは何か」「どんな機能があるのか」「なぜそのような機能になっているのか?」「プロダクションレベルで運用するために何をすればいいのか」「プラグインはどうやって作るのか」と、500ページ近いボリュームで実践的な内容が網羅されています。

特に、第1章の「Fluentdとは何か」は、興味深くて、大量のデータをストリーム処理するための知見(バッファリングや、リトライ)がコンパクトにまとまっていて、ここを読むだけでも設計の「学び」が有ります。

第1章以外も至るところに、「なぜこういう設計になっているか?」ということが語られている箇所が多数登場するので、「あーなるほどー」と感心するところが多い1冊ですね。

複数のサーバが協調して動く環境で「上手くいかない時にどうするか?」を設計できているか否かで運用性が全然違ってきます。この辺りは良い設計を見て学ぶしかないので、単にFluentdのことを理解するだけでなく、実践的な設計の理解、という意味でもお勧めです。

Meraki Go Wi-Fi 6 アクセスポイント (GR12)がリリースされた

ずっと自宅では初代のMeraki Goアクセスポイントを使っていて、余計なルータ機能とか無いし、スマホからアプリで設定できるし、安定しているし、シンプルな外観で気に入っていたのだけど、Wi-Fi 6対応していないなーと思っていたら、ついにWi-Fi 6対応版がリリースされた!

さすがに円安を反映してか、前機種より値段が上がっているのがちょっとアレだけど、買い替えの時にはこれを買おう。

Wi-Fi 6対応以外にも、メッシュ対応と書かれている点が気になる。

Scalaで環境変数を参照する方法

sys.envを使う

sys.envという関数が用意されていて、実態はSystem.getenv()ScalaのMapのインタフェースで包んだものが得られます。immutableなので、書き換えることはできません。

存在しない環境変数を参照と例外が送出されますので、参照する際はgetOrElseでデフォルト値を必ず与えておくと良いでしょう。

短いので、Scala 2.13のソースコードをそのまま貼り付けてしまいます。

  def env: Map[String, String] = Map.from(System.getenv().asScala).withDefault { v =>
    val s = System.getenv(v)
    if (s == null) throw new NoSuchElementException(v)
    s
  }

scala.util. Propertiesを使う

Mapとして丸っとコピーするには環境変数は大きいので、必要な物だけアクセスすればいいのでは?ということで、scala.util.Propertiesに、envOrElse関数が用意されてます。

これも短いので、該当箇所をまるっと貼り付けてしまいますが、以下のようなコードになっています。

  def envOrElse(name: String, alt: => String)   = Option(System getenv name) getOrElse alt

sys.envの方がタイプ数が短いのだけど、若干「なんかScalaっぽくない」感じがするので、scala.util. Propertiesを使った方が好みです。また、ScalaJDKのバージョン取得用のメソッドが用意されていたりと、便利なメソッドが用意されているので、scala.util. Propertiesのメソッドは一通り見ておくと良いかも。

なぜ、「過剰な」アーキテクチャを作り込むのか?

何を以て、過剰か、というと定義しづらいけど、「作る物が増え過ぎて、品質保証が終わらない」「動かすために優先度が低い部分が作られない」「動く時は動くけど、動かない時は中途半端に動かない」「そもそも運用するために理解すべきことが多過ぎる」などなど...「本当にこれは必要なのかな?」と疑問に思う瞬間が訪れた時、「過剰」が存在するのかもしれない。

そして、「過剰」が発生するのは、このような分断があるからでは?と言えるかも。


振り返って「最適なアーキテクチャだった」と言い切るのはけっこう難しいけど、「最適ではなかった」ということは気付きやすいので、そういう言語化は大事だなーと。