4世代のID調整用初期seed検索botをAPI Gateway + AWS Lambda + S3に移管した
Discordの乱数調整サーバーにbotを置いていた。
4世代のID調整用初期seedはMTを使っており逆算が不可能なため、任意のIDが出るseedを求めたい場合は総当たりしたものをファイルに保存しておいて検索するしかない。
botはラズパイで動かしていた。
が、電源コードが邪魔だった(常に1枠占有されている上に抜けたり引っかけたりしないように気を付ける必要があり、正直とても不便だった)。
年末に思い立ってAWSに移管した。
7世代のTSV検索ツールの中身だけ変えたやつ。
「Reactなんか要らん、jQueryだけで十分」みたいな言説を受けて、jQueryすら使わずにやってみている。
JSのコードはTSからコンパイルしている。
getElementByIdでいちいちnullチェックしたくなかったので、HTMLを読んでid属性からgetElementByIdのオーバーロードを吐くスクリプトを作って使っている。
感想としては、「簡単なオモチャなら作れなくもないけど、『使いやすいUI』よりも『HTML+バニラJSで実装しやすいUI』に流れる力が強く働いてしまうからもうやらない」。
「より良いものが簡単に作れる」ことの素晴らしさを思い知った。
Github ActionsでGithub Pagesへのデプロイができるやつ、めちゃ便利。
pushしたらページが生えてる。
乱数ツール系は永続化不要なので相性がとても良い。
C# .NET 7 のなんちゃらってやつで、ネイティブコードを吐くやつを使った。つい最近Lambdaが対応したらしい。
コールドスタートが速くなるんだって。
そんなに頻繁に叩かれまくるAPIではないので、ほぼ常にコールドスタートになるはず。つまりとても嬉しい。
C#を選んだのはseed検索部分のコードを流用できるからのが主な理由。単純に好きだし。
JS/TSだと32bit整数を扱うのがとてもつらい。
APIの入出力部分は一番素直に扱えそうなんだけどね…。
Pythonは…遅いじゃん…。
Goは速そうだったけど入門からになって年末年始で終わりそうになかったからやめた。
あとGopherが生理的に受け付けない。
Lambdaでプログラムがやってることとその前処理
seed検索に必要なデータファイルを表IDごとに分けてバイナリファイルにし、S3にアップロード。
32bit整数をseedとしたときに生成される表IDを総当たりして、裏IDでソートしたものを表IDごとにseedだけ保存している。
検索時は裏IDで二分探索する。
256KB前後のファイルが65536個できる。
seedから裏ID生成は検索時にも行うが、ここのプチ工夫として、IDを確認するだけならMTの状態を持つために配列を確保する必要がない。配列確保を省くだけでそこそこ速くなる。
Lambdaは指定されたIDに応じてS3からファイルを取ってきて検索。
コールドスタートで+1000msくらい掛かっているが、検索処理だけなら1回あたり100 ~ 200msくらい。
ハマったポイント一覧
APIGatewayとの繋ぎ込み部分でRequest / ResponseをJSONに変換するんだけど、適切なスキーマに変換する必要があり、半日くらい上手く行かねーって言ってた。
Amazon.Lambda.APIGatewayEventsパッケージを追加でインストールし、FunctionHandlerのinput引数の型をAPIGatewayProxyRequest、戻り値の型をAPIGatewayProxyResponseにした上で、LambdaFunctionJsonSerializerContextにJsonSerializer属性経由でこれらの型を教えてやる必要があった。
これは最新のSystem.Text.Jsonの機能を追っていなかったので知らなかったが、SourceGeneratorを使ってリフレクションを回避するためのやつらしい。
...ResponseのStatusCodeがデフォルトで0のままなのに気付かず1敗。
Internal Server Errorが無限に出る
APIGatewayのCloudWatchを有効にしておきましょう。
なぜか依存関係で怒られる
AWSSCK.S3などはrd.xmlに追記する必要がある。
その上で、何故かVisual Studioが上手く認識してくれなくてエラーを吐いていた。再起動したら何か直った。
AWSにデプロイするたびにVisual StudioがAWS系のパッケージを認識しなくなる
解決方法わからんかった。
IDEの助けを借りずにコーディングしてたりした。
AWS拡張と何が相性悪いのかの切り分けもしていないが、軽く調べても出てこなかったので、たぶん新しめの構成とかみ合ってないんだと思う。
S3周りで気を付けること
コンソールから65536個のファイルをアップロードするのは無理。
段々重くなるし途中でセッション切れる。
AWS CLIをインストールしてaws s3コマンドからアップロードする必要がある。
アップロード時の転送量には課金されないが、PUTリクエスト回数には課金される。
1ファイルごとに1回PUTリクエストを行っているため、更新系APIリクエストの無料枠(2000回まで無料)は余裕で越える。
「フォルダ構成気に入らないからもう1段掘ろう」みたいなのもたぶん課金される。事前に入念な設計を行うこと。
S3のストレージクラスの選定も慎重にすること!!
ReadOnlyな上に頻繁にアクセスされるわけでもないので、保存コスト的には標準の低頻度アクセス(Standard-IA)クラスにしておくのが丸い。
16GBぶんだけを保存するとして、標準だと1か月あたり0.40USD、IAだと0.22USD。1か月あたり0.18USD安い。
ただしPUTアクセスの料金が標準クラスに比べて割高。
標準だとアップロード時のPUTリクエストに0.31USD、低頻度アクセスでは0.66USDかかる。
損益分岐点は2ヶ月目。
普通にAWS CLIからアップロードすると標準クラスに配置される
ストレージクラスの変更はPUTリクエストで行うことになるので、0.31USD払ったうえに追加で0.66USDを払うハメになる(1敗)。
S3ストレージ料金の1年無料枠は標準クラスにのみ適用される
アカウント開設後1年間は5GBまでのストレージ料金が無料になるが、これはIAクラスには適用されない。
それでもIAクラスを使っていたほうが安くなるが。
とは言っても年間ワンコインでお釣りがくる程度の値段なので、富豪的な気持ちで運用している。
悪い人にDDoS食らったり、いきなりドル円が10000円/USDとかならない限り破産はしない…はず
AWS費用を記録していく
table:2022_12
Month USD JPY 累計 API Call
2022_12 0.02 3円 3円
2023_01 1.29 170円 170円 177回
2023_02 0.23 32円 202円 54回
2023_03 0.24 32円 234円 73回
2023_04 0.24 32円 266円 32回
2023_05 0.24 33円 299円 106回 レート上がりやがった
2023_06 0.24 34円 333円 131回
2023_07 0.24 34円 367円 195回
2023_08 0.24 35円 402円 203回
2023_09 0.24 36円 438円 54回
2023_10 0.24 36円 474円 99回
2023_11 0.24 36円 510円 188回 ワンコインに収まらなかった…おのれ円安
2023_12 0.24 35円 545円 420回 ここで無料枠が終了、でもS3代だけなのでそんなに影響はないはず…。
2024_01 0.24 35円 35円 440回 無料枠終わったけど影響なかったわ
2024_02 0.24 36円 71円 293回
2024_03 0.24 37円 108円 158回