12.3. API へのリクエストに関する問題の特定

API に対するリクエストのどこに問題があるのかを特定するには、以下のリストに従って確認を行います。

12.3.1. API

API が動作状態にあり、リクエストに応答していることを確認するため、同じリクエストを API に対し直接、API ゲートウェイを経由せずに実行します。API ゲートウェイを経由する場合のリクエストと同じパラメーターおよびヘッダーを送信していることを確認する必要があります。失敗したリクエストが正確にわからない場合は、API ゲートウェイと API 間のトラフィックを取得します。

呼び出しに成功する場合、API に関する問題を除外できますが、失敗した場合には、さらに API のトラブルシューティングを行う必要があります。

12.3.2. API ゲートウェイ > API

API ゲートウェイと API 間のネットワークの問題を除外するには、前と同じ呼び出しを、API に直接、ゲートウェイサーバーから実行します。

呼び出しに成功する場合、API ゲートウェイ自体のトラブルシューティングに進むことができます。

12.3.3. API ゲートウェイ

API ゲートウェイが正常に機能していることを確認するためには、多くのステップを順に実施します。

12.3.3.1. API ゲートウェイの起動および稼働確認

ゲートウェイが稼働しているマシンにログインします。これに失敗する場合、ゲートウェイサーバーがダウンしている可能性があります。

ログインしたら、NGINX プロセスが実行中であることを確認します。そのためには、ps ax | grep nginx または htop を実行します。

リストに nginx master processnginx worker process が表示されている場合、NGINX は稼働中です。

12.3.3.2. ゲートウェイログでのエラーの有無確認

以下は、error.log のゲートウェイログで表示される可能性のある典型的なエラーの例です。

  • API ゲートウェイが API に接続できない

    upstream timed out (110: Connection timed out) while connecting to upstream, client: X.X.X.X, server: api.example.com, request: "GET /RESOURCE?CREDENTIALS HTTP/1.1", upstream: "http://Y.Y.Y.Y:80/RESOURCE?CREDENTIALS", host: "api.example.com"
  • API ゲートウェイが 3scale に接続できない

    2015/11/20 11:33:51 [error] 3578#0: *1 upstream timed out (110: Connection timed out) while connecting to upstream, client: 127.0.0.1, server: , request: "GET /api/activities.json?user_key=USER_KEY HTTP/1.1", subrequest: "/threescale_authrep", upstream: "https://54.83.62.186:443/transactions/authrep.xml?provider_key=YOUR_PROVIDER_KEY&service_id=SERVICE_ID&usage[hits]=1&user_key=USER_KEY&log%5Bcode%5D=", host: "localhost"

12.3.4. API ゲートウェイ > 3scale

API ゲートウェイが正常に動作していることを確認したら、次のステップは API ゲートウェイと 3scale 間の接続についてのトラブルシューティングです。

12.3.4.1. API ゲートウェイでの 3scale へのアクセスの可否確認

API ゲートウェイに NGINX を使用している場合、ゲートウェイが 3scale と通信できないときは、以下のメッセージが nginx エラーログに表示されます。

2015/11/20 11:33:51 [error] 3578#0: *1 upstream timed out (110: Connection timed out) while connecting to upstream, client: 127.0.0.1, server: , request: "GET /api/activities.json?user_key=USER_KEY HTTP/1.1", subrequest: "/threescale_authrep", upstream: "https://54.83.62.186:443/transactions/authrep.xml?provider_key=YOUR_PROVIDER_KEY&service_id=SERVICE_ID&usage[hits]=1&user_key=USER_KEY&log%5Bcode%5D=", host: "localhost"

ここでは、upstream の値に注意してください。この IP は、3scale プロダクトが解決する IP の 1 つに対応します。これは、3scale へのアクセスに問題があることを意味します。逆引き DNS ルックアップを実行して、nslookup を呼び出すことで、IP のドメインを確認することができます。

たとえば、API ゲートウェイが 3scale にアクセスできないからといって、3scale がダウンしているとは限りません。この問題の最も典型的な理由の 1 つは、API ゲートウェイが 3scale に接続することを妨げるファイアウォールルールです。

ゲートウェイと 3scale の間に、接続のタイムアウトを引き起こすネットワークの問題が存在する可能性があります。この場合、一般的な接続の問題のトラブルシューティング に関する手順を実施して、問題がどこにあるのかを特定する必要があります。

