kavo’s diary

備忘録

ISUCON練習 private-isu[1] Windows上構築~ベンチ成功(0点)

private-isuをやっていく。

github.com

環境

  • Windows 10
  • Docker Desktop
  • 言語はGo

ログ

アプリ起動

  • Docker Desktopは起動しておく

してないとerror during connect: this error may indicate that the docker daemon is not running:

  • rubyで一回イメージ作った場合、docker-compose.ymlをgolangに書き換えてからイメージを再作成する

docker compose build app

  • 画面確認

ベンチ

  • 実行してみる
$ docker run --network host -i private-isu-benchmarker /opt/go/bin/benchmarker -t http://host.docker.internal -u /opt/go/userdata
exec /opt/go/run.sh: no such file or directory

Windows で Docker 環境構築時のエラー対処法【no such file or directory】

この問題か・・・git config --global core.autocrlf inputしてやり直し

  • 再実行
$ docker run --network host -i private-isu-benchmarker /opt/go/bin/benchmarker -t http://host.docker.internal -u /opt/go/userdata
/opt/go/run.sh: line 3: /opt/go/C:/Program Files/Git/opt/go/bin/benchmarker: No such file or directory

WindowsのGit Bashでパス変換が予期せぬ動作をする場合の対処法 - Qiita

今度はこれ。MSYS_NO_PATHCONV=1 で対処

  • 再々実行
$ MSYS_NO_PATHCONV=1 docker run --network host -i private-isu-benchmarker /opt/go/bin/benchmarker -t http://host.docker.internal -u /opt/go/userdata
{"pass":false,"score":25,"success":68,"fail":6,"messages":["静的ファイルが正しくありません (GET /css/style.css)","静的ファイルが正しくありません (GET /js/main.js)","静的ファイルが正しくありません (GET /js/timeago.min.js)"]}

webappの方の資材再作成忘れてた

  • 再々々実行
