Eng (なりたい)

はやく エンジニア になりたい

GAEのレイテンシがつらいという話

TL;DR

GAEは…

  • (Google App Engine)のレイテンシが思っていたより大きい
  • Keepaliveヘッダーを無視する
  • API サーバーとして利用するにはあまり向いていなさそう(感想)

経緯

既存のシステムの一部をAPIとして切り出そうという作業をしていました。 そこで目をつけたのがGCP(Google Cloud Platform)のGAE(Google App Engine)です。(楽だし) 他のシステムから呼ばれることもあってレスポンスタイムの要求がかなりシビアなので計測しておくことにしました。 計測対象のアプリ自体はただの echo server です。

環境

region: asia-northeast1
environment: standard
language: go

計測

abコマンドを用いて計測しました。

$ ab -c 1 -n 100 <URL>
...
Concurrency Level:      1
Time taken for tests:   25.657 seconds
Complete requests:      100
Failed requests:        0
Total transferred:      31412 bytes
HTML transferred:       4100 bytes
Requests per second:    3.90 [#/sec] (mean)
Time per request:       256.571 [ms] (mean)
Time per request:       256.571 [ms] (mean, across all concurrent requests)
Transfer rate:          1.20 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:      163  198  16.5    198     250
Processing:    49   58  11.5     54     150
Waiting:       47   58  11.6     53     150
Total:        219  256  21.0    257     360

Percentage of the requests served within a certain time (ms)
  50%    257
  66%    262
  75%    270
  80%    271
  90%    281
  95%    289
  98%    311
  99%    360
 100%    360 (longest request)

300ms 程度のレスポンスタイムとなりました。

さらに httpstatコマンドを使って内訳を見てみると。

$ httpstat <URL>
...
  DNS Lookup   TCP Connection   TLS Handshake   Server Processing   Content Transfer
[     4ms    |      61ms      |     148ms     |       49ms        |        0ms       ]
             |                |               |                   |                  |
    namelookup:4ms            |               |                   |                  |
                        connect:65ms          |                   |                  |
                                    pretransfer:213ms             |                  |
                                                      starttransfer:262ms            |
                                                                                 total:262ms

TLS Handshakeがかなりの時間を占めていました。

他のシステムからの利用であることもありぱっと思いつくのは、Keep-Alive なので試してみます。

$ ab -c 1 -n 100 -k <URL>
...
Concurrency Level:      1
Time taken for tests:   6.330 seconds
Complete requests:      100
Failed requests:        0
Keep-Alive requests:    100
Total transferred:      33804 bytes
HTML transferred:       4100 bytes
Requests per second:    15.80 [#/sec] (mean)
Time per request:       63.302 [ms] (mean)
Time per request:       63.302 [ms] (mean, across all concurrent requests)
Transfer rate:          5.21 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    2  20.0      0     200
Processing:    51   61   5.2     60      81
Waiting:       51   61   5.2     60      81
Total:         51   63  20.5     60     260

Percentage of the requests served within a certain time (ms)
  50%     60
  66%     61
  75%     63
  80%     64
  90%     68
  95%     76
  98%     81
  99%    260
 100%    260 (longest request)

いい感じ? httpstat で確認してみると

$ httpstat -k <URL>
...
  DNS Lookup   TCP Connection   Server Processing   Content Transfer
[     4ms    |      57ms      |       60ms        |        0ms       ]
             |                |                   |                  |
    namelookup:4ms            |                   |                  |
                        connect:61ms              |                  |
                                      starttransfer:276ms            |
                                                                 total:276ms

なんか数値が壊れている…

本当に Keep-Alive が効いているのか確認してみます。

$ curl -s -I -k <URL>
HTTP/2 400
content-type: text/plain; charset=utf-8
x-cloud-trace-context: XXXXXXXXXXXXXX
content-length: 30
date: Sun, 19 May 2019 13:54:14 GMT
server: Google Frontend
alt-svc: quic=":443"; ma=2592000; v="46,44,43,39"

Connection: keep-aliveがない…

ぐぐってみると…

The following headers are removed from the request: ... Keep-Alive ...

ref. Request Headers and Responses

そういう話か… 検証はしてないですが、ab , httpstatコマンドは-kオプションを付けると 「Keep-Alive」が効いている前提で計測しているだけで実際にKeep-Aliveが効いているかの確認はしていないみたいです。 ちなみに Apache JmeterではしっかりコネクションタイムがKeep-Aliveを有効にしても計測されていました。

コンテナの思想的にもKeep-Aliveを無視するというのはあっている気がするが、これに気づくのにかなり時間を使ってしまったので頭の片隅においておきたいです。

レイテンシが99%ileで360になるのはつらいと思うんだが、みんなどうやって解決しているのか気になる…

おまけ

計測の中でGCEを立てて httpstat で計測をした結果があったので載せます。

  DNS Lookup   TCP Connection   TLS Handshake   Server Processing   Content Transfer
[     4ms    |       1ms      |     10ms      |        5ms        |        0ms       ]
             |                |               |                   |                  |
    namelookup:4ms            |               |                   |                  |
                        connect:5ms           |                   |                  |
                                    pretransfer:15ms              |                  |
                                                      starttransfer:20ms             |
                                                                                 total:20ms

当たり前のことなんですが内部ネットワークが爆速で一気にすべてGCPに移行したい気持ちになりました。(そうはいかない。)