シナリオ背景
連携API(VPC A)とAPIを使うサービス(VPC B)はAWSの違うVPCに存在する。
2つのシステムはPeering設定されて通信できる状況。
連携APIのVPCはマルチAZ構成*になっている(2つのAZ)
Peering:2つのVPC間の通信を外部ネットワーク経由でなくL3ネットワーク経由で、でVPC間の相互に通信ができるサービスです。
マルチAZ構成:クラウド上で構築・運用されるシステムの可用性を高めるためのベストプラクティスの一つであり
VPCピア機能についてはこちらを参考してください。
シナリオ概要
サービス運用途中急に連携APIの1/3のResponseがTimoutになった。
「VPC A」環境からの接続には問題なし。
原因調査準備
「VPC B」の環境に新しいEC2インスタンスを作ってテスト環境を用意
APIの負荷テスト
vegeta・ApacheBenchを使ってAPIサーバーの性能に問題があるのかを調査。
負荷テストを行なったが特に性能上問題はなかった。
vegetaテスト方法
{API URL} に向けて 10 request/sec のレートで 30秒間 負荷をかけ続ける場合
$ echo "GET {API URL}" | vegeta attack -rate=10 -duration=30s | tee results.bin | vegeta report
Requests [total, rate, throughput] 300, 10.03, 10.03
Duration [total, attack, wait] 29.908s, 29.9s, 8.468ms
Latencies [min, mean, 50, 90, 95, 99, max] 2.424ms, 9.616ms, 8.06ms, 15.127ms, 23.502ms, 29.709ms, 88.864ms
Bytes In [total, mean] 60000, 200.00
Bytes Out [total, mean] 0, 0.00
Success [ratio] 100.00%
Status Codes [code:count] 200:300
Error Set:
ApacheBenchテスト方法
10ユーザがそれぞれ10回リクエストした場合
ab -n 100 -c 10 {API URL}
n: 生成するリクエスト数を指定します
c: 並列実行する数(コネクション数)を指定します
This is ApacheBench, Version 2.3 <$Revision: 1874286 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking xxxxxxxxxx (be patient).....done
Server Software: nginx/1.15.12
Server Hostname: xxxxxxxxxxxxx
Server Port: 80
Document Path: /api
Document Length: 25 bytes
Concurrency Level: 10
Time taken for tests: 0.148 seconds
Complete requests: 100
Failed requests: 0
Total transferred: 15300 bytes
HTML transferred: 2500 bytes
Requests per second: 676.97 [#/sec] (mean)
Time per request: 14.772 [ms] (mean)
Time per request: 1.477 [ms] (mean, across all concurrent requests)
Transfer rate: 101.15 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 2 2.3 1 14
Processing: 2 11 7.2 9 31
Waiting: 2 11 7.2 9 30
Total: 3 13 8.4 10 35
Percentage of the requests served within a certain time (ms)
50% 10
66% 16
75% 20
80% 21
90% 26
95% 30
98% 34
99% 35
100% 35 (longest request)
[ABの使い方についてはこちらを参考]
(https://dev.classmethod.jp/articles/ab-tutorial/)
連携APIサーバーの疎通テスト
curlを使ってテストサーバーからAPIを直接実行して疎通確認した結果、Timeoutが再現できました。
Timeoutの原因調査のため、curlのTraceオプションをつけて実行
$curl -sS {API URL} --trace-ascii trace.log -o /dev/null
DNS名前解決ができなかったのが原因でTimeoutになったのが分かりました。
== Info: Trying xx.xxx.xx.xx...
== Info: TCP_NODELAY set
== Info: connect to xx.xxx.xx.xx port 80 failed: Connection timed out
== Info: Trying xx.xxx.xx.x...
== Info: TCP_NODELAY set
== Info: Connected to {API URL} (xx.xxx.xx.x) port 80 (#0)
=> Send header, 169 bytes (0xa9)
0000: GET /api HTTP/1.1
0032: Host: {API URL}
0072: amazonaws.com
0081: User-Agent: curl/7.61.1
009a: Accept: */*
00a7:
<= Recv header, 15 bytes (0xf)
0000: HTTP/1.1 200
<= Recv header, 37 bytes (0x25)
0000: Date: Wed, 02 Sep 2020 06:59:42 GMT
<= Recv header, 32 bytes (0x20)
0000: Content-Type: application/json
<= Recv header, 28 bytes (0x1c)
0000: Transfer-Encoding: chunked
<= Recv header, 24 bytes (0x18)
0000: Connection: keep-alive
<= Recv header, 23 bytes (0x17)
0000: Server: nginx/1.15.12
<= Recv header, 2 bytes (0x2)
0000:
<= Recv data, 209 bytes (0xd1)
0000: c6
0004: {"result":{""}}]}}
00cc: 0
00cf:
== Info: Connection #0 to host {API URL} left intact
~
~
その後nslokup
でDSNが3つに増えてその1つに接続できなくてTimeoutになったのが判明しました。
結論
背景で連携APIサーバーのマルチAZ構成は2つだと説明したと思います。
APIサーバー(VPC A)のAZ構成を3つに増やしたけど連携APIを使うサーバー(VPC B)のPeering設定は2つのAZを許可したままになっているので新しいAZのDNSに接続できないためエラーになります。
「VPC B」のPeering設定に新しく追加されたAZサブネットのCIDRを追加することで解決。
Amazon API Gatewayを使って連携すれば上記のような設定変更の影響は無くなる。