Y

ISUCON12予選の復習をしました 10

この記事は何か?

ISUCON12予選の復習記録です。

第10回はISUCON12 予選の解説 (Node.jsでSQLiteのまま10万点行く方法)の「10 AddTenant APISQLite DBを作るのをやめる」を試します。

目次

  1. 「10 AddTenant APISQLite DBを作るのをやめる」を試す

1.「10 AddTenant APISQLite DBを作るのをやめる」を試す

3台構成準備のその2です。

1台構成であればAdminのAddTenant APISQLiteのDBを追加する、でよいのですが、上の方にも書いた通り3台構成にするとAdminのAddTenantをするサーバとテナントの処理サーバが一致していないとこの処理がうまくいきません。テナントのサブドメインはベンチマーカーから指定されるランダム文字列なので先頭文字を使って既存テナントと新規テナントを振り分けるみたいなこともできないためnginxが /api/admin/tenants/add を受け取ったときに適切なサーバに振り分けるのはなかなか難しい…ということで新規DB作成処理のタイミングを変えます。

まず、AddTenant APIでcreateTenantDB関数を呼び出すのをやめます。そして、テナントAPIに出てくるconnectToTenantDB関数の中でテナントのDBファイルが存在するかチェックして、なければcreateTenantDBを呼ぶという処理に変えると、nginxでテナントの振り分けさえ出来ていれば全てのSQLiteの処理は振り分けたサーバで行われるようになるので、3台構成が可能になります。

上記のとおりです。

私のISUCON歴では、3台全てを利用できることがなかったです。全台を利用するのは必須だと思うのでやっていきます。

isucon@ip-192-168-0-12:~/webapp/go$ git diff
--- a/go/isuports.go
+++ b/go/isuports.go
@@ -85,6 +85,17 @@ func tenantDBPath(id int64) string {
 // テナントDBに接続する
 func connectToTenantDB(id int64) (*sqlx.DB, error) {
        p := tenantDBPath(id)
+
+       // テナントDBが存在しない場合は新規に作成する
+       if _, err := os.Stat(p); err == nil {
+       } else if errors.Is(err, os.ErrNotExist) {
+               if err := createTenantDB(id); err != nil {
+                       return nil, fmt.Errorf("error createTenantDB: id=%d %w", id, err)
+               }
+       } else {
+               return nil, fmt.Errorf("error file exist check")
+       }
+
        db, err := sqlx.Open(sqliteDriverName, fmt.Sprintf("file:%s?mode=rw", p))
        if err != nil {
                return nil, fmt.Errorf("failed to open tenant DB: %w", err)
@@ -530,9 +541,9 @@ func tenantsAddHandler(c echo.Context) error {
        // NOTE: 先にadminDBに書き込まれることでこのAPIの処理中に
        //       /api/admin/tenants/billingにアクセスされるとエラーになりそう
        //       ロックなどで対処したほうが良さそう
-       if err := createTenantDB(id); err != nil {
-               return fmt.Errorf("error createTenantDB: id=%d name=%s %w", id, name, err)
-       }
+       //if err := createTenantDB(id); err != nil {
+        //     return fmt.Errorf("error createTenantDB: id=%d name=%s %w", id, name, err)
+       //}

        res := TenantsAddHandlerResult{
                Tenant: TenantWithBilling{
  • 変更前のスコア
22:42:51.168658 SCORE: 15122 (+16087 -965(6%))
  • 変更後のスコア
10:29:17.392487 SCORE: 9872 (+11893 -2021(17%))

感想

エラーが多くなりました。何かが足りないと思いますが、とりあえず気にせず前に進みます。

参考

1 ISUCON12 予選の解説 (Node.jsでSQLiteのまま10万点行く方法)

2 ISUCON12 予選当日マニュアル