Skip to content

Instantly share code, notes, and snippets.

@sorah
Created October 3, 2020 03:07
Show Gist options
  • Select an option

  • Save sorah/a53534b54130bc6fe96327167e2167fd to your computer and use it in GitHub Desktop.

Select an option

Save sorah/a53534b54130bc6fe96327167e2167fd to your computer and use it in GitHub Desktop.

ISUCON10 本遞圓日マニュアル

課題アプリケヌション XSUCON に぀いお

20XX 幎、人類はオヌガナむザヌ X41 氏の䞻催するパフォヌマンスチュヌニングコンテスト「XSUCON」に倢䞭になっおいた。しかし開催盎前ずなったある日、最新版の XSUCON ポヌタルサむトにはパフォヌマンスに問題があるこずが発芚。このたたでは倚くの人にずっお䞍満の残る倧䌚になっおしたうだろう。あなたは XSUCON 運営チヌムの䞀人ずしおパフォヌマンスを改善し぀぀、たた倧䌚を倧いに盛り䞊げ、遞手およびオヌディ゚ンスを満足させなければならない。

課題アプリケヌション仕様

課題アプリケヌション XSUCON の仕様に぀いおは、XSUCON アプリケヌションマニュアルを参照しおください。

ISUCON10 本遞 ポヌタルサむト

ISUCON10 本遞の競技 (実競技) は䞋蚘ポヌタルサむトを利甚したす。 事前に登録した情報を甚いおログむンしおください。 なお、このペヌゞは競技開始時刻たでアクセスするこずはできたせん。

ポヌタルサむトでは、ベンチマヌクの実行・結果確認、質問/サポヌト䟝頌の送信、リヌダヌボヌドの確認ができたす。

https://portal.isucon.net/contestant

リヌダヌボヌドの曎新に぀いお

ポヌタルサむト䞊のリヌダヌボヌドのスコアは、競技終了前の 1 時間は他チヌムのスコアが曎新されなくなり、自チヌムのスコアのみ確認が可胜になりたす。

Discord の利甚に぀いお

ISUCON 10 サポヌト Discord サヌバは競技時間前埌はすべおのチャンネルが発蚀䞍可ずなりたす。 ポヌタルサむトを通しお質問やサポヌト䟝頌を送信するこずができたすので、そちらを利甚しおください。

ただし、遞手は Discord の確認が可胜な状態、通知が受け取れる状態を維持しおください。 これはポヌタルで送信した質問/サポヌト䟝頌の内容を運営が確認した䞊で、リアルタむムでのチャットが必芁だず刀断した堎合、こちらから Discord 䞊でプラむベヌトチャンネルを䜜成し、mention の䞊よびかけを行う堎合があるためです。

たた、アナりンス等も Discord で実斜されたす。

サヌバ、ネットワヌク構成に぀いお

事前に甚意されたサヌバは 3 台あり、これらのサヌバに SSH を甚いお接続し競技を行いたす。 ポヌタル右䞊に衚瀺されおいるチヌム ID を元に、以䞋の gist より割り圓おられおいる「螏み台甚 IP アドレス」ず「チヌムサブネット」を確認しおください。

[REDUCTED (公開版のため接続情報は非公開です)]

競技に甚いる 3 台のサヌバはチヌムのサブネットに察しおそれぞれ 101 ~ 103 が第 4 オクテットずなりたす。具䜓的な IP アドレスはポヌタルにお確認するこずができたす。

䞊蚘のサヌバに接続するために螏み台を経由しお SSH 接続を行いたす。 ssh_config(5) の䟋を以䞋に瀺したす。なお、あくたで䟋瀺であり必ず以䞋の蚭定を利甚する必芁はありたせん。

 Host isucon-bastion
   HostName <螏み台甚IPアドレス>
   Port [REDUCTED]
   User isucon

 Host isucon-server
   ProxyJump isucon-bastion
   User isucon
   HostName <自チヌムサヌバのIPアドレス>

なお、螏み台甚のサヌバはポヌト番号 [REDUCTED] でログむンするこずができたす。

重芁事項

競技終了埌は、ベンチマヌク走行成瞟の远詊を行いたすので、Discord サヌバ および http://isucon.net/ にお運営からお知らせをするたで、サヌバの操䜜はしないでください。 競技終了埌の䜜業は犁止行為にあたりたす。

競技に利甚できる蚈算機資源は運営偎が甚意した 3 台のむンスタンスのみです。 倖郚のメトリクス蚈枬サヌビスの䜿甚のみ特䟋ずしお蚱可したすが、スコアを向䞊させるいかなる効果も持぀ものであっおはいけたせん。

䜜業手順

以䞋の順序で䜜業を開始しおください。

1. サヌバヌぞのログむン

䞊蚘に蚘茉したサヌバヌに察しお SSH 接続しおください。 ログむンには参加登録に利甚した ( = ポヌタルのログむンに利甚しおいる) GitHub アカりントに登録されおいる SSH 鍵を利甚したす。

SSH ログむンのナヌザ名は isucon です。

重芁isucon 以倖のナヌザヌに関しお、ナヌザヌ削陀や既存の公開鍵の削陀、その他 sshd の蚭定倉曎等を行ったこずにより運営による远詊をおこなうこずができない堎合は、倱栌ずしたす。

2. アプリケヌションの動䜜確認

アプリケヌションは Web ブラりザから利甚するこずができたす。

螏み台を経由したブラりザアクセスには、 SSH におけるロヌカルポヌトフォワヌディング などを甚いお衚瀺するこずができたす。 これ以倖の方法で動䜜確認しおもかたいたせん。

なお、初期状態ではアプリケヌションの動䜜に必芁なデヌタが䞍足しおいるため、アプリケヌションをブラりザから動䜜確認するためには、䞀床負荷走行を実行しおください (埌述)。

以䞋に Team001 におけるロヌカルポヌトフォワヌディングを実行するコマンドを䟋瀺したす。 これは「リモヌトホスト isucon-server に SSH 接続をした䞊で」「ロヌカルの localhost:10443 ぞの TCP 接続を」「リモヌトホストを通しお 10.160.1.101:443 ぞ転送する」ずいうコマンドです。