ネットワークの問題を除外するため、traceroute または MTR を使用して、ルーティングおよびパケット送信を確認します。3scale と API ゲートウェイに接続できるマシンから同じコマンドを実行し、出力を比較することもできます。

さらに、API ゲートウェイと 3scale の間で送信されているトラフィックを確認するには、一時的に 3scale プロダクトの HTTP エンドポイント (su1.3scale.net) を使用するように切り替えている限りは、tcpdump を使用できます。

12.3.4.2. API ゲートウェイが 3scale のアドレスを正しく解決していることの確認

nginx.conf にリゾルバーディレクティブが追加されていることを確認します。

nginx.conf の設定例を以下に示します。

http {
  lua_shared_dict api_keys 10m;
  server_names_hash_bucket_size 128;
  lua_package_path ";;$prefix/?.lua;";
  init_by_lua 'math.randomseed(ngx.time()) ; cjson = require("cjson")';

  resolver 8.8.8.8 8.8.4.4;

Google DNS (8.8.8.8 および 1377 8.8.4.4) は希望する DNS と置き換え可能です。

API ゲートウェイから DNS 解決を確認するには、以下のように指定したリゾルバー IP で nslookup を呼び出します。

nslookup su1.3scale.net 8.8.8.8
;; connection timed out; no servers could be reached

上記の例は、Google DNS に到達できない場合に返されるレスポンスを示しています。この場合、リゾルバー IP を更新する必要があります。nginx の error.log に、以下のアラートが表示される場合もあります。

2016/05/09 14:15:15 [alert] 9391#0: send() failed (1: Operation not permitted) while resolving, resolver: 8.8.8.8:53

最後に、dig any su1.3scale.net を実行して、現在 3scale Service Management API について動作中の IP アドレスを確認します。これは、3scale によって使用される可能性のある IP アドレスの範囲全体ではないことに注意してください。容量の理由から、一部の IP アドレスがスワップインまたはスワップアウトされる場合があります。さらに、3scale サービスのドメイン名を今後追加することもできます。このため、該当する場合は、インテグレーション中に指定された特定のアドレスに対して必ずテストを行う必要があります。

12.3.4.3. API ゲートウェイが 3scale を正しく呼び出していることの確認

API ゲートウェイが 3scale に送信しているリクエストを確認する場合は、トラブルシューティング用途に限り、nginx.conf の 3scale authrep の場所 (API キーおよび App_id 認証モードの場合は /threescale_authrep) に、以下のスニペットを追加することができます。

body_filter_by_lua_block{
  if ngx.req.get_headers()["X-3scale-debug"] == ngx.var.provider_key then
    local resp = ""
    ngx.ctx.buffered = (ngx.ctx.buffered or "") .. string.sub(ngx.arg[1], 1, 1000)
    if ngx.arg[2] then
      resp = ngx.ctx.buffered
    end

    ngx.log(0, ngx.req.raw_header())
    ngx.log(0, resp)
  end
}

X-3scale-debug header が送信されると (例: curl -v -H 'X-3scale-debug: YOUR_PROVIDER_KEY' -X GET "https://726e3b99.ngrok.com/api/contacts.json?access_token=7c6f24f5")、このスニペットにより以下の追加ロギングが nginx error.log に追加されます。

これにより、以下のログエントリーが生成されます。

2016/05/05 14:24:33 [] 7238#0: *57 [lua] body_filter_by_lua:7: GET /api/contacts.json?access_token=7c6f24f5 HTTP/1.1
Host: 726e3b99.ngrok.io
User-Agent: curl/7.43.0
Accept: */*
X-Forwarded-Proto: https
X-Forwarded-For: 2.139.235.79

 while sending to client, client: 127.0.0.1, server: pili-virtualbox, request: "GET /api/contacts.json?access_token=7c6f24f5 HTTP/1.1", subrequest: "/threescale_authrep", upstream: "https://54.83.62.94:443/transactions/oauth_authrep.xml?provider_key=REDACTED&service_id=REDACTED&usage[hits]=1&access_token=7c6f24f5", host: "726e3b99.ngrok.io"
2016/05/05 14:24:33 [] 7238#0: *57 [lua] body_filter_by_lua:8: <?xml version="1.0" encoding="UTF-8"?><error code="access_token_invalid">access_token "7c6f24f5" is invalid: expired or never defined</error> while sending to client, client: 127.0.0.1, server: pili-virtualbox, request: "GET /api/contacts.json?access_token=7c6f24f5 HTTP/1.1", subrequest: "/threescale_authrep", upstream: "https://54.83.62.94:443/transactions/oauth_authrep.xml?provider_key=REDACTED&service_id=REDACTED&usage[hits]=1&access_token=7c6f24f5", host: "726e3b99.ngrok.io"

最初のエントリー (2016/05/05 14:24:33 [] 7238#0: *57 [lua] body_filter_by_lua:7:) は、3scale に送信されたリクエストヘッダーを出力します。この例では、Host、User-Agent、Accept、X-Forwarded-Proto、および X-Forwarded-For です。

2 番目のエントリー (2016/05/05 14:24:33 [] 7238#0: *57 [lua] body_filter_by_lua:8:) は、3scale からのレスポンスを出力します。この例では、<error code="access_token_invalid">access_token "7c6f24f5" is invalid: expired or never defined</error> となります。

両方がオリジナルのリクエスト (GET /api/contacts.json?access_token=7c6f24f5) とサブリクエストの位置 (/threescale_authrep)、ならびにアップストリームリクエスト (upstream: "https://54.83.62.94:443/transactions/threescale_authrep.xml?provider_key=REDACTED&service_id=REDACTED&usage[hits]=1&access_token=7c6f24f5") を出力します。 この最後の値で、どの 3scale IP が解決されているかと、3scale に行った実際のリクエストも確認できます。

12.3.5. 3scale

12.3.5.1. 3scale がエラーを返しているかの確認

3scale は利用可能だが、呼び出しが API に通ることを妨げるエラーを API ゲートウェイに返している可能性もあります。承認呼び出しを 3scale で直接実行して、レスポンスを確認します。エラーが発生した場合は、3scale のエラーコードセクションで何が問題かを確認します。

12.3.5.2. 3scale デバッグヘッダーの使用

たとえば、以下のように X-3scale-debug ヘッダーを設定して API を呼び出すことで、3scale デバッグヘッダーを有効にすることもできます。

curl -v -X GET "https://api.example.com/endpoint?user_key" X-3scale-debug: YOUR_SERVICE_TOKEN

これにより、API レスポンスで以下のヘッダーが返されます。

X-3scale-matched-rules: /, /api/contacts.json
< X-3scale-credentials: access_token=TOKEN_VALUE
< X-3scale-usage: usage[hits]=2
< X-3scale-hostname: HOSTNAME_VALUE

12.3.5.3. インテグレーションエラーの確認

管理ポータルでインテグレーションエラーを確認し、3scale へのトラフィックに関する問題がないか確認することもできます。https://YOUR_DOMAIN-admin.3scale.net/apiconfig/errors を参照してください。

インテグレーションエラーの理由の 1 つは、サーバーブロックでは無効な underscores_in_headers ディレクティブによりヘッダーでクレデンシャルを送信していることです。

12.3.6. クライアント API ゲートウェイ

12.3.6.1. 一般のインターネットから API ゲートウェイにアクセスできるか調べる

ブラウザーをゲートウェイサーバーの IP アドレス (またはドメイン名) に転送するよう試みます。これに失敗する場合、該当するポートのファイアウォールが開いていることを確認してください。

12.3.6.2. クライアントから API ゲートウェイにアクセスできるかの確認

可能な場合は、前述の方法 (telnet、curl など) のいずれかを使用して、クライアントから API ゲートウェイへの接続を試みます。 接続に失敗する場合、クライアントと API ゲートウェイ間のネットワークに問題が発生しています。

そうでない場合は、API への呼び出しを行うクライアントのトラブルシューティングに進む必要があります。

12.3.7. クライアント

12.3.7.1. 別のクライアントを使用した同じ呼び出しのテスト

リクエストが想定される結果を返さない場合は、別の HTTP クライアントでテストします。たとえば、Java HTTP クライアントで API を呼び出している時に何らかの問題が生じる場合、cURL を使用して結果を照合します。

クライアントとゲートウェイ間のプロキシー経由で API を呼び出し、クライアントが送信している正確なパラメーターとヘッダーを取得することもできます。

12.3.7.2. クライアントから送信されたトラフィックの確認

Wireshark などのツールを使用して、クライアントが送信しているリクエストを調べます。これにより、クライアントが API を呼び出しているかどうか、およびリクエストの詳細を確認することができます。