isucon / isucon13 Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
CAUTION: this project is open for only #isucon administrators /webapp /webapp/perl /webapp/ruby /webapp/nodejs /tools /tools/benchmark /tools/domchecker /tools/scoreboard ** Webアプリの基本方針 -処理はすべてリクエストを受け取ってから実施する --DBへのクエリ --テンプレートからのレンダリング -全てのコンテンツをアプリケーションから渡す --js/css/画像も含めて -キャッシュ等はとりあえず全て無し ** 実装するリクエストハンドラ - / -- GET -- articleのリスト(投稿順(id順) 最新10個) --- SELECT id,title,body,created_at FROM article ORDER BY id DESC LIMIT 10 - /article/:articleid -- GET -- articleページの表示 (article + comments) --- SELECT id,title,body,created_at FROM article WHERE id=? --- SELECT name,body,created_at FROM comment WHERE article=? ORDER BY id なお全ページ、左側のサイドバーに「新しいコメントがついた順に記事10件」を表示 --- SELECT article FROM comment GROUP BY article ORDER BY created_at DESC LIMIT 10 - /post -- GET -- 記事投稿用HTML ただしベンチ対象外のURLとする - /post -- POST -- 記事投稿 -- パラメータはform形式で title, body --- INSERT INTO article SET ... -- レスポンスは / へのリダイレクト(成功)、もしくは適当なエラー用のHTTPステータス - /comment/:articleid -- POST -- コメント投稿 (投稿フォームは /article/:articleid の末尾) -- パラメータはform形式で name, body --- INSERT INTO comment SET ... -- レスポンスは /article/:articleid へのリダイレクト(成功)、もしくは適当なエラー用のHTTPステータス ** 添付するstaticファイル - 画像 -- isuconロゴを適当なサイズにして流用、ページトップのバナー画像にする - js -- jquery 最新版の minify 済みファイル -- jquery-ui 最新版の minify 済みファイル -- isucon.js デザイン調整用 - css -- jquery-ui の適当なスタイル用のもの一式 -- isucon.css デザイン調整用
ベンチマーカーのassetdirを指定すると、静的ファイル群が置いてあるパスからファイルを読み出して各ファイルが改変されていないかチェックする想定がある
現状未実装なので、これをきちんとやる
(assetdirからの読み出し自体はisucon9-finalのものを流用)
ansibleはパッケージに含まれるスキーマを適用して、indexをいじる
dockerはrepo上にあるスキーマを適用する
これを統一しておきたい
ISUCON13_FOO_BAR 系の使ってない環境変数を整理する
ミドルウェアなどで必要となる場合、Security Groupは変更してもOK。
ただし、運営やベンチマークに必要なポートが開放されなくなった場合は失格になります、というのを明記しておく
コメントで TODO FIXME 書いておいて最後に確認しましょう
diff --git a/bench/isupipe/client.go b/bench/isupipe/client.go
index 8df9d0e..7e7d291 100644
--- a/bench/isupipe/client.go
+++ b/bench/isupipe/client.go
@@ -514,11 +514,13 @@ func (c *Client) GetLivestreamsByTag(
option(&pat)
}
- urlPath := fmt.Sprintf("/livestream?tag=%s", tag)
- req, err := c.agent.NewRequest(http.MethodGet, urlPath, nil)
+ req, err := c.agent.NewRequest(http.MethodGet, "/livestream", nil)
if err != nil {
return bencherror.NewInternalError(err)
}
+ query := req.URL.Query()
+ query.Add("tag", tag)
+ req.URL.RawQuery = query.Encode()
resp, err := c.sendRequest(ctx, req)
if err != nil {
2023-11-11T11:57:52.124Z info isupipe-benchmarker webappの初期化を行います
不正な広告レベル
500が返った結果、広告レベルが取得できなくてこのエラーになるようですが、選手には分かりづらいのでstatus!=200の場合「initializeが失敗しました」と返した方がよいです。
ディレクトリ移動なく
make hoge を実行 => ansible 実行
で動くようにする。
ライブ配信に対する各種投稿履歴に基づいた統計情報算出エンドポイントの実装
10/25版webappのコードを見て気が付いたところを書いていきます
名前解決結果が参加者のインスタンスに割り振られたIP以外だったらエラーにする
参加者のインスタンスの3つのIPアドレスを取得して、ベンチマーカーに渡してあげる必要がある
直した方がよさそうなこと
感想
SET long_query_time = 60.0;
を頑張って書いていった本番では証明書確認を必須にする
ひとまず、誰がいくら支払ったか、投げ銭の記録を取れるサーバを作る
2-3回のリトライはしてもいいのかも
水責め時、ベンチ実行時はやらない。
pretest、finalcheck時にのみリトライ行う
エラーログ、まだ err
が握りつぶされてそう #205 (実際のエラー内容がログにでていない + 出力元が main.go で統一されてしまってどこが出所か分からない)
Nov 12 00:22:31 isucon-app isupipe[289292]: {"time":"2023-11-12T00:22:31.202621676+09:00","level":"ERROR","prefix":"echo","file":"main.go","line":"220","message":"error at /api/livestream: code=500, message=failed to fill livestream"}
pdnsはzone file backendにしてmysqlと無関係にした
ng_word判定、N+1をいくつか解消して売上3000程度までいった
GET のエンドポイントで begin / commit を全て外してみたところ、なぜか売上が 0 になった
が、/api/livestream/search だけまだトランザクションが残っていたのを外したら 4500 に
DNSを別ホストに逃がしたらベンチがCPU 400%使うようになった
search/livestreams で limit も tag も引数に付いてこないので適当に LIMIT 1, 10, 100 としたらどれもベンチを完走した (本来のアプリ仕様を満たさない改変)
ここまでの所感
N+1が fillなんとか関数で発生している、これが多くの箇所から呼ばれているので解消がとても面倒くさい、けどボトルネックなのでやらざるを得ないので、ここから腕力で N+1 をなんとかするゲームになりそう。
売上: 10178の時点で
mysql> select sum(tip) from livecomments;
+----------+
| sum(tip) |
+----------+
| 4958790 |
+----------+
これと売上はどういう関係になっているんでしょう?
/
--- webapp
|_____ frontend
|_ viteのsccafoldしたやつら
|_____ go
|_ main.go
|_ movie_handlers.go
|_ user_handlers.go
|_ channel_handlers.go
|_ ...
|_____ sql
|_ create_database.sql
|_ create_table.sql
|_ insert_data.sql
1~3日以内にできるといいのかな、という想定
以下、セッションIDをCookieで扱う方式と仮定して記載
ログアウト機能はつくらないという話だったので含めない
User
を定義過去問題と同様のスパム判定処理だと焼き直しになってしまい、競技者の体験を損ねるのではないか
仕様の詰めもあるが、単純にAho-Corasickで判定するだけのこと以上のネタを考えたい
DNSの名前解決の数をカウントする
isucon13/webapp/go/livestream_handler.go
Line 380 in 9644b1b
failed to insert livestream_view_history
ではなく failed to delete livestream_view_history
最終的にoffにするかどうか確認
log-dns-queries=yes
loglevel=6
log-dns-details=yes
UDPでlistenすること、Aレコードを返すことを明記する
UDPで問い合わせた時にtc bitがつくのはいいけど、最初からTCPで問い合わせたりはしないよと
CNAMEを返されても再帰クエリしないよ、と明記する
Aレコード以外が帰ってきたらエラーにする
AAAAの問い合わせは無視してok
pdnsはALIASレコードあるので使おうと思えば使える
移植で一貫性が取れなくなるので、文字列でちゃんと返すように
情報が散らばると分かりづらくなるため、こちらに集約します
基本的には凍結するスタンスですが、動作に著しく支障をきたす場合は修正した上で差分をこちらのIssueに紐付けます
今はansibleでIPアドレスを渡しているが、
AMIでのサーバ作成時には渡すことができない
プロフィール画面で、ユーザのライブ配信を一覧できないとかなり寂しい感じになるということで、追加することになりました
ベンチマーカーでは、プロフィール訪問時に叩くことになります
現在のコードでは以下のようなエラーハンドリングになっていますが、実際に発生したerr
をどこにも出力しないため原因を見つけるのがたいへん難しくなっています。
tx, err := dbConn.BeginTxx(ctx, nil)
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "failed to begin transaction")
}
c.Logger().Errorf()
を使って別途エラーログを吐くか、NewHTTPErrorのメッセージに err.Error() を含める必要があります。
lookuphostはhappy eyeballの動作のためAAAAの解決も行おうとする
今回に関しては必要ないので、miekg/dns での名前解決としたい
Lines 110 to 119 in 074362c
このコードは他の言語に移植が難しいので、これを追加するならsystemdの起動順を定義しておいた方がよさそう。
Idになっているのは意図的ですか?GoだとIDにすることが多いです。
paymentMu sync.RWMutex
は最終的にどうする予定ですか?これは他言語に移植できません。
Makefileの.PHONYは上に書く方が一般的だと思います。
スキーマでidがintとBIGINTが混ざっていますが、全部BIGINTでもいいかもですね。
goのディレクトリの中の.gitignoreの一番下にisupipeと書かれていますが、どこでgitignoreされているかが競技者から分かりにくいかもしれません。
webpapp/go/initial_livestreams.sql
は何のために存在していますか? initializeで必要な他の言語実装でも必要なのでgoディレクトリはおかしいです。
Dockerfileのbullseyeは1つ前のDebianなので、できるなら新しいバージョンにしたいですね。
100, 200, 500, 1000, 2000, 5000, 10000, 20000
想定される解法をつくっておく
ベンチマークのパフォーマンス確認と、開催後のブログ記事用
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.