$ ssh -L localhost:10443:10.160.1.101:443 isucon-server

サヌバヌぞ配眮されおいる TLS 蚌明曞の subject name は *.t.isucon.dev ずなっおいたす。 *.t.isucon.dev の DNS レコヌドは 127.0.0.1, ::1 が蚭定されおいるため、 t.isucon.dev のサブドメむンを利甚しお localhost のポヌトぞアクセスするこずで、TLS 蚌明曞怜蚌゚ラヌを回避するこずができたす。

以䞊を螏たえるず、䞊蚘のコマンド䟋を実行しおいる堎合、 https://xsuportal.t.isucon.dev:10443 でアプリケヌションぞアクセスするこずができたす。

アプリケヌションぞのログむン方法

以䞋は https://xsuportal.t.isucon.dev:10443 でアプリケヌションぞアクセスできるように蚭定した堎合の䟋です。

負荷走行が正垞に実行された堎合䞋蚘の 4 ナヌザが登録されるので、動䜜確認にご利甚ください。ログむンはトップペヌゞ仮想オヌディ゚ンス向けペヌゞから行うこずができたす。

ログむン ID (contestant_id) パスワヌド 備考
admin admin 仮想運営
isucon1 isucon1 仮想遞手
isucon2 isucon2 仮想遞手
isucon3 isucon3 仮想遞手

デヌタベヌスの初期化方法

初期状態のアプリケヌションでは、初期化凊理POST /initializeにおいおデヌタベヌスのレコヌドは削陀したすがスキヌマは初期化されたせん。スキヌマを初期状態に戻したい堎合は、以䞋の SQL ファむルをご利甚ください。

~isucon/webapp/sql/schema.sql

動䜜確認に䟿利なスクリプト集

競技サヌバヌの ~isucon/webapp/tools ディレクトリ以䞋には、アプリケヌションの動䜜確認に利甚できる䞋蚘のスクリプトが眮いおありたす。 詳しい䜿い方は ~isucon/webapp/tools/README.md を参照しおください。

File 説明
add_benchmark_job 仮想ベンチマヌクゞョブの゚ンキュヌを行えたす。
finish_benchmark_job 仮想ベンチマヌクサヌバから 1 件デキュヌし、仮想負荷走行を完了させたす。
show_notifications notifications テヌブルの䞭身をデコヌドしお衚瀺したす。

3. 負荷走行 (ベンチマヌク)

負荷走行はポヌタルサむト䞊からリク゚ストしたす。 ポヌタルサむトの 競技参加者向けペヌゞ にアクセスし、 "Job Enqueue Form" から負荷走行察象のサヌバヌを遞択、"Enqueue" をクリックで負荷走行のリク゚ストが行われ、順次開始されたす。

なお、負荷走行が埅機䞭 (PENDING) もしくは実行䞭 (RUNNING) の間は远加の Enqueue を行うこずはできたせん。

参考実装

䞋蚘の蚀語での実装が提䟛されおいたす。

  • Ruby
  • Rust
  • Go
  • Node.js

参考実装の切り替え方法

初期状態では Ruby による実装が起動しおいたす。

各蚀語実装は systemd で管理されおいたす。 䟋えば、参考実装を Ruby から Go に切り替えるには次のようにしたす。

sudo systemctl disable --now xsuportal-web-ruby.service
sudo systemctl disable --now xsuportal-api-ruby.service

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

/etc/hosts および *.t.isucon.dev ドメむンに぀いお

サヌバヌには初期状態で、割り圓おられおいる 3 台のサヌバヌの IP アドレス + ベンチマヌカヌの IP アドレスが事前に /etc/hosts ぞ登録されおいたす。これらのホスト名は自由に利甚しお構いたせん (これを利甚しなくおも構いたせん)。

䟋:

isu1.t.isucon.dev 10.160.1.101
isu2.t.isucon.dev 10.160.1.102
isu3.t.isucon.dev 10.160.1.103
isubench.t.isucon.dev 10.160.1.104

前述の通り、これ以倖の *.t.isucon.dev の FQDN に関しおは 127.0.0.1 (IPv6 は ::1) の DNS レコヌドが登録されおいたす。たた、サヌバヌに配眮されおいる TLS 蚌明曞は subject name が *.t.isucon.dev であるため、この名前であれば TLS 蚌明曞の怜蚌が通る状態で HTTPS 接続等を行うこずができるようになっおいたす。

ベンチマヌカヌにも同様の /etc/hosts ゚ントリが登録されおいたす。負荷走行の際は、ベンチマヌカヌより負荷走行の察象ずなるサヌバヌに察応する isu1 - isu3.t.isucon.dev のホスト名を利甚した HTTPS 接続が行われたす。その際、TLS 蚌明曞怜蚌が通る必芁がある旚、留意しおください。

たた、ベンチマヌカヌの IP アドレスは isubench.t.isucon.dev ずしお登録されおいたす。この /etc/hosts ゚ントリに぀いお、線集しおも構いたせんが、その堎合に負荷走行が正しく動䜜するかは運営は保蚌したせん。

時蚈に぀いお

運営が管理するベンチマヌカヌに぀いおは、Google Public NTP サヌバヌ (time1.google.com, time2.google.com, time3.google.com, time4.google.com) ず systemd-timesyncd を利甚しお時刻同期が蚭定されおいたす。

遞手ぞ提䟛されるサヌバヌに぀いおも、初期状態で同様の蚭定がされおいたす。

負荷走行に぀いお

ベンチマヌカヌによる負荷走行は以䞋のように実斜されたす。

  1. 初期化凊理の実行 POST /initialize (20 秒でタむムアりト)
  2. アプリケヌション互換性チェック (数秒数十秒)
  3. 初期化凊理の実行 POST /initialize (20 秒でタむムアりト)
  4. 負荷走行 (60 秒)
  5. 埅ち時間 (5 秒)
  6. 敎合性チェック (数秒〜数十秒)

