こんにちは。CData Software Japan リードエンジニアの杉本です。
今回は Dynamics 365・Dataverse(CDS)のWeb APIを扱うにあたって重要な API 制限について確認したいと思います。
ちなみに、Dynamics 365 ・Dataverse(CDS)では Web API(OData)とSOAPの2種類のAPIがありますが、今回の記事では前者のWeb API(OData)を対象としています。
docs.microsoft.com
Dynamics 365 FO や BCのAPIとは異なるので注意してください。
Dynamics 365・DataverseのAPI制限について
まず、基本的なAPI制限を確認しておきましょう。
Dynamics 365・DataverseのAPI制限は24時間制のAPI制限となっており、APIアクセスを行っているユーザーに紐付いたライセンスの種類によって、24時間以内のリクエスト数が変わります。
それぞれのライセンスごとのAPI要求数は以下の通り。
docs.microsoft.com
※ 2021/03/08 時点の情報です
ライセンスを複数持っている場合は合算され、
例えば、Dynamics 365 プロフェッショナル(10,000)とPower Apps ユーザーごとのプラン(5,000)であれば、24時間以内のAPIリクエスト数は 15,000になるようです。
なお、ライセンスが紐付かないユーザーによるアクセス、例えばClientCredentialsを用いたアプリケーションユーザーによるアクセスの場合は、Office365(Microsoft 365)テナントごとに保持しているライセンスによって決定されます。
docs.microsoft.com
ただ、こちらの上限は最上位のプランに左右されるようなので、Dynamics 365 Enterpriseを持っていれば、ほかのどのライセンスがあっても、最大24時間で100,000リクエストまでのようです。
API リクエストあたりのデータ処理量
併せて気になるのは、1回のAPIリクエストでどのくらいのデータを処理できるのか? ではないでしょうか。
まず、データの取得に関しては、特に明示的な指定が無い限り1APIリクエストで「5000」レコード取得することができます。
docs.microsoft.com
より小さなページサイズを指定しない限り、リクエストごとに最大5000個のエンティティが返されます。
データの書き込み、更新などの処理では、バッチリクエストを利用することができるので、このバッチリクエストの制限が1回でのリクエスト上限となります。
このバッチリクエストでは、最大「1000レコード」を同時に処理できるようでした。
docs.microsoft.com
バッチリクエストには、最大1000の個別のリクエストを含めることができ、他のバッチリクエストを含めることはできません。
つまり、10,000 APIリクエスト保持している状態であれば、理論上は「5千万レコードの取得」もしくは「1千万レコードの書き込み」が可能になります。とはいっても、単純な取得や書き込みをひたすら実施することは無いと思うので、あくまで目安として考えておきましょう。
API リクエスト状況の確認方法
現在のAPI Call数は Power Platform Admin centerの「Analytics」→「Dataverse」にある「API calls statistics」から確認できます。
ただ、ユーザーごとにAPI Limitが紐付いているはずなのに、ここではテナントごとのトータルリクエスト数しか見れません・・・。
でも、上記以外にもAPIリクエストの消費状況を確認する方法があります。それは実際にAPIリクエストを行った際のレスポンスに含まれるヘッダー情報です。
docs.microsoft.com
ヘッダー名 |
値の説明 |
x-ms-ratelimit-burst-remaining-xrm-requests |
この接続の残りの要求の数 |
x-ms-ratelimit-time-remaining-xrm-requests |
同じユーザー アカウントを使用するすべての接続の残りの合計期間 |
実際のHTTPレスポンスをキャプチャしたところ、以下のように値が含まれていました。
この画像では「x-ms-ratelimit-burst-remaining-xrm-requests: 5413」となっており、APIリクエストを実行するごとに、値が減っていきました。
これを消費しつくすと、API 制限に抵触するようですね。
API 制限に抵触したらどうなるの?
そこで皆さん気になるのは、「x-ms-ratelimit-burst-remaining-xrm-requests」が無くなったら、つまりAPI制限に抵触したらどうなるの? ということだと思います。
というわけで、試しに CData Dynamics 365 for Sales Driver を使って、2万回 APIリクエストを投げてみました。
www.cdata.com
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.CData.D365Sales;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dynamics365APILimitTest
{
class Program
{
static void Main(string[] args)
{
string connectionString = "InitiateOAuth=GETANDREFRESH;OrganizationUrl=https://XXXXX.crm7.dynamics.com/;";
using (D365SalesConnection connection = new D365SalesConnection(connectionString))
{
for (int i = 0; i < 20000; i++)
{
D365SalesDataAdapter dataAdapter = new D365SalesDataAdapter(
"SELECT accountid, Name FROM Accounts", connection);
DataTable table = new DataTable();
dataAdapter.Fill(table);
Console.WriteLine($"Count: {i}; {table.Rows[1]["accountid"]}");
}
}
}
}
}
すると結果は、、、
全然エラーにならない!!!
いやいや、どう考えてもおかしいでしょ? と思って、「x-ms-ratelimit-burst-remaining-xrm-requests」を確認してみたら、、、、4959?
そんなに減ってない!?
開始時点で「x-ms-ratelimit-burst-remaining-xrm-requests」は5999(おそらく私の環境では6000がデフォルト値だったと思われる)だったんですね。
というわけで、改めてドキュメントを色々と見てみたところ、以下のような文章を発見しました。
docs.microsoft.com
アプリケーション ユーザーが基本要求容量を超えると、統合が機能しなくなりますか?
現在、発生する可能性のある合理的な超過分については、統合を停止していません。 管理者は Power Platform 管理センターで使用状況を確認することができます (Dataverse では、一般的なレポート機能は 2020 年のリリース サイクル 2 に含まれています)。 ただし、現時点でユーザーやフローが一貫して長期間制限を超ている場合は、そのユーザーを無効にするか、フローをオフにすることができます。
移行期間が終了すると、テナントが Power Platform のリクエスト限度を超えた場合には、一部の操作がさらにブロックされます。 これらのブロック作業は、主に管理、カスタマイズ領域での作業となりますが、これらの作業に限定されるものではありません (また、超過シナリオによっては他の領域にも拡大する可能性があります)。
ここには「現在、発生する可能性のある合理的な超過分については、統合を停止していません。」と書かれています。つまり、現状は合理的な範囲(?)であれば、API Limitを超過しても、特にエラーにはならないようでした。
並列処理を実施して、無理やり引き起こそうかなとも思ったんですが、あんまりやりすぎるのも忍びないので、今回の検証はここまでにしました。
CData Dynamics 365 / Dataverse Driver はどのように APIリクエストを行っているのか?
続いて CData Dynamics 365 / Dataverse Driver についても解説していきましょう。
まず、誤解の無いように予めお伝えしておきたいのですが CData DriverはDynamics 365 / Dataverse のRDB(SQL server)に接続しているわけではありません。
何かMicrosoft 側と裏口工作とかを行って、秘密裏にデータを取得しているとか、そういうわけではなく、Dynamics 365 / Dataverse のAPIを活用して、CData Driverのエクスペリエンスを実現しています。前述のAPI制限の検証例からもわかるかと思います。
現在、Dynamics 365 ・Dataverseでは、SQL Server(TDSプロトコル)のエンドポイントを使うことができますが、これともまた違ったアプローチになっています。
docs.microsoft.com
そのため、CData Dynamics 365 / Dataverse Driverを使うと、上記で紹介した API リクエスト数を消費してデータの疎通を行います。
それらを踏まえた上で実際にCData Driverがとのように、Dynamics 365 / Dataverse API に対してリクエストを行い、API 制限を消費しているのか? を解説していきます。
www.cdata.com
www.cdata.com
CData Driverのリクエストの内容はログからも確認できますが、今回はHTTPキャプチャ・プロキシツールのFiddlerを利用して、見てみました。
www.cdatablog.jp
それでは例をあげて、リクエストを見てみましょう。
例えば、CData Driverに対して「SELECT accountid, Name FROM Accounts」を発行した場合です。
これで取引先企業のデータを取得できるのですが、Fiddlerを確認してみると、以下のように3つのリクエストが飛んでいることがわかります。
「sugimomoto45.crm7.dynamics.com」のHostに対してのリクエストが今回のAPIリクエスト制限を消費するものです。Host名は皆さんの環境に併せて置き換わります。
おそらくこの記事をご覧になられている方は「1APIリクエストで済むのではないか」 とイメージされているのではないかと思いますが、実はそうではありません。
このリクエストを一つづつ紐解いてみましょう。
まず、以下の「GET https://sugimomoto45.crm7.dynamics.com/api/data/v9.0/ 」というリクエストです。これは、Dynamics 365 の環境の疎通・存在確認を行っています。
次に「GET https://sugimomoto45.crm7.dynamics.com/api/data/v9.0/$metadata 」というリクエストです。
これは、Dynamics 365 のMetadataの取得を行っています。CData Driverはその特性上、Dynamics 365 ・Dataverseでどのようなエンティティ・項目を保持しているかを事前に確認する必要があります。そのため、このようなリクエストを最初に行い、データ定義を取得しています。
最後に「GET https://sugimomoto45.crm7.dynamics.com/api/data/v9.0/accounts?$select=accountid%2cname 」というリクエストです。これで実際に取引先企業のデータを取得しています。レスポンスのJSONが確認できますね。
いかがでしょうか。このように、CData Driverでは、1SQL=1APIリクエストという図式で成り立っているわけではありません。
なお、ここで取得していたテーブル構造やカラム構造は内部的にキャッシュされるため、SELECTクエリ発行の度に取得し直すわけではありません。
また、もし1回のAPIリクエストで取得しきれないデータがある場合は、自動的にページネーションなどの処理を行って、複数回APIリクエストを実施し、データを取得するケースもあります。
「CData DriverはどのくらいAPIリクエストを消費するのか?」という質問は良く頂くのですが、上記のように様々な係数およびユースケースがあるため、一概に答えることができないものとなっています。
API Limitに抵触しないようにするにはどうしたらいいの?
最後に、これもまたよく頂く質問「API Limitに抵触しないようにするにはどうしたらいいの?」についても、回答したいと思います。
単刀直入に言ってしまえば、抵触しないようにするためのアプローチとして、単純な解決策はありません。
そのため、現在想定しているユースケースでどのくらいAPI Limitを消費するのか? を最初に見極める必要があります。
まずは自身のユースケースに合わせたAPIリクエストを実行してみて、管理画面にてどのくらいAPIリクエストを消費しているのか、是非確認してみてください。
その上で、例えばデータの書き込みが多数の割合を締めているような場合であれば、Bulk Insertなどの一括処理を行うことが可能です。
cdn.cdata.com
また、同じテーブルに何度もアクセスしてデータを取得し集計などを実施している、といったユースケースであれば、CData Driverのキャッシュ機能を利用したり
cdn.cdata.com
CDataSyncという製品を利用して、RDBやDWHに一度データをロードしてしまう、といったアプローチも有効です。
www.cdata.com
このように単純にこれを実施すれば良い、という対策はありませんが、CData Driverが標準で備えている機能を活用することで、各ユースケースごとにフィットしたクエリ方法を探ることが可能です。
もし、こういったユースケースで、APIリクエスト数を緩和したい、何か良い方法はないか? といった悩み事があれば、お気軽にテクニカルサポートまで連絡ください。
CData Software Japan - サポートフォーム
関連コンテンツ