$ MSYS_NO_PATHCONV=1 docker run --network host -i private-isu-benchmarker /opt/go/bin/benchmarker -t http://host.docker.internal -u /opt/go/userdata
{"pass":true,"score":0,"success":209,"fail":64,"messages":["リクエストがタイムアウトしました (GET /)","リクエストがタイムアウトしました (GET /@angelina)","リクエストがタイムアウトしました (GET /@clarissa)","リクエストがタイムアウトしました (GET /@colleen)","リクエストがタイムアウトしました (GET /@dina)","リクエストがタイムアウトしました (GET /@ilene)","リクエストがタイムアウトしました (GET /@kristina)","リク 
エストがタイムアウトしました (GET /@olivia)","リクエストがタイムアウトしました (GET /@rowena)","リクエストがタイムアウトしました (GET /@shana)","リクエストがタイムアウトしました (POST /login)","リクエストが
タイムアウトしました (POST /register)"]}

スコア0だけどようやくpass!

makeインストール

ローカルでもmakeできるように。

Make for Windows

  • PATH通し

C:\Program Files (x86)\GnuWin32\bin

where make

ISUCON練習 ISUCON12予選環境構築(自己署名証明書利用)

久しぶりに構築。色々あったのでやり方メモ。

資材

aws-isucon/isucon12-qualify at main · matsuu/aws-isucon · GitHub

構築

インスタンス起動

インスタンスタイプ選択

https://ap-northeast-1.console.aws.amazon.com/ec2/home?region=ap-northeast-1#SpotInstances:

足りるか分からないが一旦安いt3.microにする→apt updateで無応答になってしまったのでt3a.mediumに変更。

インターネットからの HTTPS トラフィックを許可 をチェック。

ssh接続に成功。

ssh -i "2021-06-14-isucon-renshu.pem" ubuntu@ec2-hoge.ap-northeast-1.compute.amazonaws.com

ベンチ正常終了に成功。

h$ ./bench -target-addr 127.0.0.1:443
[ADMIN] 19:50:46.609523 TargetURL: https://t.isucon.dev, TargetAddr: 127.0.0.1:443, RequestTimeout: 30s, InitializeRequestTimeout: 30s, StrictPrepare: true, ReproduceMode: false
[ADMIN] 19:50:52.497786 POST /initialize 200 初期化
19:50:52.497895 初期化リクエストに成功しました 実装言語:go
19:50:52.497912 整合性チェックを開始します
[ADMIN] 19:50:52.528032 POST /api/admin/tenants/add 200 新規テナント作成
[ADMIN] 19:50:52.550243 GET /index.html 200 /index.htmlを確認
[ADMIN] 19:50:52.556737 GET /js/app.3a4ec98c.js 200 /js/app.3a4ec98c.jsを確認
...
19:52:19.417110 Error 1 (Critical:0)
19:52:19.417121 PASSED: true
19:52:19.417132 SCORE: 1880 (+1898 -18(1%))

クライアント証明書

おいてあるファイルのままだとChromeにインポートできなかったので変換。

cd /etc/nginx/tls
openssl pkcs12 -export -in fullchain.pem -inkey key.pem -out fullchain.p12

isucon12-qualify/nginx/tls at main · isucon/isucon12-qualify · GitHub

設定してみたがERR_CONNECTION_TIMED_OUT

期限切れてた。

$ openssl x509 -in fullchain.pem -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            03:b0:ab:d5:14:2d:81:74:e8:26:1a:d4:f8:21:ae:20:62:87
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, O = Let's Encrypt, CN = R3
        Validity
            Not Before: Jun 17 04:40:52 2022 GMT
            Not After : Sep 15 04:40:51 2022 GMT
openssl genpkey -algorithm RSA -out key.pem -pkeyopt rsa_keygen_bits:2048
openssl req -new -key key.pem -out request.csr
openssl x509 -req -days 365 -in request.csr -signkey key.pem -out fullchain.pem
openssl dhparam -out dhparam.pem 2048

sudo cp /tmp/mycert2/myserver.crt fullchain.pem
sudo cp /tmp/mycert2/myserver.key key.pem

sudo service nginx restart
sudo service nginx status

これだとブラウザアクセスが上手く行かない。

Unable to communicate securely with peer: requested domain name does not match the server’s certificate. HTTP Strict Transport Security: true HTTP 公開鍵ピンニング: false

Google Chrome から HTTPS でアクセスすると警告が表示される - Customer Support

Subject Alternative Name (SAN) の設定がないのがダメなのかも。

san.conf

[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no

[req_distinguished_name]
CN = *.t.isucon.dev

[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.t.isucon.dev
DNS.2 = isucon.t.isucon.dev
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout myserver.key -out myserver.crt -config san.cnf
openssl pkcs12 -export -out myserver.pfx -inkey myserver.key -in myserver.crt

ファイル入れ替えてnginx再起動

それでもERR_SSL_KEY_USAGE_INCOMPATIBLEになった。 Key Usage属性がダメっぽい。

openssl genrsa -out myserver.key 2048
openssl req -new -key myserver.key -out myserver.csr -subj "/CN=*.t.isucon.dev"
echo basicConstraints = CA:FALSE > extfile.cnf
echo subjectAltName = DNS:*.t.isucon.dev >> extfile.cnf
echo keyUsage = digitalSignature, nonRepudiation, keyEncipherment >> extfile.cnf
openssl x509 -req -days 365 -in myserver.csr -signkey myserver.key -out myserver.crt -extfile extfile.cnf
openssl pkcs12 -export -out myserver.pfx -inkey myserver.key -in myserver.crt

openssl x509 -in myserver.crt -text -noout

ファイル入れ替えてnginx再起動

ここまでやってもNET::ERR_CERT_AUTHORITY_INVALID。

そのあと↓とchrome再起動をやったらできた。どれが最低限必要だったのか整理できてないが、一旦ブラウザ表示はできた。

アドレスバーに chrome://net-internals/#hsts を入力します。
"Delete domain security policies" のセクションに移動します。
"Delete domain" のフィールドにドメイン名(例:isucon.t.isucon.dev)を入力し、"Delete" ボタンをクリックします。

Terraform Associateに合格した

Terraform Associateに合格した。体験記を書いておく。(勿論規約上書ける範囲で)

費用

項目 費用(円)
試験 9,366
Udemy 2,400
AWS 236
合計 12,002

教材

事前知識:仕事で何度か簡単なtf修正、plan/applyを経験したことがあるくらいの状態だった。

学習方法

公式Associate Tutorial List

用意した環境

Windowsだと環境エラーに引っかかるかもと思っていたが、特に問題はなかった。 AWS費用は全チュートリアルをやって2ドル弱だった。

チュートリアル実施の流れ

ドキュメントを読んだ上で、

  • AWSでアクセスキー発行
  • Visual Studio CodeでTerraform拡張で補完を効かせつつ写経
  • terraformコマンドで実行
  • AWSコンソールでできたものを見る

のような感じで実施した。

Udemy

  • 問題を解くとき:本番が英語なので、英文読む練習を兼ねて基本そのままで解く
  • 解説を見るとき:Chromeの翻訳機能で日本語にして読む

Udemyは問題文以外のペインの表示が大きくて見づらいが、サポートに聞いたところ畳む方法はないとのこと。

結果

Status: Pass

Overall Score: 91%

結果は試験ツールでも見られるが、終わってすぐにメールでも届いていた。

困ったこと

試験前

  • 試験ポータルサイトのログイン方法がおそらくGithub連携のみだったのだが、前日にGithubが不安定になってログインで500エラーがでていて不安だった。結局当日は問題なかった。

試験中

  • 最初に試験ツールが他アプリ終了を要求するが、Dropboxが終了させてもタスクマネージャからキルしても復活してチェックを通せなかった。仕方ないのでDropboxをアンインストールして対処した。
  • たまにアプリが自動起動するのか、OutlookやPhone(何のアプリか不明)が試験ツールにブロックされたという表示が出た。OKを押すだけで消えたが、試験に影響しないか不安だった。結局特に問題はなかった。

感想

公式のチュートリアルが実践的で良かった。

机からディスプレイはどけたが、電源ケーブルと映像ケーブルは流石に大変でそのままにしていたが、特に何も言われなかった。

参考にした記事

[資格受験]Terraform Associate を振り返る

Terraform Associateに最短で合格する方法を考えてみた | CCIE TOZAIとITを楽しむブログ

LeetCode Weekly Contest 282 復習

leetcode.com

Rank 4615 / 22307 4問目DPが解けなかった

問題

  1. . Minimum Time to Finish the Race https://leetcode.com/contest/weekly-contest-282/problems/minimum-time-to-finish-the-race/

解説

この解説が分かりやすかった https://leetcode.com/problems/minimum-time-to-finish-the-race/discuss/1802444/C%2B%2B-Linear-time-DP-with-explanation

ポイント

アルゴリズム

  • 問題文からdp[n+1]がdp[n]から導けそうなことに気づく
  • 問題文から漸近式を導く
    • タイヤを交換するしない
    • さかのぼって交換する場合もタイヤの連続使用回数の上界で縛れること
  • オーダを落とすための制約(タイヤの連続使用回数の上界がchangeTimeとfi * ri(x-1)から導かれる)

実装

  • int32超え(2e9)の扱い

ISUCON11予選記録 Fratty 164位

チームFratty、ISUCON11予選は参考スコア27426 164位でした。悔しい・・・。

振り返りのためのメモ。

時系列

大きくスコアが伸びたポイント

時刻 スコア メモ
10:06 1631 初回
11:38 16614 インデックス追加1回目
15:55 31803 N+1 trend, getIsuList / DB分散

スコアグラフ f:id:kavohtn:20210822154534p:plain

スコア表 f:id:kavohtn:20210822154611p:plain 後半は点数記入する余裕がなかったが、結局31803が最高点だった。

やったこと

  • mockの停止:効果不明瞭
  • インデックス追加(1):明らかに向上
  • インデックス追加(2):効果不明瞭
  • N+1解消 /api/trend:効果不明瞭(スコアがさがったが対象APIは高速化していた)
  • N+1 getIsuList / DBを別サーバに分散:明らかに向上(一緒にやってしまったので混在)
  • nginx処理の別サーバへの分散:効果不明瞭、ただしサーバ1号機のサチりは解消できていた
  • drop値チューニング:結局、タイムアウトを減らせなかったので初期の0.9が一番スコアが出てそうだった

良かったこと

  • ダッシュボードの導入で、修正前後の結果をSQLAPI1本の単位での比較が高速にでき、修正影響の評価精度があがった
  • N+1解消が例年より早くできた

できなかったこと

  • タイムアウトがなぜ起きるのかを突き止める必要があると思っていたが、それを調べる方法がわからなかった
    • nginxの499ログのidからなにかできたかも

トラブル

  • Goのパス周りが壊れる(解決)

    • ビルドが一時できなくなる。.bashrcの読み直しにより解消。
  • VSCodeでGo拡張機能が動かない(未解決)

    • これの影響でIDE機能が使えず、Goの記述速度がかなり低下した
    • ローカルや別サーバでやろうとしたが、could not import...のエラーで動かせず断念。
  • モニタ枚数が足りなくて写したい情報が写せず、操作にスイッチングコストがかかっていた(長時間なので、馬鹿にならない疲労になる)

  • CloudFormationで別スタックを立てて並列開発できると思っていたが、IP数制限に引っかかった

  • CloudFormationでAMIを差し替えて切り戻しや複製ができると思っていたが、内部IPのような固定パラメータがupdateを阻害してできなかった

  • ダッシュボードでパーセンタイルデータを出してなかったので解析精度が落ちた

今後やりたいこと

  • タイムアウトの原因を特定できるようにする
  • スコアの上下に頼りすぎず、自分たちで出したメトリクスで修正結果の良し悪しを判断できるようにする
  • GoのIDE機能をいつでも使えるように準備する
  • モニタ枚数を十分に用意する

ISUCON10本選 練習環境構築 ベンチマーカーを動作させる

ISUCON10本選に挑戦してみたくてまずは環境構築したメモ。

とりあえずベンチ実行してスコアが出てアプリが見えるところまでやった。

ISUCON10 本選当日マニュアルは以下。

isucon10-final/manual.md at master · isucon/isucon10-final · GitHub

インスタンス起動、SSH接続

「ISUCONの過去問にチャレンジするためのシンプルな環境構築」を使う(ISUCON9予選) - kavo’s diary と同様にami-0f7362c1bbc7e30ecを使ってインスタンスを立ち上げ、SSH接続。

isuconユーザに切り替え。

$ sudo -i -u isucon

サービス起動

立ち上げた直後は起動していないので、起動する。 参考実装の切り替え方法

sudo systemctl enable --now xsuportal-web-golang.service
sudo systemctl enable --now xsuportal-api-golang.service

仮想ポータルアクセス

どこから仮想ポータルを見られるのかは当日マニュアルとアプリケーションマニュアルをざっと見ただけだと分からなかった。が、xsuportal-api-golang.serviceのログで9292で受けてるっぽいことに気づく。

$ sudo systemctl status xsuportal-api-golang.service
...
 http server started on [::]:9292

curlしてみると弾かれる。ポート開けてなかった。

$ curl localhost:9292

AWSコンソールで9292を開けたらcurlでhtmlが返ってきた。

$ curl localhost:9292
<!doctype html><html lang="ja" class="has-background-grey-lighter"><head><title>XSUCON Portal</title><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="xsu:api-base-url" content="/"/><link href="/packs/vendor.css" rel="stylesheet"></head><body><div id="app"></div><script src="/packs/vendor.js"></script><script src="/packs/audience.js"></script></body></html>i

ブラウザでhttp://x.x.x.x:9292/ を開くとタイトルだけ出て中身はカラのページが見えた。

f:id:kavohtn:20210617042044p:plain

ベンチマーク実行

ポータルの中身はカラに見えるのは以下の理由のよう。

なお、初期状態ではアプリケーションの動作に必要なデータが不足しているため、アプリケーションをブラウザから動作確認するためには、一度負荷走行を実行してください (後述)。

Running a benchmarker locallyのコマンドを参考に実行してみる。そのままだと下記エラーになる。3000番ポートで待ってなさそうだし、本番と同じ構成になってなさそう。

dial tcp [::1]:3000: connect: connection refused

$ sudo lsof -i:3000
$

試しにtargetのポートをapiが受けてる9292に変更し実行してみる。

$ ./bin/benchmarker     -exit-status     -target app.t.isucon.dev:9292     -host-advertise local.t.isucon.dev     -tls-cert ../secrets/cert.pem     -tls-key ../secrets/key.pem 
16:56:17.000277 ISUCON10 benchmarker e858b2588a199f9c7407baacf48b53126b8aeed6+dirty
16:56:17.001955 ===> PREPARE
16:56:26.754919 Language: go
16:56:26.754936 HTTP: http://app.t.isucon.dev:9292/(tls=false)
16:56:26.754942 gRPC: localhost:50051
16:56:26.755009 ===> LOAD
16:56:26.755049 LOAD INFO
  Registration Open at: 2021-06-16 16:56:27 +0000 UTC
  Contest Start at: 2021-06-16 16:56:37 +0000 UTC
  Contest Freeze at: 2021-06-16 16:57:17 +0000 UTC
  Contest Ends at: 2021-06-16 16:57:27 +0000 UTC
16:57:36.762065 ===> VALIDATION
16:57:47.793989 ERR: validation: critical: http: Get "http://app.t.isucon.dev:9292/api/contestant/dashboard": context canceled
16:57:47.794491 ERR: validation: timeout: critical: timeout: http: timeout: Get "http://app.t.isucon.dev:9292/api/contestant/dashboard": context deadline exceeded
16:57:47.794515 ERR: validation: timeout: critical: timeout: http: timeout: Get "http://app.t.isucon.dev:9292/api/contestant/dashboard": context deadline exceeded
16:57:47.794636 ERR: validation: critical: http: Post "http://app.t.isucon.dev:9292/api/login": context canceled
16:57:47.794724 ERR: validation: critical: http: Get "http://app.t.isucon.dev:9292/api/contestant/dashboard": context canceled
16:57:47.794820 ERR: validation: critical: http: Get "http://app.t.isucon.dev:9292/api/contestant/dashboard": context canceled
16:57:47.794877 ERR: validation: critical: http: Get "http://app.t.isucon.dev:9292/api/contestant/dashboard": context canceled
16:57:47.794933 ERR: validation: critical: http: Get "http://app.t.isucon.dev:9292/api/contestant/dashboard": context canceled
16:57:47.794989 ERR: validation: critical: http: Get "http://app.t.isucon.dev:9292/api/contestant/dashboard": context canceled
16:57:47.795089 ERR: validation: critical: http: Get "http://app.t.isucon.dev:9292/api/contestant/dashboard": context canceled
16:57:47.805110 ===> SCORE
Count: 
  admin-answer-clarification: 8
  admin-get-clarification: 8
  admin-get-clarifications: 73
  audience-get-dashboard: 370
  create-team: 10
  enqueue-benchmark: 118
  finish-benchmark: 109
  get-clarification: 8
  get-dashboard: 60
  join-member: 20
  list-notifications: 1491
  post-clarification: 8
  resolve-clarification: 8
(1290 * 1.0) + 37 - 400(err: 0, timeout: 405)
Pass: false / score: 927 (1327 - 400)
Fail reason: Critical error

Pass: falseとあるが、一応スコアは出ている。

ポータルサイトもタイムラインチャートやリーダーボードが見えるようになった。

f:id:kavohtn:20210617035556p:plain

ユーザとしてログインして管理者・競技者のページも見えた。

XSUCON Admin f:id:kavohtn:20210617044914p:plain

XSUCON Contestant f:id:kavohtn:20210617045059p:plain

最低限ベンチ動作とアプリが見えるようになった。

「ISUCONの過去問にチャレンジするためのシンプルな環境構築」を使う(ISUCON9予選)

公式で用意されているお手軽構築を使ったメモ https://isucon.net/archives/54946542.html

今回はISUCON9予選をやってみる。

キーペア作成

f:id:kavohtn:20210615005301p:plain

EC2>インスタンスを起動

f:id:kavohtn:20210615005704p:plain

AMI検索

https://github.com/matsuu/aws-isucon のAMI IDで検索。今回は「ami-03b1b78bb1da5122f」で検索し、コミュニティ AMI (1)を選択。

f:id:kavohtn:20210615005758p:plain

インスタンスタイプ選択

今回はt3.smallにしてみる。 https://aws.amazon.com/jp/ec2/pricing/on-demand/ f:id:kavohtn:20210615005941p:plain

安くしたいのでスポットインスタンスを使う。

f:id:kavohtn:20210615010046p:plain

セキュリティグループ

SSH接続と、アプリをブラウザから見たいので22と80を開けておく。(IP縛った方が安全。)

f:id:kavohtn:20210615010128p:plain

起動>キーペア選択

さっき作ったのを選ぶ。 f:id:kavohtn:20210615010303p:plain

起動後にSSH接続しようとするとConnection timed out。

ネットワーク設定修正

こちらのチェックリストに助けられた。 https://qiita.com/yokoto/items/338bd80262d9eefb152e

インターネットゲートウェイがdetachedになっていたのでVPCにアタッチ。 f:id:kavohtn:20210615010713p:plain

また、ルートテーブルにIPv4のルートがなかったので追加。 f:id:kavohtn:20210615010957p:plain

SSH接続

ローカルPCのgit bashからつないでみる。接続成功。

$ ssh -i "2021-06-14-isucon-renshu.pem" ubuntu@18.x.x.x
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 5.4.0-1045-aws x86_64)
...

アプリ画面を見る

https://18.x.x.x/ にブラウザでアクセスする。警告が出るが、続行するとアプリ画面が見えた。 f:id:kavohtn:20210615011622p:plain

めっちゃお手軽でありがたみがすごい。