初期化凊理は 2 回実行され、それぞれ 20 秒以内に完了する必芁がありたす。これを超えた堎合、負荷走行は倱敗になりたす。

ベンチマヌカヌは負荷走行終了ののち、5 秒埅っおから敎合性チェックを行いたす。 ゞョブキュヌによる遅延凊理等を远加した堎合は、このタむミングたでに凊理の敎合性をずっおください。

負荷走行終了埌、5 秒経っおもレスポンスが返っおきおいないリク゚ストはすべお匷制的に切断され、タむムアりトずしお数えられたす。

アプリケヌション互換性チェックもしくは敎合性チェックが通らなかった堎合、その負荷走行は倱敗ずなりたす。

キャッシュに぀いお

アプリケヌションは䞋蚘の条件においおキャッシュが認められおいたす。

  • GET /api/audience/dashboard
    • アプリケヌションは、デヌタの曎新から最倧 1 秒叀い情報を返すこずができたす。ただし、ベンチマヌカヌが怜知しない限りはそれより叀い情報を返しおも構いたせん。
  • 䞊蚘以倖の HTTP リク゚スト
    • デヌタの曎新が即時反映されおいるこずを期埅しおベンチマヌカヌは怜蚌を行いたす。ただし、ベンチマヌカヌが怜知しない限りは叀い情報を返しおも構いたせん。

Conditional GET のサポヌトに぀いお

たた、実ベンチマヌカヌは䞀般的なブラりザの挙動を暡した Conditional GET に察応しおいたす。アプリケヌションは、 Cache-Control やその他必芁なレスポンスヘッダを返すこずで、ベンチマヌカヌから Conditional GET リク゚ストを受けるこずができたす。デヌタが曎新されおいないこずが期埅されるリク゚ストにおいおは、304 Not Modified を返したり、あるいはブラりザのキャッシュ有効期限の制埡によっおリク゚ストが発生しおいなかったりしおも、ベンチマヌカヌはそれらのキャッシュを利甚しおレスポンスがあったものずみなしたす。

なお、ベンチマヌカヌ内のナヌザヌは独立しおいるため、 Cache-Control: public 等が指定されおいたずしおも、ナヌザヌ同士でキャッシュを共有するこずはありたせん。すなわち、ナヌザヌ (仮想遞手、仮想オヌディ゚ンス、仮想運営等) の間でブラりザキャッシュが䜿い回されるこずはありたせん。

タむムアりトに぀いお

実ベンチマヌカヌにおいお蚭定されおいるタむムアりト倀は䞋蚘の通りです。

  • 仮想ポヌタル
    • POST /initialize
      • 20 秒以内にレスポンスを返す必芁がありたす。これを超えた堎合、負荷走行は即時倱敗したす。
    • GET /api/contestant/dashboard, GET /api/audience/dashboard
      • 2 秒以内にレスポンスを返す必芁がありたす。これを超えた堎合、埌述のスコア蚈算に埓い枛点の察象ずなりたす。
    • 䞊蚘以倖の HTTP リク゚スト
      • 10 秒以内にレスポンスを返す必芁がありたす。これを超えた堎合、埌述のスコア蚈算に埓い枛点の察象ずなりたす。
  • 仮想ベンチマヌクサヌバ
    • タむムアりトは芏定したせん。

なお、負荷走行終了から 5 秒経った時点でレスポンスを返しおいないリク゚ストに぀いおは匷制的に切断され、䞊蚘のタむムアりト時間にかかわらずタむムアりトずしお凊理されたす。

スコア蚈算

負荷走行のスコアは以䞋の蚈算匏によっお算出されたす。

スコア = (仮想遞手スコア * 倧䌚芏暡ボヌナス) + 仮想オヌディ゚ンススコア - 枛点
  • 仮想遞手スコア
    • 仮想負荷走行が 1 回完了する (10 点)
    • 仮想遞手の質問Clarificationに察しお仮想運営から回答が行われたずき、その回答を質問者の仮想チヌムが初めお確認する 10 点
    • 仮想遞手がダッシュボヌドを衚瀺する (2 点)
  • 倧䌚芏暡ボヌナス
    • 仮想遞手の参加数によるボヌナス (埌述)
  • 仮想オヌディ゚ンススコア
    • 仮想オヌディ゚ンスがダッシュボヌドを衚瀺する (10 回ごずに 1 点)

倧䌚芏暡ボヌナス

倧䌚芏暡ボヌナスは、仮想コンテストに参加した仮想遞手の数team に所属しおいる contestant の総数によっお、以䞋の衚に埓っお算出されたす。

参加した仮想遞手の数 倧䌚芏暡ボヌナス倍率
1-59 1.0
60-119 1.2
120-179 1.4
180-239 1.6
240-299 1.8
300- 2.0

倱敗 (fail) ず枛点に぀いお

負荷走行時に発生する゚ラヌによっおは、枛点されたり、即時倱敗failしたりしたす。条件は以䞋の通りです。

  • アプリケヌション互換性チェック、もしくは敎合性チェックに倱敗した
    • 1 回以䞊で即時倱敗
  • 負荷走行䞭にアプリケヌション起因の臎呜的な問題が発生した
    • 1 回以䞊で即時倱敗
    • (䟋ずしお、仮想チヌム登録フェヌズ䞭に、1仮想チヌムも登録ができなかった堎合が該圓したす)
  • HTTP ステヌタスコヌドやレスポンス内容などに誀りがある
    • 1 回あたり枛点 50 点
    • 100 回を越えたら即時倱敗
  • リク゚ストがタむムアりトした堎合 (条件は前項に蚘茉)
    • 100 回あたり枛点 100 点
    • 即時倱敗は無し

蚈算の結果、スコアが 0 点以䞋になった堎合は倱敗ずしお扱われたす。たた、即時倱敗ずなったケヌスに぀いおも、0 点ず数えられたす。

特別賞

競技時間䞭のスコアが、最初に 20,000 を超えた 1 チヌムを特別賞ずしたす。

最終スコア

競技時間終了埌、再起動埌に運営によっお実行された負荷走行のスコアを最終スコアずしたす。

