【実験】App Engine(Golang)からCloud SQLに接続する際の同時接続数制約

# 追記@2019/05/23
アドバイスもらったので追記。
https://qiita.com/sky0621/items/8792b54ebf6bd21bcf72#追記

# お題
表題の通り。

[Cloud SQL](https://cloud.google.com/sql/?hl=ja)はマシンタイプ別に最大同時接続数が変わる。
例えば、`db-g1-small`インスタンスなら「`1000`」まで。（ちなみに、今回の実験では、このインスタンスを使用）

| マシンタイプ | 最大同時接続数 |
|:--|:--|
| db-f1-micro | 250 |
| db-g1-small | 1,000 |
| その他のすべてのマシンタイプ | 4,000 |

【参考】
https://cloud.google.com/sql/docs/quotas?hl=ja#fixed-limits

そして、もう１点。
[App EngineからCloud SQLへの接続時の制限に関して説明するページ](https://cloud.google.com/appengine/docs/standard/go/cloud-sql/pricing-access-limits?hl=ja#app_engine)に以下の記載がある。
「`スタンダード環境で動作する各 App Engine インスタンスは、Cloud SQL インスタンスに対する同時接続数が最大 100 個に制限されます。Java 7、Go 1.6、PHP 5.5 のアプリケーションでは、同時接続数が最大 60 個に制限されます。`」
念の為、英語サイトの方も確認。
https://cloud.google.com/appengine/docs/standard/go/cloud-sql/pricing-access-limits?hl=en#app_engine
「`Each App Engine instance running in the standard environment cannot have more than 100 concurrent connections to a Cloud SQL instance. For Java 7, Go 1.6, or PHP 5.5 apps the limit is 60 concurrent connections.`」

それぞれのApp EngineインスタンスからCloud SQLインスタンスに接続できる数は「`100`」までという制限がある。
「`100`」を超えたらどうなるのか？　そもそも超えることはできるのか？　これらについて実験してみる。
　
　
ちなみに、実験結果のまとめは下記。
https://qiita.com/sky0621/items/8792b54ebf6bd21bcf72#まとめ

# 前提
- [GCP](https://cloud.google.com/?hl=ja)は知っている。
- [Google App Engine](https://cloud.google.com/appengine/?hl=ja)のことも名前とどういったものかくらいは知っている。
- [MySQL](https://www.mysql.com/jp/)等、リレーショナルデータベースについて、ざっくりとはわかっている。

以下は済んだ上での作業。

- GCPプロジェクトの作成
- [Cloud SDK](https://cloud.google.com/sdk/docs/)のインストールと初期化・認証

# 開発環境
### # OS
```
$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="18.04.2 LTS (Bionic Beaver)"
```

### # Cloud SDK
```
$ gcloud version
Google Cloud SDK 246.0.0
```

### # Golang
```
$ go version
go version go1.11.4 linux/amd64
```

### # Vegeta

```
$ vegeta -version
Version: cli/v12.2.0
Commit: 65db074680f5a0860d495e5fd037074296a4c425
Runtime: go1.11.4 linux/amd64
Date: 2019-01-20T15:07:37Z+0000
```

# 実践

## 準備

Cloud SQL上に「`db-g1-small`」タイプのインスタンスを作成後、「`fs14db01`」という名前でデータベース作成。
※[前回](https://qiita.com/sky0621/items/0c019a36892a5e9deead#clous-sql-のセットアップ)参照。

## Goアプリのソース

### main.go

```go:[パッケージ宣言とインポート文]
package main

import (
	"fmt"
	"net/http"
	"os"

	"github.com/jinzhu/gorm"

	"github.com/google/uuid"

	_ "github.com/go-sql-driver/mysql"
	"github.com/labstack/echo"
)
```

```go:[CloudSQL接続]
func main() {
	db, err := gorm.Open("mysql",
		fmt.Sprintf("root:%s@unix(/cloudsql/%s)/fs14db01?parseTime=True",
			os.Getenv("PASS"), os.Getenv("CONN")))
	if err != nil {
		panic(err)
	}
	defer func() {
		if err := db.Close(); err != nil {
			panic(err)
		}
	}()
	// --------------------------------------------------------------
	// Pattern 1
	//db.DB().SetMaxIdleConns(0)
	//db.DB().SetMaxOpenConns(0)

	// Pattern 2
	//db.DB().SetMaxIdleConns(0)
	//db.DB().SetMaxOpenConns(95)

	// Pattern 3
	//db.DB().SetMaxIdleConns(0)
	//db.DB().SetMaxOpenConns(200)

	// Pattern 4
	//db.DB().SetMaxIdleConns(95)
	//db.DB().SetMaxOpenConns(95)

	// Pattern 5
	//db.DB().SetMaxIdleConns(200)
	//db.DB().SetMaxOpenConns(200)

	// Pattern 5
	//db.DB().SetMaxIdleConns(1000)
	//db.DB().SetMaxOpenConns(1000)
	// --------------------------------------------------------------
```

↑のコメントアウトした部分が今回の実験の肝。
詳細は後述。

```go:[WebAPIサーバの設定と起動]
	e := echo.New()
	e.POST("/user", func(c echo.Context) error {
		id := uuid.New().String()
		u := &User{
			ID:   id,
			Name: fmt.Sprintf("user-%s", id),
			Mail: fmt.Sprintf("mail-%s@example.com", id),
		}
		if err := db.Save(u).Error; err != nil {
			return c.JSON(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
		}
		return c.JSON(http.StatusOK, "OK")
	})
	e.Logger.Fatal(e.Start(fmt.Sprintf(":%s", os.Getenv("PORT"))))
}
```

```go:[userレコード構造体]
type User struct {
	ID   string `gorm:"column:id"`
	Name string `gorm:"column:name"`
	Mail string `gorm:"column:mail"`
}

func (u *User) TableName() string {
	return "user"
}
```

### app.yaml

```yaml:[app.yaml]
runtime: go111

includes:
  -  secret.yaml
```

### secret.yaml

```yaml:[secret.yaml]
env_variables:
  CONN: 【自分のGCPプロジェクトID】:asia-northeast1:sample-001
  PASS: 【Cloud SQLの対象DBのパスワード】
```

## 実験の肝

先述の通り、ソース中、コメントアウトした部分（DB接続時のコネクションの扱い方）が肝。

### 最大アイドルコネクション数の設定

アイドル状態にしておくコネクション数。現時点でデフォルトは「`2`」。
「`0`以下」ならアイドリング状態にしない。
後述の「最大オープンコネクション数（が０でなく）」を超えた設定をしても最大オープンコネクション数と合わせられる想定。

```go:[go/src/database/sql/sql.go]
// SetMaxIdleConns sets the maximum number of connections in the idle
// connection pool.
//
// If MaxOpenConns is greater than 0 but less than the new MaxIdleConns,
// then the new MaxIdleConns will be reduced to match the MaxOpenConns limit.
//
// If n <= 0, no idle connections are retained.
//
// The default max idle connections is currently 2. This may change in
// a future release.
func (db *DB) SetMaxIdleConns(n int) {
```

### 最大オープンコネクション数の設定

オープンできるコネクション数の限界。デフォルトは「`0`」で、０の場合は限度なくオープンしにいく。

```go:[go/src/database/sql/sql.go]
// SetMaxOpenConns sets the maximum number of open connections to the database.
//
// If MaxIdleConns is greater than 0 and the new MaxOpenConns is less than
// MaxIdleConns, then MaxIdleConns will be reduced to match the new
// MaxOpenConns limit.
//
// If n <= 0, then there is no limit on the number of open connections.
// The default is 0 (unlimited).
func (db *DB) SetMaxOpenConns(n int) {
```

## 実験

「最大アイドルコネクション数」と「最大オープンコネクション数」を変えながら、App EngineからCloud SQLへの接続時の制限とされている「`１インスタンスあたりの最大同時接続数＝100`」を超えた場合の挙動を確認する。
「[Vegeta](https://github.com/tsenart/vegeta)」という負荷ツールを使って、毎秒 X リクエストを５秒間流してみる。
**※「X」は実験内容に応じて変更**

<コマンド例>

```
$ echo "POST https://idle0-open-unlimited-dot-【自分のGCPプロジェクトID】.appspot.com/user" | vegeta attack -output=/tmp/vegeta_result.bin -rate=200 -duration=5s
```

上記は「最大アイドルコネクション数」と「最大オープンコネクション数」ともに「０」の設定で実装したアプリに対して、毎秒 200 リクエストを５秒間実行するもの。

### ■アイドルせず無制限にコネクションオープン

#### 実験内容

以下それぞれのレートで挙動を確認する。

- 毎秒 100 リクエスト
- 毎秒 200 リクエスト

#### 結果予想

毎秒 100 リクエストは問題なく全てのリクエストで 200 OK レスポンスを返す。
それ以外のケースでは、１App Engineインスタンスがリクエストをさばくために同じインスタンスから際限なくCloud SQLにコネクション張りにいき、処理しきれなく失敗となるレスポンスが発生する。

#### 実施

##### 【毎秒 100 リクエストを５回分】

```
Latencies     [mean, 50, 95, 99, max]  384.081067ms, 373.585ms, 509.772127ms, 566.791891ms, 595.885825ms
Latencies     [mean, 50, 95, 99, max]  358.286961ms, 375.221102ms, 475.857641ms, 580.513767ms, 946.918016ms
Latencies     [mean, 50, 95, 99, max]  348.681478ms, 300.569866ms, 607.253861ms, 670.309172ms, 711.820514ms
Latencies     [mean, 50, 95, 99, max]  374.172648ms, 389.652528ms, 538.911238ms, 604.715239ms, 643.523716ms
Latencies     [mean, 50, 95, 99, max]  433.331276ms, 436.36702ms, 532.807731ms, 566.448641ms, 579.696203ms
```

```
Success       [ratio]                  100.00%
Success       [ratio]                  98.00%
Success       [ratio]                  100.00%
Success       [ratio]                  97.80%
Success       [ratio]                  99.60%
```

##### 【毎秒 200 リクエスト】

```
Latencies     [mean, 50, 95, 99, max]  3.656447528s, 2.87129807s, 8.332759389s, 9.642830969s, 10.964205628s
Latencies     [mean, 50, 95, 99, max]  3.285328297s, 2.518179725s, 7.513602241s, 8.775689476s, 9.69245987s
Latencies     [mean, 50, 95, 99, max]  3.221727209s, 2.5302591s, 7.36735507s, 8.529768254s, 9.685437683s
Latencies     [mean, 50, 95, 99, max]  3.191123034s, 2.453029911s, 7.195667353s, 8.48264967s, 8.992381951s
Latencies     [mean, 50, 95, 99, max]  3.243005216s, 2.496180582s, 7.379312657s, 8.611970742s, 9.856214946s
```

```
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  99.00%
Success       [ratio]                  99.00%
```

#### 結果

レートに関わらず、エラーが発生する回があらわれた。
アイドリングせず、リクエストがあれば無制限にコネクションオープンする設定においては、明確に以下の制限がわかる挙動にならなかった。

**それぞれのApp EngineインスタンスからCloud SQLインスタンスに接続できる数は「`100`」までという制限がある。**

### ■アイドルせずApp Engineの１インスタンスからCloud SQLインスタンスへの同時接続数は「95」

#### 実験内容

以下それぞれのレートで挙動を確認する。

- 毎秒 100 リクエスト
- 毎秒 200 リクエスト

#### 結果予想

全てのケースで全リクエスト 200 OK レスポンスを返す。

#### 実施

##### 【毎秒 100 リクエスト】

```
Latencies     [mean, 50, 95, 99, max]  452.889849ms, 441.297314ms, 601.168658ms, 658.985005ms, 695.736952ms
Latencies     [mean, 50, 95, 99, max]  544.325051ms, 524.937348ms, 736.472778ms, 762.562193ms, 797.121262ms
Latencies     [mean, 50, 95, 99, max]  424.314663ms, 400.245986ms, 624.663188ms, 685.486331ms, 735.182867ms
Latencies     [mean, 50, 95, 99, max]  359.927434ms, 369.749875ms, 437.679054ms, 459.184288ms, 479.638534ms
Latencies     [mean, 50, 95, 99, max]  420.811133ms, 410.380115ms, 687.227128ms, 826.540714ms, 1.310744809s
```

```
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  98.00%
```

##### 【毎秒 200 リクエスト】

```
Latencies     [mean, 50, 95, 99, max]  2.884555846s, 2.132597469s, 6.722514625s, 8.060224999s, 9.17968338s
Latencies     [mean, 50, 95, 99, max]  3.241793149s, 2.570532677s, 7.219441917s, 8.723126801s, 9.771961486s
Latencies     [mean, 50, 95, 99, max]  3.250406007s, 2.494085705s, 7.375126147s, 8.994445098s, 9.536050535s
Latencies     [mean, 50, 95, 99, max]  3.349980365s, 2.612510507s, 7.615872613s, 8.907686483s, 10.00627403s
Latencies     [mean, 50, 95, 99, max]  3.167480322s, 2.393982007s, 7.191928282s, 8.429845004s, 9.732517788s
```

```
Success       [ratio]                  95.90%
Success       [ratio]                  100.00%
Success       [ratio]                  99.90%
Success       [ratio]                  100.00%
Success       [ratio]                  99.00%
```

#### 結果

やはり、レートに関わらず、エラーが発生する回があらわれた。
エラーの内容は下記。

```
Error Set:
Post https://open-95-dot-【自分のGCPプロジェクトID】.appspot.com/user: http2: timeout awaiting response headers
```

### ■App Engineの１インスタンスからCloud SQLインスタンスへの同時接続数は「95」、アイドル中の接続数「95」

#### 実験内容

以下それぞれのレートで挙動を確認する。

- 毎秒 100 リクエスト
- 毎秒 200 リクエスト

#### 結果予想

全てのケースで全リクエスト 200 OK レスポンスを返す。

#### 実施

##### 【毎秒 100 リクエスト】

```
Latencies     [mean, 50, 95, 99, max]  63.29288ms, 58.153708ms, 118.887245ms, 150.737303ms, 177.86988ms
Latencies     [mean, 50, 95, 99, max]  48.615312ms, 36.542679ms, 98.190003ms, 190.009727ms, 220.432868ms
Latencies     [mean, 50, 95, 99, max]  41.683938ms, 32.352082ms, 83.821587ms, 130.818981ms, 168.576253ms
Latencies     [mean, 50, 95, 99, max]  44.639441ms, 37.782216ms, 90.53393ms, 178.503114ms, 247.647451ms
Latencies     [mean, 50, 95, 99, max]  39.65634ms, 27.778945ms, 82.746423ms, 153.609157ms, 194.314567ms
```

```
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
```

##### 【毎秒 200 リクエスト】

```
Latencies     [mean, 50, 95, 99, max]  67.411761ms, 50.444954ms, 154.428824ms, 235.421379ms, 461.221026ms
Latencies     [mean, 50, 95, 99, max]  33.590508ms, 25.526145ms, 76.341847ms, 106.224266ms, 164.443519ms
Latencies     [mean, 50, 95, 99, max]  51.818999ms, 39.502633ms, 123.317561ms, 226.575409ms, 698.368402ms
Latencies     [mean, 50, 95, 99, max]  44.985059ms, 36.407095ms, 99.617469ms, 155.426199ms, 200.001371ms
Latencies     [mean, 50, 95, 99, max]  36.939052ms, 27.502926ms, 80.993458ms, 171.622113ms, 221.517229ms
```

```
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  97.60%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
```

##### 【毎秒 1000 リクエスト】

```
Latencies     [mean, 50, 95, 99, max]  3.961474048s, 3.502336695s, 8.950770485s, 10.394910039s, 11.772457859s
Latencies     [mean, 50, 95, 99, max]  2.932212248s, 2.387595818s, 7.209837606s, 8.700746092s, 10.033527918s
Latencies     [mean, 50, 95, 99, max]  3.064551746s, 2.409040168s, 7.537645463s, 8.837644957s, 10.498085764s
Latencies     [mean, 50, 95, 99, max]  3.286309375s, 2.521588034s, 8.251770507s, 9.744014212s, 11.461399857s
Latencies     [mean, 50, 95, 99, max]  2.781278591s, 2.147507557s, 6.995549716s, 8.492080548s, 10.129869204s
```

```
Success       [ratio]                  98.90%
Success       [ratio]                  100.00%
Success       [ratio]                  98.76%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
```

#### 結果

やはり、レートに関わらず、エラーが発生する回があらわれた。
「`MaxIdleConns`」と「`MaxOpenConns`」ともに以下ぎりぎりの数値にしてもエラーが発生する。

*「`１インスタンスあたりの最大同時接続数＝100`」*

```
Latencies     [mean, 50, 95, 99, max]  61.774114ms, 45.738899ms, 158.331009ms, 260.890918ms, 452.438621ms
Latencies     [mean, 50, 95, 99, max]  35.424859ms, 27.079778ms, 72.247126ms, 154.002554ms, 203.513374ms
Latencies     [mean, 50, 95, 99, max]  44.677085ms, 33.469162ms, 99.395694ms, 168.410454ms, 274.188638ms
Latencies     [mean, 50, 95, 99, max]  39.311035ms, 29.595308ms, 83.610205ms, 177.312437ms, 219.554742ms
Latencies     [mean, 50, 95, 99, max]  55.206895ms, 45.538022ms, 110.174877ms, 156.045373ms, 199.244258ms
```

### ■App Engineの１インスタンスからCloud SQLインスタンスへの同時接続数は「200」、アイドル中の接続数「200」

#### 実験内容

以下それぞれのレートで挙動を確認する。

- 毎秒 100 リクエスト
- 毎秒 200 リクエスト

#### 結果予想

全てのケースで全リクエスト 200 OK レスポンスを返す。

#### 実施

##### 【毎秒 100 リクエスト】

```
Latencies     [mean, 50, 95, 99, max]  61.774114ms, 45.738899ms, 158.331009ms, 260.890918ms, 452.438621ms
Latencies     [mean, 50, 95, 99, max]  35.424859ms, 27.079778ms, 72.247126ms, 154.002554ms, 203.513374ms
Latencies     [mean, 50, 95, 99, max]  44.677085ms, 33.469162ms, 99.395694ms, 168.410454ms, 274.188638ms
Latencies     [mean, 50, 95, 99, max]  39.311035ms, 29.595308ms, 83.610205ms, 177.312437ms, 219.554742ms
Latencies     [mean, 50, 95, 99, max]  55.206895ms, 45.538022ms, 110.174877ms, 156.045373ms, 199.244258ms
```

```
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
```

##### 【毎秒 200 リクエスト】

```
Latencies     [mean, 50, 95, 99, max]  65.297997ms, 46.328684ms, 193.928049ms, 430.665045ms, 1.035112389s
Latencies     [mean, 50, 95, 99, max]  47.575763ms, 39.133648ms, 93.807154ms, 175.933489ms, 226.582291ms
Latencies     [mean, 50, 95, 99, max]  61.042032ms, 45.306004ms, 177.094469ms, 288.253016ms, 360.405968ms
Latencies     [mean, 50, 95, 99, max]  86.173406ms, 55.221664ms, 246.068954ms, 362.140172ms, 794.767386ms
Latencies     [mean, 50, 95, 99, max]  71.282898ms, 53.339071ms, 164.91989ms, 334.030611ms, 391.249248ms
```

```
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
```

##### 【毎秒 500 リクエスト】

```
Latencies     [mean, 50, 95, 99, max]  175.614195ms, 163.973076ms, 357.234646ms, 556.376964ms, 1.061742841s
Latencies     [mean, 50, 95, 99, max]  836.468549ms, 669.739234ms, 2.126049478s, 3.004736981s, 4.667805048s
Latencies     [mean, 50, 95, 99, max]  621.899782ms, 473.544358ms, 1.565957858s, 2.353069857s, 3.175849897s
Latencies     [mean, 50, 95, 99, max]  531.594674ms, 424.57262ms, 1.302940472s, 1.757911144s, 3.494456259s
Latencies     [mean, 50, 95, 99, max]  116.755608ms, 100.680707ms, 254.908827ms, 351.484135ms, 2.023495735s
```

```
Success       [ratio]                  99.84%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  97.04%
```

### ■App Engineの１インスタンスからCloud SQLインスタンスへの同時接続数は「1000」、アイドル中の接続数「1000」

#### 実験内容

以下それぞれのレートで挙動を確認する。

- 毎秒 500 リクエスト
- 毎秒 1000 リクエスト

#### 結果予想

全てのケースで全リクエスト 200 OK レスポンスを返す。

#### 実施

##### 【毎秒 500 リクエスト】

```
Latencies     [mean, 50, 95, 99, max]  568.785372ms, 440.275159ms, 1.332036036s, 2.033318787s, 2.992619632s
Latencies     [mean, 50, 95, 99, max]  494.718679ms, 345.014322ms, 1.37466731s, 1.957682831s, 2.884500171s
Latencies     [mean, 50, 95, 99, max]  585.637774ms, 435.852227ms, 1.505050567s, 2.182076798s, 3.13677678s
Latencies     [mean, 50, 95, 99, max]  564.618249ms, 426.371331ms, 1.502413537s, 2.206958146s, 4.03235266s
Latencies     [mean, 50, 95, 99, max]  382.541357ms, 325.446928ms, 877.323339ms, 1.282798842s, 2.280180238s
```

```
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  97.32%
```

##### 【毎秒 1000 リクエスト】

```
Latencies     [mean, 50, 95, 99, max]  2.966114857s, 2.254049409s, 7.525979114s, 8.963435191s, 10.119524818s
Latencies     [mean, 50, 95, 99, max]  3.029569385s, 2.502902361s, 7.436747535s, 9.017578718s, 10.497356724s
Latencies     [mean, 50, 95, 99, max]  3.210386112s, 2.682305189s, 7.752421804s, 9.184400957s, 10.409681587s
Latencies     [mean, 50, 95, 99, max]  3.123610982s, 2.622561986s, 7.491094617s, 8.867739566s, 10.348725103s
Latencies     [mean, 50, 95, 99, max]  3.27176631s, 2.829572453s, 7.693434499s, 9.049754142s, 10.556765042s
```

```
Success       [ratio]                  100.00%
Success       [ratio]                  98.62%
Success       [ratio]                  100.00%
Success       [ratio]                  100.00%
Success       [ratio]                  99.44%
```


# まとめ
想定と違っていて、困惑。

**それぞれのApp EngineインスタンスからCloud SQLインスタンスに接続できる数は「`100`」までという制限がある。**

とのことなので、「`SetMaxIdleConns`」及び「`SetMaxOpenConns`」で指定すべきは「`100`未満」と想定していた。
が、実際は、「`1000`」を指定していたとしても、それによってメモリを圧迫して異常終了するでもない。

どのような設定であっても一定の割合で以下のようにタイムアウトは発生する。

```
Error Set:
Post https://open-95-dot-【自分のGCPプロジェクトID】.appspot.com/user: http2: timeout awaiting response headers
```

傾向としては、負荷に対して十分な `MaxIdleConns` を設定していた場合にレイテンシーの改善とエラー発生率の減少が見られる。
（ただ、それも毎秒 100 ないし 200 リクエストまでの傾向で、毎秒 500 リクエスト以上になってくると、それほどはっきりとは言えない。）

## 【毎秒 100 リクエストを５回分】

| No | MaxIdleConns | MaxOpenConns | Latencies<br>(mean) | Success<br>(%) |
| --- | --- | --- | --- | --- |
| 01a | 0 | 0 | 384.081067ms | 100 |
| 01b | 0 | 0 | 358.286961ms | 98 |
| 01c | 0 | 0 | 348.681478ms | 100 |
| 01d | 0 | 0 | 374.172648ms | 97.8 |
| 01e | 0 | 0 | 433.331276ms | 99.6 |
| 02a | 0 | 95 | 452.88984ms | 100 |
| 02b | 0 | 95 | 544.325051ms | 100 |
| 02c | 0 | 95 | 424.314663ms | 100 |
| 02d | 0 | 95 | 359.927434ms | 100 |
| 02e | 0 | 95 | 420.811133ms | 98 |
| 03a | 95 | 95 | 63.29288ms | 100 |
| 03b | 95 | 95 | 48.615312ms | 100 |
| 03c | 95 | 95 | 41.683938ms | 100 |
| 03d | 95 | 95 | 44.639441ms | 100 |
| 03e | 95 | 95 | 39.65634ms | 100 |
| 04a | 200 | 200 | 61.774114ms | 100 |
| 04b | 200 | 200 | 35.424859ms | 100 |
| 04c | 200 | 200 | 44.677085ms | 100 |
| 04d | 200 | 200 | 39.311035ms | 100 |
| 04e | 200 | 200 | 55.206895ms | 100 |

## 【毎秒 200 リクエストを５回分】

| No | MaxIdleConns | MaxOpenConns | Latencies<br>(mean) | Success<br>(%) |
| --- | --- | --- | --- | --- |
| 01a | 0 | 0 | 3.656447528s | 100 |
| 01b | 0 | 0 | 3.285328297s | 100 |
| 01c | 0 | 0 | 3.221727209s | 100 |
| 01d | 0 | 0 | 3.191123034s | 99 |
| 01e | 0 | 0 | 3.243005216s | 99 |
| 02a | 0 | 95 | 2.884555846s | 95.9 |
| 02b | 0 | 95 | 3.241793149s | 100 |
| 02c | 0 | 95 | 3.250406007s | 99.9 |
| 02d | 0 | 95 | 3.349980365s | 100 |
| 02e | 0 | 95 | 3.167480322s | 99 |
| 03a | 95 | 95 | 67.411761ms | 100 |
| 03b | 95 | 95 | 33.590508ms | 100 |
| 03c | 95 | 95 | 51.818999ms | 97.6 |
| 03d | 95 | 95 | 44.985059ms | 100 |
| 03e | 95 | 95 | 36.939052ms | 100 |
| 04a | 200 | 200 | 65.297997ms | 100 |
| 04b | 200 | 200 | 47.575763ms | 100 |
| 04c | 200 | 200 | 61.042032ms | 100 |
| 04d | 200 | 200 | 86.173406ms | 100 |
| 04e | 200 | 200 | 71.282898ms | 100 |

## 【毎秒 500 リクエストを５回分】

| No | MaxIdleConns | MaxOpenConns | Latencies<br>(mean) | Success<br>(%) |
| --- | --- | --- | --- | --- |
| 01a | 200 | 200 | 175.614195ms | 99.84 |
| 01b | 200 | 200 | 836.468549ms | 100 |
| 01c | 200 | 200 | 621.899782ms | 100 |
| 01d | 200 | 200 | 531.594674ms | 100 |
| 01e | 200 | 200 | 116.755608ms | 97.4 |
| 02a | 1000 | 1000 | 568.785372ms | 100 |
| 02b | 1000 | 1000 | 494.718679ms | 100 |
| 02c | 1000 | 1000 | 585.637774ms | 100 |
| 02d | 1000 | 1000 | 564.618249ms | 100 |
| 02e | 1000 | 1000 | 382.541357ms | 97.32 |

## 【毎秒 1000 リクエストを５回分】

| No | MaxIdleConns | MaxOpenConns | Latencies<br>(mean) | Success<br>(%) |
| --- | --- | --- | --- | --- |
| 01a | 95 | 95 | 3.961474048s | 98.9 |
| 01b | 95 | 95 | 2.932212248s | 100 |
| 01c | 95 | 95 | 3.064551746s | 98.76 |
| 01d | 95 | 95 | 3.286309375s | 100 |
| 01e | 95 | 95 | 2.781278591s | 100 |
| 02a | 1000 | 1000 | 2.966114857s | 100 |
| 02b | 1000 | 1000 | 3.029569385s | 98.62 |
| 02c | 1000 | 1000 | 3.210386112s | 100 |
| 02d | 1000 | 1000 | 3.123610982s | 100 |
| 02e | 1000 | 1000 | 3.27176631s | 99.44 |

う〜ん、わからない。

# 追記
あらためて、アイドルコネクション数０、最大同時接続数が無制限のアプリ設定で、秒間 5000 リクエストを５秒間実施。

## Cloud SQLの設定再確認

![Screenshot from 2019-05-23 09-17-39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180599/c2dd1a8e-0922-79f5-01fb-b8e513145bf2.png)

## 実施

```
$ echo "POST https://open-unlimited-dot-【自分のGCPプロジェクトID】.appspot.com/user" | vegeta attack -output=/tmp/vegeta_result.bin -rate=1000 -duration=5s
$
```

終わるまで５秒以上かかったものの、終了。

## 結果

```
$ vegeta report /tmp/vegeta_result.bin
Requests      [total, rate]            5000, 999.22
Duration      [total, attack, wait]    54.804763323s, 5.003926215s, 49.800837108s
Latencies     [mean, 50, 95, 99, max]  26.352328518s, 26.673000774s, 50.182139085s, 52.820348481s, 54.682983988s
Bytes In      [total, mean]            25000, 5.00
Bytes Out     [total, mean]            0, 0.00
Success       [ratio]                  100.00%
Status Codes  [code:count]             200:5000  
Error Set:
```

全リクエスト正常終了。

```
MySQL [fs14db01]> select count(*) from user;
+----------+
| count(*) |
+----------+
|     5000 |
+----------+
1 row in set (0.04 sec)
```

全 5000 件すべて入ってる。
App Engineのログも確認したが、エラーなし。

## 実施時のCloud SQLの状態

### CPU使用率

最大 46%

![Screenshot from 2019-05-23 09-14-27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180599/9ca1a74a-1d42-3f7c-c424-00f8fce9ab86.png)

### メモリ使用量

最大 857MB

![Screenshot from 2019-05-23 09-16-31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180599/d00da014-8e3b-70ee-5ca6-1fa2a5406e34.png)

### クエリ実行数(?)

最大 1050件／秒

![Screenshot from 2019-05-23 09-15-48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180599/2b3abda8-afca-47ae-f99a-c8fd88b2cacf.png)

### 同時接続数

最大 632コネクション(?)

![Screenshot from 2019-05-23 09-15-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180599/0e814be9-e0a3-8a76-4fa9-3b0989555792.png)

## 実施時のApp Engineの状態

### インスタンス数

最大インスタンス数は、8

![Screenshot from 2019-05-23 23-51-46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180599/16c4799a-a53b-64e5-c57d-abfe5f6b29f6.png)

### 実際のインスタンス数

再度、秒間 1000 リクエスト実行中の際のインスタンス数をコンソールにて確認。
最大で 17 インスタンスが作成されている。

![Screenshot from 2019-05-23 23-57-45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180599/107655eb-ca3b-f4cf-3040-2fda25e1a00e.png)

### 考察

コメントもらった通り、Cloud SQL上では最大 632コネクション貼られているものの、それは、App Engineインスタンス数が増えていたため、全インスタンスからのアクセストータルでそれだけのコネクション数になっただけである可能性が・・・。
実際、単純に 632 コネクションを App Engineのインスタンス数 8 で割ると、１App Engineインスタンスあたりは 80 コネクション程度になり、以下を確認するには至っていないことになる。

**それぞれのApp EngineインスタンスからCloud SQLインスタンスに接続できる数は「`100`」までという制限がある。**

次は、アドバイスにあるように SQL文を工夫してコネクションを保持した形で試してみよう。