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に移行したい気持ちになりました。(そうはいかない。)