競技時間終了埌に運営によっお行う䜜業手順

  1. 党チヌムのサヌバヌを再起動し、10 分以䞊埅぀
    • 運営がサヌバヌ䞊で sudo systemctl poweroff を実斜し、サヌバヌのシャットダりンを確認した埌、サヌバヌを起動したす。
    • お願い: 再起動のテストのため、意図的に poweroff されたサヌバヌの起動䟝頌に぀いお、運営では察応する䜙力がなく、ベスト゚フォヌトでの察応になりたす。確実にシステムを再起動するため、再起動手順をこのように定矩しおいたすが、競技時間䞭に再起動をテストする堎合、sudo systemctl reboot 等で実斜しおください
  2. 党チヌムのベンチマヌクを運営より実行
    • 各チヌムの、競技時間䞭最埌の負荷走行の察象ずなったサヌバヌぞ負荷走行を行う。
    • 蚈枬は各チヌム 3 回ず぀実斜する。
  3. (2) で実斜した最埌の負荷走行が fail ずなっおいるチヌムに関しおは、再床蚈枬を実斜する
    • この際、再床 fail ずなったチヌムは倱栌ずする。
  4. 党チヌムのサヌバヌを (1) ず同手順で再起動し、ブラりザから動䜜確認を行う
    • 10 分を埅たずにチェックを開始するが、動䜜が確認できなかった堎合は 10 分経過を埅぀。
    • ここで正垞な動䜜が確認できなかったチヌムは倱栌ずする。
  5. (2) の負荷走行で蚈枬したスコアのうち、その䞭で最も高いスコアをそのチヌムの最終スコアずする
    • fail に぀いおは 0 点ず数える。

競技終了埌の泚意事項

  • 運営によるブラりザからの動䜜確認の際、運営は POST /initialize をリク゚ストしない旚留意するこず。
  • 競技時間終了埌は、遞手は䞎えられたサヌバヌにおいお䞀切の操䜜を行わないでください。競技時間終了埌の操䜜は倱栌ずなりたす。

レギュレヌション

゜フトりェア事項

遞手は䞻催者から Web アプリケヌション (問題) が䞎えられ、遞手は競技時間内にその Web アプリケヌションの高速化を行う。遞手は高速化された実装 (回答) を䜜成する時、䞻催者より䞎えられた゜フトりェア (初期実装) をベヌスに実装しおも良いし、しなくおも良い。 どのプログラミング蚀語で初期実装が提䟛されるかは䞻催者は事前にアナりンスするが、その各々の性胜が䞀臎するこずは保蚌されない。

高速化の際、䞻催者より問題ずしお䞎えられた Web アプリケヌションから、以䞋の郚分は倉曎しないこず。

  • アクセス先の URI、ただしサヌバヌ偎で生成する郚分ID などは文字皮[0-9] や [0-9a-zA-Z_] などを倉えない範囲で自由に生成しおも良い
  • レスポンス (HTML の DOM, JSON オブゞェクト等) の構造衚瀺に圱響しない範囲での空癜文字の増枛は蚱可される
  • JavaScript/CSS ファむルの内容
  • 画像および動画等のメディアファむルの内容

各サヌバにおける゜フトりェアの入れ替え、蚭定の倉曎、アプリケヌションコヌドの倉曎および入れ替えなどは䞀切犁止しない。 ベンチマヌク䞭にポヌタル・マニュアル・レギュレヌションずいった、䞻催者の指瀺以倖で利甚が認められたサヌバヌ以倖の倖郚リ゜ヌスを䜿甚する行為(他のむンスタンスに凊理を委譲するなど) は犁止する。 ただしモニタリングやテスト、開発などにおいおは、PC や倖郚のサヌバヌを利甚しおも構わない。

蚱可される事項には、䟋ずしお以䞋のような䜜業が含たれる。

  • 耇数台あるサヌバヌの圹割の倉曎
  • DB スキヌマの倉曎やむンデックスの䜜成・削陀
  • デヌタベヌスに利甚するミドルりェアの倉曎
  • キャッシュ機構の远加、ゞョブキュヌ機構の远加による遅延曞き蟌み
  • Web Push 実装の远加XSUCON アプリケヌションマニュアルを参照
  • HTTP レスポンスの圧瞮
  • 他の蚀語による再実装

ただし以䞋の事項に留意するこず。

  • コンテスト進行甚のメンテナンスコマンドが正垞に動䜜するよう互換性を保぀こず
  • サヌバ再起動埌にすべおのアプリケヌションコヌドが正垞動䜜する状態を維持するこず
  • ベンチマヌク実行時にアプリケヌションに曞き蟌たれたデヌタは再起動埌にも取埗できるこず

質問

遞手は䞻催者ぞ質問を送信するこずができる。競技時間䞭は原則ずしおポヌタルから、競技前埌は Discord 䞊のサポヌトチャットを利甚する。質問は競技内容・マニュアル・レギュレヌション等に察する疑問点・明確にしたい事項の確認や、サヌバヌ障害などのトラブル報告・サポヌト䟝頌に利甚するこずができるが、これに限らない。䞻催者は質問された内容に぀いお競技の䞀環である堎合は、回答できない旚返答するこずがある。

競技時間䞭の質問に぀いお、䞻催者からの回答は党遞手ぞ公開、あるいは個別に回答される。党遞手ぞ公開される堎合、質問内容の原文、あるいは䞻催者による内容の芁玄が公開される。未回答の質問・未公開の回答に぀いおは質問した遞手およびそのチヌムメンバヌ、䞻催者のみが確認できる。質問ぞの回答/曎新はポヌタルサむト䞊にお遞手ぞ通知される。

䞻催者は競技時間䞭の質問ぞの回答に぀いお、原則ずしお党遞手ぞ公開する。ただし、重耇する質問や、遞手およびチヌム個別の問題 (サヌバ障害など) に察する察応の堎合、この限りではない。

犁止事項

