ISUCON の練習環境については色々記事がありますが、そもそも出たことない人にとってはまあまあハードル高く感じたので、一旦ベースのところから資料まとめていきたいなと思います
ISUCON 情報
当日の進め方 https://gist.github.com/matsukaz/6af9dd76d62e2cddb65fafa5b0636e9a
1.ISUCONで本選進出するために https://zenn.dev/tohutohu/articles/3dfabe751c743f
[NG]ISCUON11 の環境を簡単に構築できるらしい https://github.com/isucon/isucon11-qualify/tree/main/provisioning/cf-kakomon
[] ISUCON13 https://github.com/isucon/isucon13
summary
- isucon13 でやったこと
- AMI から EC2 インスタンス起動
- 証明書使ってたので更新
- bench側の信頼ストアに証明書投入
- クライアント側で chromium 使用し、SSLエラーを無視して接続
- ブラウザでの動作確認とベンチマーク起動によるポイント確認
- ISUCON 12 とか、単一 EC2 じゃないタイプだとまた変わりそう
ISUCON13 検証
https://github.com/isucon/isucon13
- ami-041289d910c114864 で EC2 を起動→まだある
EC2立ち上げてログイン。su で isucon user に切り替えてホームへ移動
pwd
/home/isucon
ls -l
total 39588
-rwxr-xr-x 1 root root 40517898 Nov 27 2023 bench_linux_amd64
-rwxr-xr-x 1 isucon isucon 334 Nov 6 01:22 env.sh
drwxrwxr-x 3 isucon isucon 4096 Nov 27 2023 go
drwxr-xr-x 8 isucon isucon 4096 Nov 27 2023 local
drwxr-xr-x 13 isucon isucon 4096 Nov 24 2023 webapp```
tree -L 2 . ├── bench_linux_amd64 ├── env.sh ├── go │ └── pkg ├── local │ ├── golang │ ├── node │ ├── perl │ ├── php │ ├── python │ ├── ruby │ └── rustup-init.sh └── webapp ├── go ├── img ├── node ├── pdns ├── perl ├── php ├── public ├── python ├── ruby ├── rust └── sql
すでに nginx が立ち上がっている。
証明書は自己署名で、パブリックなドメインはないので、ローカルのhosts を編集して大会用ドメインを検証環境IPへ向ける
for ISUCON
xxx.xxx.xxx.xxx pipe.u.isucon.dev xxx.xxx.xxx.xxx test001.u.isucon.dev
cat /etc/nginx/nginx.conf
証明書ない気がする。デフォルト配置あるか?
ls /etc/nginx/tls -la total 36 drwxr-xr-x 2 root root 4096 Nov 27 2023 . drwxr-xr-x 9 root root 4096 Nov 6 01:25 .. -rw-r–r– 1 root root 5591 Nov 27 2023 _.t.isucon.dev.crt -rw-r–r– 1 root root 1675 Nov 27 2023 _.t.isucon.dev.key -rw-r–r– 1 root root 5256 Nov 27 2023 _.u.isucon.dev.crt -rw-r–r– 1 root root 3751 Nov 27 2023 _.u.isucon.dev.issuer.crt -rw-r–r– 1 root root 227 Nov 27 2023 _.u.isucon.dev.key
普通に証明書が切れている。uとtは何が違う?
openssl x509 -in _.u.isucon.dev.crt -text
Validity
Not Before: Jun 17 04:40:52 2022 GMT
Not After : Sep 15 04:40:51 2022 GMT
Subject: CN = *.t.isucon.dev
秘密鍵 key はあるので、再度証明書作る?いや鍵も作り直す
openssl req -x509 -nodes -sha512 -days 365
-newkey rsa:2048 -keyout server.key
-out server.pem -subj “/CN=.u.isucon.dev” -addext “subjectAltName = DNS:.u.isucon.dev, DNS:u.isucon.dev”
sudo vi ../nginx.conf
ssl_certificate /etc/nginx/tls/server.pem;
ssl_certificate_key /etc/nginx/tls/server.key;
sudo chmod 711 server.key sudo service restart nginx
仮IP
35.72.35.148
ローカルのホストでドメインを上のIPへ向ける
sudo vi /private/etc/hosts
for ISUCON
35.72.35.148 pipe.u.isucon.dev 35.72.35.148 test001.u.isucon.dev
うまくいかん
あ〜〜〜 `/etc/nginx/sites-enabled` これ読み込んでるのね
以下を差し替え
cat sites-enabled/isupipe.conf
https://pipe.u.isucon.dev/ へアクセス
ERR_CERT_AUTHORITY_INVALID
これは想定通り
cat して local に保存したけど無理
正味、chromium をこれ用に使って TLS エラーをignore した方が早いかも
chromium –args –ignore-certificate-errors
一応 chromium 使うことで起動を確認
### 負荷かけてみる
pwd /home/isucon
./bench_linux_amd64 run
{“error”: “Post "http://pipe.u.isucon.dev:8080/api/initialize": 「pipe.u.isucon.dev」の名前解決に失敗しました。「35.72.35.148」はサーバーリストに含まれていません”} {“pass”:false,“score”:0,“messages”:[“初期化が失敗しました”,“initializeのリクエストに失敗しました Post "http://pipe.u.isucon.dev:8080/api/initialize": 「pipe.u.isucon.dev」の名前解決に失敗しました。「35.72.35.148」はサーバーリストに含まれていません”],“language”:“unknown”,“resolved_count”:0}
それはそう。bench が同じインスタンスだとそれはそう。これどうすrべき?
### ISUCON13 当日manual
https://github.com/isucon/isucon13/blob/main/docs/cautionary_note.md
- ISUPipe には、サーバーのWeb ブラウザから HTTPS でアクセスできます。
- ISUPipe へのログインは以下のアカウント情報を用いることができます。
- test001
- test
- 参考実装では2つのデータベースがあります。
- isupipe アプリケーションが利用するデータベース
- isudns PowerDNSのゾーン情報を格納するデータベース
- 変更してはいけない点
- envcheck.serviceに関わるファイル
- /etc/systemd/system/envcheck.service
- /etc/systemd/system/multi-user.target.wants/envcheck.service
- /opt/isucon-env-checker 内のファイル、バイナリファイル
- aws-env-isucon-subdomain-address.service に関わるファイル
- /etc/systemd/system/aws-env-isucon-subdomain-address.service
- /etc/systemd/system/multi-user.target.wants/aws-env-isucon-subdomain-address.service
- /opt/aws-env-isucon-subdomain-address.sh
- isuadmin ユーザに関わるファイルおよびログイン情報
- その他、主催者による追試を妨げる変更(例: サーバー上の isucon 以外のユーザに関する、ユーザ削除や既存の公開鍵の削除、サーバーの再起動の妨害)
- ポータルから負荷走行を実行した場合、指定したサーバー(IPアドレス)のDNSサーバー(53/UDP)に名前解決を行い、得られたIPアドレスに対してHTTPSでアクセスを行います。
- サーバーに DNS サーバーも乗っかってるので最終的には DNS のレスポンスも微妙に影響するっぽい?
- 負荷走行中、DNSサーバに対していわゆる「DNS水責め攻撃」が行われます。
- スコア計算
- スコアは一回の負荷走行中にISUPipeの投げ銭(Tip)機能により、送金・寄付された金額(ISUCON)の合計となります。
- スコアの合計額がサーバとベンチマーカーとで差分がある場合、ベンチマーカーで計測している値をスコアとします。
### 名前解決確認
dig pipe.u.isucon.dev @127.0.0.1 A +short 35.72.35.148
cat env.sh ISUCON13_MYSQL_DIALCONFIG_NET=“tcp” ISUCON13_MYSQL_DIALCONFIG_ADDRESS=“127.0.0.1” ISUCON13_MYSQL_DIALCONFIG_PORT=“3306” ISUCON13_MYSQL_DIALCONFIG_USER=“isucon” ISUCON13_MYSQL_DIALCONFIG_DATABASE=“isupipe” ISUCON13_MYSQL_DIALCONFIG_PARSETIME=“true” ISUCON13_POWERDNS_SUBDOMAIN_ADDRESS=“35.72.35.148” ISUCON13_POWERDNS_DISABLED=“false”
35.72.35.148 が返ってきているのはOK
https://github.com/matsuu/aws-isucon/tree/main/isucon13
を参考に確認
ベンチマークが微妙っぽい。これビルド済みだから無理かも...
おお、こんな感じでいけるっぽい
$ ./bench_linux_amd64 run –target https://pipe.u.isucon.dev
–nameserver 127.0.0.1 –enable-ssl
–webapp {サーバ2} –webapp {サーバ3}
これで見えるのか
./bench_linux_amd64 run –help
./bench_linux_amd64 run –target https://pipe.u.isucon.dev
–nameserver 127.0.0.1 –enable-ssl
./bench_linux_amd64 run –target https://pipe.u.isucon.dev –nameserver 35.72.35.148 –enable-ssl
curl -v –resolve pipe.u.isucon.dev:443:35.72.35.148 https://pipe.u.isucon.dev -k
200 OK
sudo lsof -i:53 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME pdns_serv 827 pdns 5u IPv4 17997 0t0 UDP *:domain pdns_serv 827 pdns 6u IPv6 17998 0t0 UDP *:domain pdns_serv 827 pdns 7u IPv4 17999 0t0 TCP *:domain (LISTEN) pdns_serv 827 pdns 8u IPv6 18000 0t0 TCP *:domain (LISTEN)
dig @127.0.0.1 pipe.u.isucon.dev +short 35.72.35.148 dig @35.72.35.148 pipe.u.isucon.dev +short
bench には public ip 指定が必要ぽい?
あ〜 DNS も使うから DNS のポート(UDPで)開けないとだめか
dig @35.72.35.148 pipe.u.isucon.dev +short 35.72.35.148
え〜結局証明書で落ちるのか...
{“pass”:false,“score”:0,“messages”:[“初期化が失敗しました”,“initializeのリクエストに失敗しました Post "https://pipe.u.isucon.dev:443/api/initialize": tls: failed to verify certificate: x509: certificate signed by unknown authority”],“language”:“unknown”,“resolved_count”:0}
Linux の信頼ストアは?以下っぽい? user でも追加できるっぽい
ls /etc/ssl/certs
cd /usr/share/ca-certificates/ sudo mkdir mylocal sudo cp /etc/nginx/tls/server.pem mylocal/ sudo su echo “mylocal/server.pem” » /etc/ca-certificates.conf update-ca-certificates exit
./bench_linux_amd64 run –target https://pipe.u.isucon.dev –nameserver 35.72.35.148 –enable-ssl
{“pass”:false,“score”:0,“messages”:[“初期化が失敗しました”,“initialize へのリクエストに対して、期待されたHTTPステータスコードが確認できませんでした (expected:200, actual:502)"],“language”:“unknown”,“resolved_count”:0}
証明書はOKぽいけど 502 返ってくる
サーバー側問題くさいと思う。多分 mysql 繋がってない
ps aux | grep “mysql” mysql 7268 0.1 10.8 1787920 409772 ? Ssl 01:26 1:06 /usr/sbin/mysqld isucon 63580 0.0 0.0 6612 2560 pts/1 S+ 16:18 0:00 grep –color=auto mysql
## ログは?
systemd から調べる
vi /etc/systemd/system/isupipe-go.service sudo service isupipe-go status
[Unit] Description=isupipe-go After=syslog.target After=mysql.service Requires=mysql.service
[Service] WorkingDirectory=/home/isucon/webapp/go EnvironmentFile=/home/isucon/env.sh
User=isucon Group=isucon ExecStart=/home/isucon/webapp/go/isupipe ExecStop=/bin/kill -s QUIT $MAINPID
Restart=on-failure RestartSec=5
[Install] WantedBy=multi-user.target
sudo service isupipe-go status
Main PID: 826 (code=killed, signal=TERM)
sudo service isupipe-go restart
リスタートで動作sita!
### mysql
sudo mysql isupipe show tables; +—————————-+ | Tables_in_isupipe | +—————————-+ | icons | | livecomment_reports | | livecomments | | livestream_tags | | livestream_viewers_history | | livestreams | | ng_words | | reactions | | reservation_slots | | tags | | themes | | users | +—————————-+ 12 rows in set (0.00 sec)
select * from domains; +—-+————–+——–+————+——–+—————–+———+———+———+ | id | name | master | last_check | type | notified_serial | account | options | catalog | +—-+————–+——–+————+——–+—————–+———+———+———+ | 2 | u.isucon.dev | | NULL | NATIVE | NULL | | NULL | NULL | +—-+————–+——–+————+——–+—————–+———+———+———+
やっと動いた...?
### ベンチマーク
./bench_linux_amd64 run –target https://pipe.u.isucon.dev –nameserver 35.72.35.148 –enable-ssl
livestream 動いてないっぽい?
2回目で成功
2024-11-06T16:30:51.696Z info staff-logger bench/bench.go:260 ベンチマーク走行時間: 1m0.332004691s 2024-11-06T16:30:51.697Z info isupipe-benchmarker ベンチマーク走行終了 2024-11-06T16:30:51.697Z info isupipe-benchmarker 最終チェックを実施します 2024-11-06T16:30:51.698Z info isupipe-benchmarker 最終チェックが成功しました 2024-11-06T16:30:51.698Z info isupipe-benchmarker 重複排除したログを以下に出力します 2024-11-06T16:30:51.698Z info staff-logger bench/bench.go:277 ベンチエラーを収集します 2024-11-06T16:30:51.698Z info staff-logger bench/bench.go:285 内部エラーを収集します 2024-11-06T16:30:51.699Z info staff-logger bench/bench.go:301 シナリオカウンタを出力します 2024-11-06T16:30:51.699Z info isupipe-benchmarker 配信を最後まで視聴できた視聴者数 {“viewers”: 8} 2024-11-06T16:30:51.699Z info staff-logger bench/bench.go:323 [シナリオ aggressive-streamer-moderate] 17 回成功 2024-11-06T16:30:51.700Z info staff-logger bench/bench.go:323 [シナリオ dns-watertorture-attack] 8 回成功 2024-11-06T16:30:51.700Z info staff-logger bench/bench.go:323 [シナリオ streamer-cold-reserve] 34 回成功, 2 回失敗 2024-11-06T16:30:51.701Z info staff-logger bench/bench.go:323 [シナリオ streamer-moderate] 38 回成功 2024-11-06T16:30:51.701Z info staff-logger bench/bench.go:323 [シナリオ viewer-report] 35 回成功, 2 回失敗 2024-11-06T16:30:51.701Z info staff-logger bench/bench.go:323 [シナリオ viewer-spam] 19 回成功 2024-11-06T16:30:51.702Z info staff-logger bench/bench.go:323 [シナリオ viewer] 8 回成功 2024-11-06T16:30:51.702Z info staff-logger bench/bench.go:323 [失敗シナリオ streamer-cold-reserve-fail] 2 回失敗 2024-11-06T16:30:51.702Z info staff-logger bench/bench.go:323 [失敗シナリオ viewer-report-fail] 2 回失敗 2024-11-06T16:30:51.703Z info staff-logger bench/bench.go:329 DNSAttacker並列数: 2 2024-11-06T16:30:51.703Z info staff-logger bench/bench.go:330 名前解決成功数: 1358 2024-11-06T16:30:51.703Z info staff-logger bench/bench.go:331 名前解決失敗数: 91 2024-11-06T16:30:51.704Z info staff-logger bench/bench.go:335 スコア: 2388
## DBに index 貼ってみる?
大体こういうときは mysql slow log 出すとか profiler の出番な気がするが
sudo mysql isupipe
SHOW COLUMNS FROM users
;
SHOW COLUMNS FROM users
;
+————–+————–+——+—–+———+—————-+
| Field | Type | Null | Key | Default | Extra |
+————–+————–+——+—–+———+—————-+
| id | bigint | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | UNI | NULL | |
| display_name | varchar(255) | NO | | NULL | |
| password | varchar(255) | NO | | NULL | |
| description | text | NO | | NULL | |
+————–+————–+——+—–+———+—————-+
この辺見る限りえぐ目のクエリが多い?
https://github.com/isucon/isucon13/blob/main/webapp/go/top_handler.go#L75-L86
show index from users;
index は貼られてる。とってきてるデータが多いのが良くない?
https://github.com/isucon/isucon13/blob/main/webapp/go/user_handler.go
icon は static にしたいよね。AWS なら S3 + CF とかにできると嬉しいけど、そこまでじゃなくても static にしてキャッシュは効かせた方が良い
vi user_handler.go
ID だけとってくるよう変更
if err := tx.GetContext(ctx, &user, "SELECT * FROM users WHERE name = ?", username); err != nil {
sudo service isupipe-go restart sudo service isupipe-go status
### powerdns でクエリキャッシュさせる
https://ryuichi1208.hateblo.jp/entry/2022/09/12/223515
1.Authoritative Server Settings — PowerDNS Authoritative Server documentation
https://doc.powerdns.com/authoritative/settings.html
sudo vi /etc/powerdns/pdns.conf
cache-ttl=300 negquery-cache-ttl=300 query-cache-ttl=300
sudo service pdns status
## index はる
alter table themes add index idx_user_id (user_id); alter table icons add index idx_user_id (user_id);
bench してみる
## profiler 導入
これは全然わからんので、もう調査する
1.Go の pprof で ボトルネックを探して ISUCON で優勝する
https://zenn.dev/team_soda/articles/d4701665e8a3a7
そろそろ VS Code でアクセスできないとだいぶしんどいかも..
一旦次に分割する
## ISUCON11 検証
CloudFormation から立ち上げ
Bench が 1, 本番が3って構成らしい
SSH 全開放は辛いので、自分の IP 一本になるよう SG を絞る
全体構成はこんな感じ
![[../../Pasted_image_20241106101056.png]]
できれば SSM SessionManager 作った形式に書き直したいところ
と思ったら、Template 作成でエラー。image IDがないだと。。。
> なお AMI は ISUCON11 運営の解散を目処に公開を停止する予定です。上記イメージが参照不可である場合ひとつ下の手順で構築してください。
なるほど