APIを利用したり、提供する中で良くあがってくる問題を紹介します。従来のシステム開発手法と異なるために、問題もまた特徴的です。それらは単に問題として終わらせるのではなく、APIらしい解決方法を考える必要があるでしょう。
トランザクション
APIを提供していて最もよくある問題がトランザクションではないでしょうか。この解決法は幾つかあります。
- トランザクションが不要な設計をする
- トランザクションIDを用いる
- 有効期限付きデータロック
トランザクションが不要な設計は最もベストな選択と言えます。実際、システムを開発していて必ずしもトランザクションが必要という場面は多くありません。アイディア次第で解決できるのですが、RDBMSにおけるトランザクションはとても便利なのでつい頼ってしまっていないでしょうか。
また、逆にトランザクションが必要な場合にそれらの処理をひとまとめにしたAPIを提供するという方法があります。その場合はRDBMSのトランザクションが使えますので安心です。
トランザクションIDを使う方法はシステムの複雑化を招く傾向があります。トランザクションを自作するのに匹敵するかも知れません。データのロック、前のデータの保存、ロック解除、データを戻す処理などを自分で作るのはとても大変ですし、不具合があると大きな問題になる可能性があります。
そもそも商品の在庫引き当てなどの場合、行単位でのデータロックで対応できる可能性があるでしょう。その上で5分間などのロック有効期限を設けることで、その間に決済処理を行ったり、失敗した場合にはロックを解除するといった処理にするのが良いかと思います。
ネットワークコネクションが増える
RESTfulなAPIではデータモデル一つに対して一つのURIが割り当てられます。そのため、3つのモデルを操作する場合には3つのネットワークコネクションが必要になります。これはスマートフォンアプリなどでは大きな問題になります。
解決策としては、
- ネットワーク接続の非同期化
- 複数処理の同時実行
があります。ネットワーク接続の非同期化は最も簡単な方法で、プログラミング側で対応できます。ただしネットワークコネクション数は変わりませんし、サーバへの負荷が高まる傾向があります。
後者の複数処理の同時実行はバッチ処理化です。3つのモデルに対するリクエストをまとめて一回でリクエストできるようにします。これはプロキシサーバを設け、そのサーバがリクエストを3つに分割してAPIリクエストを行ってもらうことで解決できます。プロキシサーバでは返ってきたレスポンスを一つに結合して返す必要があります。なお、この方法はリクエストの結果を受け取って処理判定して別なリクエストを行う場合には使えません。
例えば顧客情報と取引履歴、サポート対応履歴などを取得して画面に表示する場合、これらの情報を一回のHTTPリクエストとレスポンスだけで受け取れるようになります。
相互通信
APIは一般的にサーバへのリクエストとレスポンスで成り立っています。そのためサーバ側からクライアントに対してリクエストを行うのには向いていません。解決策としては、
- WebSocket/MQTTの利用
- WebHooksの利用
があげられます。WebSocket/MQTTは相互通信のプロトコルですが、環境によってはバッテリーの消費などが大きくなるかも知れません。WebHooksはクライアントとサーバが常時繋がっている必要はありませんが、クライアント側がHTTPアクセスを受け入れている必要があります。
スマートフォンアプリの場合はプッシュ通知を使い、それを受け取ったタイミングでAPIを叩いてもらう仕組みが使えます。
通信断
APIの処理に時間がかかっていたり、ネットワーク環境が不安定な場合にネットワークが途絶えるリスクがあります。データの取得であれば再度取得すれば良いだけですが、データの登録や更新が伴う場合は大きなリスクになります。
この問題はサーバとクライアント間で処理IDを設けることで、お互いの処理IDを交わすことで通信断した時の処理が終わっているかどうかを確認することができます。そして、クライアント側では処理する内容を記録しておき、オンラインになった時に再開できる仕組みにしておく必要があるでしょう。
CORS
Webアプリケーション向けにAPIを公開している場合、ドメインを越えたCORS問題が話題になります。無条件に解放してしまうと思いもしないサイトからアクセスが来る可能性があります。できれば適切に許可を出したいところです。
解決策としてはOAuth2を用いてアクセス元に対するパーミッションを適用することです。アプリケーションごとに公開ドメインを設定し、適切にフィルタリングできるようにしましょう。
APIを提供すると、通常のWebアプリケーションや業務システムではなかった問題に遭遇することがあります。APIらしい設計であったり、クライアント側とのデータ送受信方法を考える必要があるでしょう。