以䞋の行為を特に犁止する。

  • 競技終了時間たでに、競技の内容に関するあらゆる事項 (問題内容・蚈枬ツヌルの蚈枬方法など)を公開・共有するこず(内容を掚察できる発蚀も含む)
    • 䞍特定倚数ぞの公開はもちろん、他チヌムの遞手ず連絡を取り、問題内容等を共有する事 (結蚗行為) も犁止ずする。
    • ただし䞻催者が Twitter, Web サむトにおいお公開しおいる情報は陀く。ポヌタルサむトにおけるログむンを芁するペヌゞにおいお蚘茉されおいる内容は公開情報でない旚留意するこず。
  • 䞻催者が他チヌムぞの劚害、競技ぞの支障ずなるずみなす党おの行為
  • 䞻催者が競技に䞍必芁ずみなす競技環境からのネットワヌクアクセス
    • 競技に必芁なネットワヌク利甚ずしおは、䞻催者の指瀺 (レギュレヌション, マニュアル等含む) で蚱可・想定されおいる行為、提䟛されたむンスタンスの初期状態で利甚可胜なサヌビスや、倖郚のバヌゞョン管理システム (GitHub 等)、゜フトりェアパッケヌゞのリポゞトリ (apt, yum リポゞトリや、docker, npm, RubyGems レゞストリ, proxy.golang.org, crates.io 等) が䟋ずしお挙げられる。
    • 䞀方、提䟛されたむンスタンスからむンタヌネットたでの経路䞊にあるホスト等、遞手がその遞手ぞ提䟛されおいないホストに぀いお盎接のアクセスを詊みる行為や、倖郚ぞの䞍正アクセスを詊みる行為は、䞻催者により䞍必芁ず刀断される堎合がある。なお、䟋瀺のため、これに限らない。

本マニュアルにおいお犁止ずされた行為 (犁止事項) ぞの違反は、倱栌ずなる。

XSUCON アプリケヌションマニュアル

甚語

ISUCON 実際のコンテスト/競技 ず XSUCON ISUCON 10 本遞問題に登堎する仮想的なコンテスト/競技 内の甚語を区別するために、本マニュアルでは「実」を付けた堎合には ISUCON を、「仮想」を付けた堎合には XSUCON を指したす。

䟋:

  • ISUCON
    • 実ベンチマヌカヌ
    • 実遞手
    • ...
  • XSUCON
    • 仮想ベンチマヌカヌ
    • 仮想遞手
    • ...

XSUCON の流れ

実負荷走行の䞭で開催される XSUCON は、以䞋のような状態を持ちたす。

  1. 0 秒時点: 仮想チヌム登録フェヌズ
  2. 10 秒時点: 仮想コンテスト開始
  3. 50 秒時点: 仮想スコアフリヌズ
  4. 60 秒時点: 仮想コンテスト終了

䞊蚘のフェヌズ遷移の時間は目安です。実際には、実ベンチマヌカヌによっお POST /initialize で時間が指定されたす。

1. 仮想チヌム登録フェヌズ

仮想遞手が仮想チヌムを登録したり、メンバヌを招埅したりしたす。

実ベンチマヌカヌは、アプリケヌションがチヌム登録リク゚ストを凊理できるかぎり、仮想チヌムを登録しようずしたす。これに察しアプリケヌションは、レスポンスコヌドによっお仮想チヌムの参加䞊限数を制限する事ができたす。

䟋えば、XSUCON の参加チヌム数を 10 チヌムにしたい堎合は、11 チヌム目以降のチヌム登録リク゚スト POST /api/registration/team に察し HTTP レスポンスコヌド 403 を返しおください。

なお仮想チヌムには 1 チヌムあたり最倧 3 人たで参加する事ができたす。

2. 仮想コンテスト開始

仮想コンテスト(XSUCON)が開始したす。これ以降の仮想チヌム登録はできたせん。

仮想コンテスト開催䞭は、実ベンチマヌカヌは以䞋の 3 皮類のナヌザヌを暡したリク゚ストを行いたす。

  • 仮想遞手
    • 仮想コンテストの参加者です。仮想ベンチマヌカヌぞの゚ンキュヌや仮想ダッシュボヌド閲芧、仮想運営ぞの質問など、競技に関する動䜜を行いたす。
  • 仮想運営
    • 仮想遞手からの質問ぞの回答を行いたす。
  • 仮想オヌディ゚ンス
    • 仮想コンテストには参加したせんが、仮想遞手達のスコアを芋守り、応揎しおいたす。䞀定の条件を満たすず仮想オヌディ゚ンスは増えおいきたす埌述。

3. 仮想スコアフリヌズ

仮想コンテスト終了たで、ダッシュボヌドは「スコアフリヌズ」状態になりたす。

スコアフリヌズ状態では、各ダッシュボヌドは以䞋のような挙動になりたす。

  • 仮想遞手向けダッシュボヌド GET /api/contestant/dashboard
    • 仮想遞手は、他仮想チヌムに぀いおは、スコアフリヌズ状態になった時点たでのスコアしか芋られなくなりたす。自チヌムに぀いおは匕き続き最新のスコアが衚瀺されたす。
  • 仮想オヌディ゚ンス向けダッシュボヌド GET /api/audience/dashboard
    • 仮想オヌディ゚ンスは、党おの仮想チヌムに぀いお、スコアフリヌズ状態になった時点たでのスコアしか芋られなくなりたす。

仮想スコアフリヌズ䞭も仮想コンテストは続いおおり、仮想遞手達は匕き続き競技に関するリク゚ストを行いたす。

4. 仮想コンテスト終了

仮想コンテストが終了するず、仮想遞手達は競技に関するリク゚スト仮想負荷走行の゚ンキュヌなどができなくなりたす。

各ダッシュボヌドにおける仮想スコアフリヌズは解陀され、他仮想チヌムの最新スコアが再び芋られるようになりたす。

仮想ベンチマヌクサヌバず仮想負荷走行に぀いお

image

実競技に甚いるチュヌニング察象のアプリケヌション以䞋アプリケヌションず衚蚘は「仮想ポヌタル HTTPS」ず「仮想ベンチマヌクサヌバ gRPC」からなりたす。

仮想ベンチマヌカヌは実ベンチマヌカヌの䞭に実装されおいるため、実装を芋たり倉曎したりするこずはできたせん。

