Go
isucon

ISUCON7決勝のポータルアプリとベンチマーカーをビルドして動かす

ベンチ単体で動かせばええやんという話もあるだろうが、ポータルからやるほうが盛り上がりがあるのでポータルをセットアップした。
READMEがあっさりしていたので動かすまでやったことをメモしておく。あっさりしているとはいえ公開されているだけでありがたい。そして、(セットアップがちゃんとしていれば)ちゃんと動く。(改めて、運営お疲れ様でした)

環境セットアップ

ルートのREADME.mdにあるとおりUbuntu 16.04 LTSを使う。そして、依存をシュッと入れる。

sudo apt update
sudo apt install -y mysql-server nginx
sudo apt install -y git curl libreadline-dev pkg-config autoconf automake build-essential libmysqlclient-dev \
    libssl-dev python3 python3-dev python3-venv openjdk-8-jdk-headless libxml2-dev libcurl4-openssl-dev \
    libxslt1-dev re2c bison libbz2-dev libreadline-dev libssl-dev gettext libgettextpo-dev libicu-dev \
    libmhash-dev libmcrypt-dev libgd-dev libtidy-dev libgmp-dev

ほか、makeを使うためにbuild-essentialが必要なので入れる。1

sudo apt install -y build-essential

MySQLのrootのパスワードは空でよさげなので一旦そうした。
あとポータルを動かすためにはタイムゾーン情報が必要なので入れておく。(これはREADMEにないが、あるべきなのだろうか…?)

mysql_tzinfo_to_sql /usr/share/zoneinfo | sudo mysql -uroot mysql

この他にgo周りが必要なので入れる。xbuildでgo 1.9.2を入れることになっているが、ビルドだるいしポータルとベンチマーカだけ動けばいいのでバイナリをそのまんま入れてしまおう。(手抜き)
ここから入手して入れる: https://golang.org/dl/

wget https://dl.google.com/go/go1.9.2.linux-amd64.tar.gz
tar zxvf go1.9.2.linux-amd64.tar.gz
sudo mv go1.9.2.linux-amd64 /usr/local/go

PATH/GOPATHを設定すれば下準備は完了。

sudo bash -c 'echo "export PATH=\$PATH:/usr/local/go/bin" > /etc/profile.d/golang.sh'
echo <<'EOD' >> ~/.profile
export GOPATH="$HOME/go"
export PATH="$GOPATH/bin:$PATH"
EOD

ベンチマーカーのビルド

depが必要なので入れる。

go get -u github.com/golang/dep/cmd/dep

ビルドする。素直にmakeすればいい。
update-staticfile.go は必要なのかよくわかんないけどとりあえずやっとく。

cd ~/cco/bench
make ensure
go run update-staticfile.go
make

ポータルのビルド

こっちはあREADMEがっさりしててちょっと苦労した。
gb、go-bindataを使っているとのことなので入れる。

go get -u github.com/constabulary/gb/...
go get -u github.com/jteeuwen/go-bindata/...

依存モジュールをインストールしてビルドする。
gbのプラグインとしてgb-vendorというやつがありこれを使っているようなのでそれで入れる。1

cd ~/cco/portal
gb vendor restore
make build

ポータルを起動する

ポータルを起動するとテンションが上がるのでポータルを動かす。

env.shを用意する

いったん空でOK。

touch ~/env.sh

portalディレクトリを移動する

ビルド済のportalの中身を /home/ubuntu/portal に移動する。

mv ~/cco/portal ~/portal

symlinkでも動いたかもしれない。

DBをセットアップする

これは迷うことはないのでREADMEの通り。

cat <<'EOD' | sudo mysql -uroot
create user ubuntu@localhost identified by 'ubuntu';
grant all on *.* to ubuntu@localhost;
EOD
portal/db/init.sh

チームのインポートは本戦に出場できなかったチームはちょっといじくる必要がある。
以下のファイルをいい感じにしよう。どうすればいいかはきっと見れば雰囲気で分かる。

  • portal/data/isu7f-teams.tsv
  • portal/data/isu7f-servers.tsv

あとはインポートする。(これは実はまだ動かしていない)

portal/bin/import -dsn-base "ubuntu:ubuntu@(localhost)" -target teams < portal/data/isu7f-teams.tsv
portal/bin/import -dsn-base "ubuntu:ubuntu@(localhost)" -target servers < portal/data/isu7f-servers.tsv

ポータル用にnginxを設定する

files/portal.nginx.conf が本体だが、SSLの設定が入っている。
頑張ってSSLの設定をしてもよしなのだが、練習用だしめんどいのでHTTPで受けられるようにしてしまう。
これで上書きする。

# Apply fix for very long server names
server_names_hash_bucket_size 128;

gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
log_format vhost '$host $remote_addr - $remote_user [$time_local] '
                 '"$request" $status $body_bytes_sent '
                 '"$http_referer" "$http_user_agent"';
# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";

# portal.example.com
upstream portal.example.com {
  server 127.0.0.1:3333;
}
server {
  server_name _;
  listen 80;
  access_log /var/log/nginx/access.log vhost;
  client_max_body_size 100M;
  location / {
          proxy_pass http://portal.example.com;
  }
}

ポータルを起動する

sudo cp files/portal.day* /etc/systemd/system/
sudo systemctl enable portal.day1
sudo systemctl start portal.day1
sudo journalctl -xu portal.day1 # 確認

IPを指定すればnginx経由でアクセスできるはず。
このままだと競技が始まってないのでアクセスできないよって感じのことをいわれる。

競技を開始状態に変更する

管理者権限でこじあければいい。

/login が実はアクセス可能なのでアクセスして管理用の9999のチームIDでログインする。これはREADMEに載ってるのでみるべし。
その後、 /XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/admin にアクセスするとなにやらそれっぽい画面がでるので競技中にステータスを変更する。

再びトップページに移動するとそれっぽい画面が出てテンションが上がる。

ベンチマーカーを起動する

ベンチマーカーを起動して動かす。
単体で動くほか、worker modeというやつがあり、それで起動することでportalと連携する仕組みっぽい。

env.shをいじる

さきほど isu7f-teams.tsvisu7f-servers.tsv ででっちあげたgroup nameを環境変数にいれてやる。

ISU7_GROUP_NAME=oniyanma

benchディレクトリを移動する

ビルド済のbenchの中身を /home/ubuntu/bench に移動する。

mv ~/cco/bench ~/bench

symlinkでも動いたかもしれないが、疲れてきたのでmvする。

bench.prod.service を書き換える

https://portal.isu.k0y.org になっているのをTLSを外しつつ先程ポータルにアクセスしたときのそれに変える。

ベンチマーカーを起動する

あとはよいしょしたら動く。

sudo cp files/bench.prod.service /etc/systemd/system/
sudo systemctl enable bench.prod
sudo systemctl start bench.prod
sudo journalctl -xu bench.prod # 確認

これでポータルでenqueueしたらベンチマーカーが動いてくれるようになってさらにテンションが上がる。(はず)

実際に動かしたらまた追記する。