以䞋、仮想遞手が仮想負荷走行を゚ンキュヌしおから、その走行結果を仮想遞手が受け取るたでの流れを説明したす。

1. 仮想遞手: 仮想負荷走行の゚ンキュヌ

HTTP リク゚スト: POST /api/contestant/benchmark_jobs

仮想遞手が仮想ポヌタルに察し、仮想負荷走行benchmark_jobの゚ンキュヌをリク゚ストしたす。゚ンキュヌしたずき、ゞョブのステヌタスは PENDING ずしお蚭定されたす。

仮想遞手は、゚ンキュヌができる状況にあるずきは即時に゚ンキュヌを詊みたす。以䞋のような状況にある堎合は仮想遞手ぱンキュヌをせず、状況が倉化するのを埅ちたす。

  • ただ FINISHED になっおいない所属仮想チヌムのゞョブPENDING, SENT, RUNNINGがすでにあり、ただ仮想負荷走行終了の通知を受け取っおいないずき
  • 仮想遞手本人あるいは所属仮想チヌムのメンバヌが仮想運営ぞの質問Clarificationを投皿したあず、ただ仮想運営からの回答を確認しおいないずき

2. 仮想ベンチマヌカヌ: ベンチマヌクキュヌのポヌリング

gRPC サヌビス: xsuportal.proto.services.bench.BenchmarkQueue, プロシヌゞャ: ReceiveBenchmarkJob

仮想ベンチマヌカヌは仮想ベンチマヌクサヌバに察し、垞にキュヌをポヌリングしおいたす。キュヌにゞョブがあった堎合はそのゞョブがデキュヌされたす。デキュヌされたゞョブは、ステヌタスが PENDING から SENT に倉曎されたす。

仮想ベンチマヌカヌは仮想チヌムず同じ数だけ甚意されおおり、最倧で党おの仮想チヌムの仮想負荷走行を同時に凊理できる胜力を有したす。

仮想ベンチマヌカヌのポヌリング挙動に぀いお

各仮想ベンチマヌカヌは、ReceiveBenchmarkJob の実行でゞョブが返华されなかった堎合キュヌが空、埅ち時間を挟たず、即時にリトラむをしたす。たた、仮想負荷走行埌、レポヌトを登録した埌も、埅ち時間を挟たず即時に ReceiveBenchmarkJob を実行したす。

3. 仮想ベンチマヌカヌ: レポヌトの登録

gRPC サヌビス: xsuportal.proto.services.bench.BenchmarkReport, プロシヌゞャ: ReportBenchmarkResult

仮想ベンチマヌカヌは仮想負荷走行に察し、以䞋の通りレポヌトを送りたす。

  • 仮想負荷走行が開始したずき
    • ゞョブのステヌタスは SENT から RUNNING に倉曎されたす。
  • 仮想負荷走行が完了したずき
    • ゞョブのステヌタスは RUNNING から FINISHED に倉曎されたす。

仮想負荷走行は開始したあず瞬時に完了したす。

4. 仮想遞手: 通知のポヌリング

仮想遞手のブラりザは䞀定時間ごずに通知リストGET /api/contestant/notificationsをポヌリングしおいたす。仮想ポヌタルは、仮想遞手の仮想チヌムが実行した仮想負荷走行が完了しおいた堎合、ベンチマヌク完了通知xsuportal.proto.resources.Notification.BenchmarkJobMessageを通知リストに加えたす。

仮想遞手はこの通知を受け取ったずき、ゞョブ詳现GET /api/contestant/benchmark_jobs/:idにアクセスし、仮想負荷走行の結果を確認したす。実ベンチマヌカヌはこの確認が完了したずき「仮想負荷走行が 1 回成功した」ずしおカりントしたす。

仮想オヌディ゚ンスの増枛に぀いお

仮想オヌディ゚ンスは、XSUCON を盛り䞊げるために欠かせない存圚です。仮想オヌディ゚ンスは、仮想オヌディ゚ンス甚ダッシュボヌドGET /api/audience/dashboardを䞀定間隔で閲芧し、仮想コンテストの動向を芋守っおいたす。

仮想オヌディ゚ンスは、仮想コンテスト開始盎埌は 0 人の状態から始たりたす。いずれかの仮想チヌムが仮想負荷走行を 1 回成功させるたびに、仮想オヌディ゚ンスは 1 人増えたす。たた、仮想オヌディ゚ンスの行動䞭に゚ラヌがあった時、1 回の゚ラヌに぀き仮想オヌディ゚ンスは 1 人枛りたす。

仮想ポヌタルの質問機胜に぀いお

仮想遞手は、䞀定の頻床で質問を投皿POST /api/contestant/clarificationsしたす。仮想運営は質問を䞀定間隔で確認しおおり (GET /api/admin/clarifications)、未回答の質問を怜知した堎合即時に回答を曞き蟌みたすPUT /api/admin/clarifications。

仮想遞手は、本人あるいはチヌムメンバヌが質問を投皿したら、仮想運営による回答を確認できるたで、以䞋の行動を停止したす。

  • 仮想負荷走行の゚ンキュヌ
  • 新たな質問の投皿

仮想遞手のブラりザは、䞀定時間ごずに通知リストGET /api/contestant/notificationsをポヌリングしおおり、質問に察する回答が来たかどうかはこの通知の䞭身を芋お刀断したす。仮想遞手は、通知リストに回答通知xsuportal.proto.resources.Notification.ClarificationMessageが含たれおいるこずを確認したら、回答の本文を質問リストGET /api/contestant/clarificationsから閲芧したす。仮想遞手は質問リストを芋お回答されおいるこずが確認できたら、停止しおいた䞊蚘の行動を再開したす。

質問に察する個別回答ず党䜓回答に぀いお

仮想遞手からの質問に察する仮想運営からの回答には、「個別回答」ず「党䜓回答」がありたす。仮想運営は、質問に察しどちらの皮別の回答を行うかは、䞀定の確率で遞択したす。

個別回答では、質問を投皿した仮想チヌムのみ、質問および回答を閲芧できたす。

党䜓回答では、質問を投皿した仮想チヌム以倖の仮想遞手も含め、党おの仮想遞手が質問ずその回答を閲芧できたす。党䜓回答が行われた堎合、党仮想遞手の通知リストに回答通知が加えられたす。回答の通知を受け取った仮想遞手は、その回答を即時に閲芧するため、質問リストぞアクセスしたす。

仮想ポヌタルの通知機胜に぀いお

image

仮想ポヌタルの通知機胜は、ブラりザの Notifications API および Push API を甚いお実装されおいたす。仮想ポヌタルの仮想遞手向けダッシュボヌド画面/contestant/dashboard右䞊にある「通知を有効にする」ボタン䞊図を抌すず、ブラりザを通じお通知を受け取るこずができたす。ブラりザで動䜜確認する際には、お䜿いのブラりザが Notifications API および Push API に察応しおいるかどうかを確認しおくださいSafari は察応しおいたせん。実運営は、Chrome ず Firefox を甚いお動䜜確認を行っおいたす。

アプリケヌションの参考実装仮想ポヌタルのクラむアントサむドにおいお、新着通知の取埗は前述の通り GET /api/contestant/notifications ぞのポヌリングで実装されおいたす。

参考実装のサヌバサむドでは未実装ですが、クラむアントサむドはこのポヌリング方匏に加え、 Web Push 方匏が実装されおいたす。

以䞋の 2 ぀の API は、参考実装ではステヌタスコヌド 503 を返すようになっおいたす。これらを正しく実装し、200 を返すようにするこずで、Web Push による通知を賌読/賌読解陀できるようになりたす。

  • Web Push 通知の賌読: POST /api/contestant/push_subscriptions
  • Web Push 通知の賌読解陀: DELETE /api/contestant/push_subscriptions

実ベンチマヌカヌ内の仮想遞手が䜿うブラりザも同様に、Web Push が実装されおいるため、䞊蚘 API が実装されおいれば Web Push による通知を賌読するようになりたす。

アプリケヌションは、Web Push で党おの通知を送るように倉曎した堎合は、通知リストGET /api/contestant/notificationsのリク゚ストに察しお空の通知リストを返す事ができたす。空の通知リストを返す堎合も、正垞時の HTTP ステヌタスコヌドは 200 であるこずが期埅されたす。

たた、アプリケヌションは 1 人の仮想遞手に察しお、Web Push 方匏の通知ずポヌリング方匏の通知を混圚させおも構いたせん。たた、通知に関しおは既に受信したものを重耇しお受信した堎合でも、繰り返し凊理されたせん。

実ベンチマヌカヌが実装する Web Push service に぀いお

ブラりザの Push API の挙動を再珟するため、実ベンチマヌカヌには RFC8030 push service が実装されおいたす。

実ベンチマヌカヌが実装する push service は RFC8030 Section 5. に蚘茉されおいる push resource をサポヌトしおいたす。user agent に぀いおは、実ベンチマヌカヌに内包しおいるため、その他の゚ンドポむントに぀いおは実装されおいたせん。

加えお、䞀般的なブラりザで Push API を利甚する際必芁になる RFC8291 (メッセヌゞの暗号化), RFC8292 (VAPID を利甚したサヌバ認蚌) をサポヌトしおいたす。

原則

実ベンチマヌカヌはアプリケヌションを実際のブラりザで利甚した堎合の挙動を暡倣しおいたす。すなわち、Push API を利甚しお埗られる push subscription 情報を、必芁に応じおアプリケヌションぞ送信したす。ただし、RFC8292 における public key (VAPID 公開鍵) がアプリケヌションより、実ベンチマヌカぞ送信されおいる必芁がありたす (詳现は参考実装の挙動を確認しおください)。

push subscription 情報に぀いおは、push resource の URL に加え、W3C Push API: getKey() メ゜ッド における p256dh, auth の倀が提䟛されたす。提䟛方法も参考実装の挙動に準じたす。

そしお、push resource ぞ送信した push message は即座に user agent (仮想遞手) ぞ送信されたす。仮想遞手は通知を順次凊理するため、同時に耇数の通知に察応する動䜜を取るこずはありたせん。

たた、各蚀語の参考実装においお既に存圚するラむブラリを利甚しおの動䜜を怜蚌しおいたす (サンプルコヌドに぀いおは埌述)。

Caveats

重耇する内容もありたすが、実ベンチマヌカヌが送信する push resource の゚ンドポむントに぀いお、RFC に定矩されおいない動䜜、あるいは RFC を意図的に違反しおいる点は䞋蚘の通りです。

これらは ISUCON10 本遞競技の課題の範疇においおは、Web Push ラむブラリなどを利甚しおいる限り問題にはならないず考えおいたす。

  • RFC8291 (暗号化) の利甚が必須です。
    • W3C Push API の Section 4. 等 をはじめ、Web ブラりザの Web Push における RFC8030 の利甚では、push message は暗号化される事が前提ずなっおいるためです。
    • したがっお、push resource ぞ送信するリク゚ストに぀いおは、 RFC8291 に埓い暗号化しお送信する必芁がありたす。暗号化されおいないリク゚ストに぀いおは、push resource は HTTP 400 ゚ラヌを返したす。
    • 実ベンチマヌカヌは push subscription をアプリケヌションぞ提䟛するずき、かならず RFC8291 で定矩された鍵亀換のための EC 公開鍵、共有鍵である、 Push API で取埗できる p256dh, auth の倀が送信されたす。
    • push resource ぞ送信した push message の埩号の倱敗は実負荷走行の゚ラヌずしお蚘録されたす。
  • RFC8292 (VAPID) の利甚が必須です。
    • 実ベンチマヌカヌは Section 4. における restricted push message subscription のみを生成したす。
    • したがっお、アプリケヌションからの push resource ぞのリク゚ストは HTTP Authorization ヘッダの vapid スキヌムを利甚しお認蚌される必芁がありたす。
    • Section 2., Section 4.2. に埓い、aud, exp クレヌムのみを怜蚌したす。
    • VAPID の ECDSA 公開鍵がアプリケヌションより実ベンチマヌカヌぞ送信されおいない堎合、実ベンチマヌカヌは push resource を生成し、アプリケヌションぞ送信するこずはありたせん。
  • RFC8030 Section 5.1. に定矩されおいる push message receipt に぀いおは、実装されおいたせん (RFC 違反)。
    • push resource ぞのリク゚ストにおいお Prefer: respond-async ヘッダが䞎えられたずきの Link レスポンスヘッダに぀いおは実装されおいたすが、 Link ヘッダが瀺す URL は 404 Not Found を返答したす。
    • たた、Prefer: respond-async ヘッダを䞎えたずきの動䜜に぀いおは保蚌したせん。
  • RFC8030 Section 5.2. TTL ヘッダ, Section 5.3. Urgency ヘッダ, Section 5.4. Topic ヘッダに関しおは、受け付けたすが意味を持ちたせん。
    • user agent (仮想遞手) ぞは即座に送信され、user agent は即座に push message に察応した動䜜を取りたす。
    • user agent は通知を順次凊理したす。同時に耇数の通知に察する行動は取りたせん。
  • 䞀郚ラむブラリにおける RFC8291 Section 3.1. 実装ミスを救枈するため、1 床目の埩号゚ラヌに぀いお、誀った ECDH shared secret の導出手順によりリトラむを詊みるようになっおいたす。
    • 具䜓的には、 Go 実装は https://github.com/SherClockHolmes/webpush-go の䞍具合を救枈しおいたす。
    • RFC8291 Section 3.1. の ECDH 凊理に぀いお、SEC1 Section 6.1.3., 2.3.5., 2.3.7. に埓っお実装するず shared secret (output) が垞に 32 バむトになるずころ、32 バむト未満になるケヌスが存圚するためです。
    • リトラむでも埩号に倱敗した堎合は「䞍正な Web Push メッセヌゞ」ずしお゚ラヌになりたす。リトラむで発生した゚ラヌに぀いおは砎棄され、゚ラヌメッセヌゞには 1 回目 (リトラむ前) の゚ラヌが蚘録されたす。
  • 存圚しない push resource ぞのリク゚ストは実負荷走行の゚ラヌずしお蚘録されたす。
  • 存圚したが expire した push resource ぞのリク゚ストは、゚ラヌずなりたせんが、user agent (仮想遞手) ぞは送信されたせん。

Web Push サンプルコヌドに぀いお

仮想ポヌタルのクラむアントサむド (Web ブラりザで衚瀺されるフロンド゚ンド実装) に察しお Web Push 通知でテストメッセヌゞを送るこずができる各蚀語のコヌドが甚意されおいたす。

これらのサンプルコヌドは、 xsuportal.proto.resources.Notification.TestMessage をメッセヌゞずしお持぀通知 (xsuportal.proto.resources.Notification) を生成し、指定された contestant の持぀ push_subscriptions に察し Web Push で送りたす。

Web Push の賌読ずサンプルコヌドの実行方法

  1. ~isucon/webapp 䞊で ./generate_vapid_key.sh を実行し、VAPID 甚の ECDSA 鍵 webapp/vapid_private.pem を生成する
    • 参考実装では自動で ~isucon/webapp/vapid_private.pem をロヌドするようになっおいたす。
    • 耇数のサヌバヌを利甚する堎合、同じ鍵ファむルを共有するようにする必芁がありたす。
  2. 仮想ポヌタルにブラりザでアクセスしお通知を受け取りたい仮想遞手ずしおログむンし、/contestant から通知を賌読する
  3. send_web_push (埌述) を実行し、通知を送信する

正垞に Web Push が送信できた堎合、䞋図のような通知を即座に受け取るこずができたす。

(初期状態のサヌバヌサむド実装を利甚しおいる堎合、send_web_push で生成される通知は、ポヌリング方匏からも送信されたす)

image

以䞋に各蚀語の実装および、その実行方法を蚘茉したす。いずれもサヌバヌ䞊か぀、初期状態での実行を想定しおいたす。

Ruby 実装: ~isucon/webapp/ruby/send_web_push.rb

set -o allexport; source ~isucon/env; set +o allexport

cd ~isucon/webapp/ruby
bundle exec send_web_push.rb -c contestant_id -i vapid_private_key_path
  • -c contestant_id 通知を送信する contestant の ID必須
  • -i vapid_private_key_path ECDSA 秘密鍵 PEM ファむル必須
    • ~isucon/webapp/generate_vapid_key.sh で生成した鍵を利甚できたす。

Rust 実装: ~isucon/webapp/rust/src/bin/send_web_push.rs

set -o allexport; source ~isucon/env; set +o allexport

cd ~isucon/webapp/rust
cargo run --bin send_web_push -- -c contestant_id -i vapid_private_key_path
  • -c contestant_id 通知を送信する contestant の ID必須
  • -i vapid_private_key_path ECDSA 秘密鍵 PEM ファむル必須
    • ~isucon/webapp/generate_vapid_key.sh で生成した鍵を利甚できたす。

Go 実装: ~isucon/webapp/golang/cmd/send_web_push/main.go

set -o allexport; source ~isucon/env; set +o allexport

cd ~isucon/webapp/golang
make
./bin/send_web_push -c contestant_id -i vapid_private_key_path
  • -c contestant_id 通知を送信する contestant の ID必須
  • -i vapid_private_key_path ECDSA 秘密鍵 PEM ファむル必須
    • ~isucon/webapp/generate_vapid_key.sh で生成した鍵を利甚できたす。

Node.js 実装: ~isucon/webapp/nodejs/src/sendWebpush.ts

set -o allexport; source ~isucon/env; set +o allexport

cd ~isucon/webapp/nodejs
npm run send-webpush -- ${contestant_id} ${vapid_private_key_path}
  • ${contestant_id} 通知を送信する contestant の ID必須
  • ${vapid_private_key_path} ECDSA 秘密鍵 PEM ファむル必須
    • ~isucon/webapp/generate_vapid_key.sh で生成した鍵を利甚できたす。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment