SlideShare a Scribd company logo
脱RESTful API設計手法の提案
株式会社ゆめみ 仲川樽八
はじめに
この資料は、アプリの開発にあたって、どの機能をアプリで提供し、どの機能はAPIサーバで提供
するべきか、そしてそのAPI設計の粒度をどうするべきかという問題に対する回答の一つを示すも
のです。
この資料においてはソーシャルゲームでの利用を例としています。
corporate data center
フロントアプリ
・ブラウザ APIサーバ
通信
RESTful APIがよく利用される
フロントアプリ
スタンドアロンゲームの構成要素(例)
グラフィック アニメーション サウンド
レベルアップ戦闘ルール 評価・報酬
シナリオ
ゲームシステム・基本ルール
演出
セーブ・ロード
全ての機能はフロントアプリに実装される
ソーシャルゲームになって構成要素が増えた
各種
マスタリソース 追加シナリオ
イベント配信
アカウント
引き継ぎ
会員登録
多端末
同時利用
運営から
アカウント凍結
アプリ上データ
アカウント関連機能
会員
セーブデータ
データ管理機能
各種ログ管理
フレンド
登録管理
(準)課金機能
その他運営機能
連続ログイン
報酬
課金管理
アイテム
ガチャ管理フレンド連携
報酬管理 報酬付与
グラフィック アニメーション サウンド
レベルアップ戦闘ルール 評価・報酬
シナリオ
ゲームシステム・基本ルール
演出
セーブ・ロード
どの機能をゲームサーバに持たせるか?どう利用させるか?
ほぼ全ての機能をサーバサイドに持たせるとほとんどWebアプリになり、
ゲーム性を損ないやすい。また、サーバ負荷が増える。
逆にほぼ全ての機能をフロントアプリに持たせるとチートがしやすくなる。
ぶっちゃけ、これが決まらないと
何も作れないよね。
原点に立ち戻って、
・ユーザーの要求
・アプリ開発者の要求
の両面から考える
ゲームなんだからレスポンスって重要だ。
対戦の命令を出したらあとは見てるだけのゲームより、ちゃ
んと操作出来るゲームで遊びたい。
バックエンドの能力に引きずられて待たされたり、止まっちゃ
うようなゲームなんて嫌だ。
ユーザーの欲求
→サーバAPIを使うことでゲーム体験の低下があるのは嫌だ。
(ブラウザゲームじゃちょっと、、、。)
アプリ開発側が、スタンドアローンゲーム開発で培ってきた
開発プロセスをできるだけ活かせるようにしたい。
ゲームロジックを持つAPIの実装をいちいち待たなくても開発
を継続できるようにしたい。
アプリ開発者の欲求
→サーバAPIを使うことで開発の邪魔をされなくない
・サーバAPIとしては単機能のものを複
数準備する。
・サーバ側は複雑なロジックを持たず
に、複雑なゲームロジックはフロントア
プリでサーバAPIを組み合わせながら
構築する。
・同一のHTTPリクエストの中で複数の
APIを同時実行できるようする。
サーバサイド設計者からの解決案の提示
実装してみた
命名:T8エンジン
ゲームサーバ
フロントアプリ
「アイテム購入API」を準備しないかわりに、
「課金アイテム消費API」
「アイテムGET API」
「現在の保有アイテム取得API」
を同時にコール出来るようにする。
T8エンジン 利用例
体力全回復 API課金アイテム消費API
アイテムGET API
現在の保有アイテム取得 API
会員データ更新 API
メッセージ送付 API
アイテム購入 API
×
その他、単機能のAPI
ロジックの多くがフロントアプリに寄ることによって、通信状
況やサーバの状況に巻き込まれてユーザー体験が損なわ
れる事が減る。
より、リッチで、インタラクティブなゲームをプレイできる。
ユーザーのメリット
・サーバ上のAPIの組み合わせによって、サーバ上のリソースに自由
にアクセスできる。
・仕様変更時もアプリ側の修正ですぐに対応可能。
・サーバサイドの実装を待たずに自由に開発を継続する事ができる。
・フロントにロジックがあるので、よりインタラクティブなゲームを自由
に構築する事ができる。
アプリ開発者のメリット
本音
• サーバ側でゲームロジックの実装をすると面倒くさい。
• インタラクティブなゲームとなるとより面倒な結合が増える。
• サーバの通信回数も負荷もできるだけ抑えたい。
• ロジックがフロントによると利用ユーザーが増えても、サーバの負
荷が増えにくいので負荷設計が楽。
• 要件がよくわかんないから、イベントに対する膨大な組み合わせの
APIの実装なんてやってられない。
ユーザーからの要望、アプリエンジニアから
の要望に対応しているように見えて、自分た
ちにとってハッピーな開発ができる。
ゲームサーバフロントアプリ
サーバ側はどうしてもサーバでやらないと
ならない部分の開発に注力できる。
各種
マスタリソース 追加シナリオ
イベント配信
アカウント
引き継ぎ
会員登録
多端末
同時利用
運営から
アカウント凍結
通信
アプリ上データ
アカウント関連機能
会員
セーブデータ
マスタデータ管理機能 データ管理機能
各種ログ管理
フレンド
登録管理
(準)課金機能
その他運営機能
連続ログイン
報酬
課金管理
アイテム
ガチャ管理フレンド連携
報酬管理 報酬付与
グラ
フィッ
ク
アニ
メー
ション
サウン
ド
レベル
アップ
戦闘
ルー
ル
評価・
報酬
シナリ
オ
ゲームシステム・基本ルール
演出
セー
ブ・
ロード
メリットだらけに見える
デメリットは?
デメリット
1. 複数のAPIを同時コールできるようにするために、インタフェイスが
RESTful APIでなくなる。
2. アプリや通信をクラックされた時にチートをされやすくなる。
デメリット1
複数のAPIを同時コールできるようにするために、
インタフェイスがRESTful APIでなくなる。
どうしてもRESTful APIである必要がある場合、間にプロクシサーバを立てる必要
がある。
同一のHTTP
リクエストで投げる
ゲームサーバ
フロントアプリケーション
プロクシサーバ
課金アイテムを消費して
アイテムをGETして、
現在のアイテムを取得する API
課金アイテムを消費して
アイテムをGETして、
現在のアイテムを取得したい
RESTful APIとし
て作る。 RESTful APIではない。
課金アイテム消費API
アイテムGET API
現在の保有アイテム取得 API
ただし、ゲームのようにそもそも複数のリソースに対する参照、更新の操作が必
要な時点でRESTful APIとして設計・構築することが難しい。
デメリット2
アプリや通信をクラックされた時にチートをされやすくなる。
チートを防ぐための努力は必要だが、それでもチートはされるものだと考える。
チートをされた際の影響範囲の洗い出しと評価が必要。
全体のポリシーとしては、他人のデータを操作出来るチートは一発アウトとします。
チーター本人のデータの書き換えまではある程度覚悟して、一部のユーザーの
チートが全体のバランスを崩さないようにするゲームデザインが必要となる。
複数のAPIの同時実行について
フロントアプリケーションでは、準備されたAPIのうちの任意のAPIを複数選んでロ
ジックを組み立て、それらを同一のトランザクション処理内で実行する事ができま
す。
それぞれのAPIは同一のトランザクション中で、指定された順番通りに実行されま
す。
体力全回復 API
課金アイテム消費API
100コイン使え
同一のHTTP
リクエストで投げる
保有コインから100コインを使ってゲームデータをセーブする
ついでにおまけアイテムも渡す。
コインが不足していたらその旨を通知してロールバックする
ゲームサーバフロントアプリケーション
アイテムGET API
現在の保有アイテム取得 API
ここで、トランザクション処理とは?
トランザクション処理とは?
DB等に対する複数の更新処理の一貫性を担保するための処理です。
いわゆるKVSにはこの処理ができないものも多いですので、組み合わせて利用する際には注意
が必要です。
ユーザーの所持金を100円減らせ
前の処理がOKだったら、ユーザーにアイテムを渡せ
←OK 減らしたよ
100円で復活アイテムを買う例
ここでクラッシュ
←OK 渡したよ
部分的な処理に失敗した時であっても、全てのデータを元通りに直してくれます。
部分的な処理の失敗はHW、ネットワークやミドルウエアの問題である事が多く、開発者が手を出
せないケースも多いですので、これは神のようなシステムです。(※開発者の責任だったとしても
ですが。。。)
ユーザーの所持金を100円減らせ
←OK 減らしたよ
100円で復活アイテムを買う例
ここでクラッシュ
課金もなかったコトに
しましょう!
前の処理がOKだったら、ユーザーにアイテムを渡せ
トランザクション処理が利用できないシステムだとどうなるか?
体力全回復 API
課金アイテム消費API
100コイン使え
API実行
ゲームサーバフロントアプリケーション
アイテムGET API
現在の保有アイテム取得 API
← OK
API実行
← OK
API実行
← OK
API実行
体力減らす API
課金アイテム戻すAPI
100コインAPI
API実行
途中で通信に失敗したら、それまでのAPI実行をキャ
ンセルする為のAPIをコールしなければならない。
→どこまで成功したかを把握する必要がある。
→キャンセルAPIも失敗する可能性がある。
無理ゲー…
もしNGだっ
たら?
キャンセルが
NGだったら?
リリース後の
・課金アイテムロストバグ
・アイテム無限増殖バグ
等の発生源となります。
大変盛況なため、予期しなかったバグが発生しています。
稼働させながらバグを直すので、皆様協力して下さい。
(2017年のとあるソシャゲ公式発表の要約)
この状態を回避するための代替ソリューションもありますが・・・
ゲームサーバ上に、
○コインを利用して
○体力を全回復して、
○おまけのアイテムをゲットして、
○その結果現在の保有アイテムを取得する
という全ての操作行うAPIを準備する。
・作らなければならないAPIの組み合わせが膨大すぎて死ねる。
・当然、テストも膨大になる。
・仕様変更に弱い。
デスマーチの予感!!
単一のデータソースにおける
トランザクション処理の担保方法
前提:
対象となるデータソースがトランザク
ション処理をサポートしている場合
try{
begin_transaction( Database1 );
データ処理1( Database1 );
データ処理2(Database1 );
データ処理3(Database1 );
commit_transaction(Database1 );
catch Exception(){
rollback(Database1)
}
単一のデータソースにおけるトランザクション処理の担保方法
→データ処理1~3のどこで失敗しても、commit_transaction([to Database1] )が実行されないかぎり、
どんなデータ処理を行ってもそれらはロールバックされる。(データ処理を行う前の状態に戻る)
※rollbackを記載していなくても、commitされない限り、rollbackされる
どんな例外でもとにかく元の状態に戻せ
トランザクション開始宣言
トランザクション終了宣言
複数のデータソースにまたがる
トランザクション処理の担保方法
try{
begin_transaction( Database1 );
データ処理1(Database1 );
begin_transaction( Database2 );
データ処理2( Database2 );
データ処理3( Database1 );
commit_transaction( Database2 );
commit_transaction(Database1 );
catch Exception(){
rollback( Database2)
rollback( Database1)
}
複数のデータソースにまたがるトランザクション処理の担保方法
→begin_transactionとcomimt_transactionを入れ子にすることで、全体をトランザク
ション処理することが可能。
トランザクション開始宣言
どんな例外でもとにかく全部もとに戻せ
トランザクション終了宣言
→複数のデータソースをまたがる事も可能なの
で、DBのシャーディング(水平分割)にも対応可能。
マスタDB ユーザーDB1 ユーザーDB2 ユーザーDB3
更新があったDBの
みcommit
更新があったDBの
みcommit
ユーザーDB4
トランザクション処理を担保しない
データソースに対する
トランザクション処理方法
一般的にトランザクション処理をサポートする
データソースの更新処理性能はそうでないデー
タソースと比較して低い事が多いため、高負荷を
前提とするシステムにおいては、トランザクション
処理をサポートしないKVS等のNoSQLを利用する
事も多い。
前提:
1. リードスルーキャッシュ
として利用している場合
try{
begin_transaction(Database1 );
データ処理1( Database1 );
データ処理2( Database1 );
データ処理3( KVS_Key1 );
commit_transaction( Database1 );
catch Exception(){
delete( KVS_Key1)
rollback( Database1)
}
複数のデータソースにまたがるトランザクション処理の担保方法
→ロールバック用のブロック中で、更新対象となったKVSのキーを削除すれば、次
回のリクエスト時に新たにデータが作成される。(疑似的なロールバック)
トランザクション開始宣言
更新対象となったデータを消す
トランザクション終了宣言
Database1に関しては更新前に戻す
→リードスルーキャッシュとしての範囲であれば、
NoSQL等を組み合わせることも可能。
2. 永続的なデータとして
利用している場合
単純に消せばいいというわけではなく、戻す先の状態を考えなければならないの
で、トランザクション担保は基本的に非常に難しい。
※元のデータを保存していても、ロック機構が無いことも多く、その状態に戻していいかどうかが
不明なため
高負荷時や、システムのエラー時における
・課金アイテムロストバグ
・アイテム無限増殖バグ
は避けられないので、せめてユーザーの不利益にはならない方向にシステムを
実装する。
※課金アイテム→通常アイテムの交換に関して言うと、先に通常アイテムを付与
してから、課金アイテムを減らすなどをする。
T8 エンジンの具体的なコール方法
HTTPリクエスト例
curl - -X POST "${HOST}/${VERSION}/gameapi" 
-H "Content-type: application/json" 
-d " ${JSON_BODY}";
→一般的なHTTPリクエスト方式
但し、リクエストメソッドは全部POST
JSON_BODY部分
{
“token” : “user_idとnonce, user_secret, 時刻等から生成した認証用token”,
“user_id” : “user_id”,
“nonce” : “ランダム文字列”,
“body” : [
{
“api_name” : “課金アイテム消費API”,
“api_id” : “課金アイテム消費API_01”,
“params” : {“use_num” : 100}
}, {
“api_name” : “アイテム付与API”,
“api_id” : “アイテム付与API_01”,
“params” : {“item_id”: 10, “num” : 5 }
}, {
“api_name” : “アイテム取得API”,
“api_id” : “アイテム取得API_01”,
“params” : {“item_id”: 10 }
}
]
}
※user_secretは予めサーバとアプリ
間で共有しておき、tokenを生成する
ために使用されるが、通信ではやり
取りされない。
※api_idはレスポンス中でapiを特定
するために利用するため、一意であ
れば何でも良い。
HTTPレスポンス例(成功例)
HTTP/1.1 200 OK
{
“result_code” : 1,
“results” : [
{
“api_id” : “課金アイテム消費API_01”,
“result” : {“result”:”OK”}
}, {
“api_id” : “アイテム付与API_01”,
“result” : {“result”: “OK” }
}, {
“api_id” : “アイテム取得API_01”,
“result” : {“result”: “OK”, {“item_id”:10, “num”:15} }
}
]
}
※個別のAPI毎の実行結果がリス
トで返答される。
HTTPレスポンス例(失敗例)
HTTP/1.1 400 BadRequest
{
“result_code” : 0,
“error” : {
“api_id” : “課金アイテム消費API_01”,
“err_code” : 1,
“msg” : “残金が不足しています。チャージして下さい。”
}
}
利用実績
・ソーシャルゲームアプリ
・クーポン、情報提供アプリ
・予約サイトAPI
など、ゲームだけでなく複数のアプリでの実績有り。
…気がついていないだけで使っていたかも?
結論
RESTful APIであることにこだわらなければ
みんな(主に開発者)がハッピーになれるかもしれません。

More Related Content

PDF
分散トレーシング技術について(Open tracingやjaeger)
PDF
REST API のコツ
PPTX
Redisの特徴と活用方法について
PDF
ストリーム処理を支えるキューイングシステムの選び方
PDF
例外設計における大罪
PDF
Dockerイメージの理解とコンテナのライフサイクル
PDF
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
PDF
RESTful Web アプリの設計レビューの話
分散トレーシング技術について(Open tracingやjaeger)
REST API のコツ
Redisの特徴と活用方法について
ストリーム処理を支えるキューイングシステムの選び方
例外設計における大罪
Dockerイメージの理解とコンテナのライフサイクル
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
RESTful Web アプリの設計レビューの話

What's hot (20)

PPTX
SPAセキュリティ入門~PHP Conference Japan 2021
PDF
DockerとPodmanの比較
PPTX
データ履歴管理のためのテンポラルデータモデルとReladomoの紹介 #jjug_ccc #ccc_g3
PDF
ゲームアーキテクチャパターン (Aurora Serverless / DynamoDB)
PDF
それはYAGNIか? それとも思考停止か?
PDF
「GraphDB徹底入門」〜構造や仕組み理解から使いどころ・種々のGraphDBの比較まで幅広く〜
PDF
Dockerからcontainerdへの移行
PPTX
本当は恐ろしい分散システムの話
PDF
マイクロにしすぎた結果がこれだよ!
PPTX
[社内勉強会]ELBとALBと数万スパイク負荷テスト
PDF
AWSのログ管理ベストプラクティス
PPTX
分散トレーシングAWS:X-Rayとの上手い付き合い方
PDF
TLS, HTTP/2演習
PDF
ドメイン駆動設計サンプルコードの徹底解説
PDF
Docker入門-基礎編 いまから始めるDocker管理【2nd Edition】
PDF
開発速度が速い #とは(LayerX社内資料)
PDF
macOSの仮想化技術について ~Virtualization-rs Rust bindings for virtualization.framework ~
PDF
Tackling Complexity
PDF
PostgreSQLアンチパターン
PDF
MagicOnion入門
SPAセキュリティ入門~PHP Conference Japan 2021
DockerとPodmanの比較
データ履歴管理のためのテンポラルデータモデルとReladomoの紹介 #jjug_ccc #ccc_g3
ゲームアーキテクチャパターン (Aurora Serverless / DynamoDB)
それはYAGNIか? それとも思考停止か?
「GraphDB徹底入門」〜構造や仕組み理解から使いどころ・種々のGraphDBの比較まで幅広く〜
Dockerからcontainerdへの移行
本当は恐ろしい分散システムの話
マイクロにしすぎた結果がこれだよ!
[社内勉強会]ELBとALBと数万スパイク負荷テスト
AWSのログ管理ベストプラクティス
分散トレーシングAWS:X-Rayとの上手い付き合い方
TLS, HTTP/2演習
ドメイン駆動設計サンプルコードの徹底解説
Docker入門-基礎編 いまから始めるDocker管理【2nd Edition】
開発速度が速い #とは(LayerX社内資料)
macOSの仮想化技術について ~Virtualization-rs Rust bindings for virtualization.framework ~
Tackling Complexity
PostgreSQLアンチパターン
MagicOnion入門
Ad

Viewers also liked (14)

PDF
失敗事例で学ぶ負荷試験
PDF
負荷試験入門公開資料 201611
PPTX
PayPal Reference Transaction APIをお財布ケータイぽく使ってみる
PDF
Resemaraを支えた技術 フライングゲットガチャの舞台裏 #ksgstudy #ドリコム
PDF
Webアプリケーションの パフォーマンス向上のコツ 概要編
PDF
Webアプリケーションの パフォーマンス向上のコツ 実践編
PPTX
デジタル・フォレンジックとOSS
PPTX
SQLまで使える高機能NoSQLであるCouchbase Serverの勉強会資料
PDF
こんなに使える!今どきのAPIドキュメンテーションツール
PDF
Rest ful api設計入門
PPTX
徳丸本に載っていないWebアプリケーションセキュリティ
PPTX
Webアプリケーション負荷試験実践入門
PDF
Swaggerでのapi開発よもやま話
PPTX
CSS2017キャンドルスターセッション
失敗事例で学ぶ負荷試験
負荷試験入門公開資料 201611
PayPal Reference Transaction APIをお財布ケータイぽく使ってみる
Resemaraを支えた技術 フライングゲットガチャの舞台裏 #ksgstudy #ドリコム
Webアプリケーションの パフォーマンス向上のコツ 概要編
Webアプリケーションの パフォーマンス向上のコツ 実践編
デジタル・フォレンジックとOSS
SQLまで使える高機能NoSQLであるCouchbase Serverの勉強会資料
こんなに使える!今どきのAPIドキュメンテーションツール
Rest ful api設計入門
徳丸本に載っていないWebアプリケーションセキュリティ
Webアプリケーション負荷試験実践入門
Swaggerでのapi開発よもやま話
CSS2017キャンドルスターセッション
Ad

Similar to 脱RESTful API設計の提案 (20)

PDF
20200708サーバーレスでのAPI管理の考え方
PPTX
技術選択とアーキテクトの役割
PPTX
Microsoft Azure Mobile Serviceによるアプリ構築
ODP
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
PPTX
【 ヒカ☆ラボ 】LIFULL Home's androidアプリの開発の裏側について
PPTX
RESTful Web API Design
PDF
RESTfulとは
PDF
私たちは何を Web っぽいと感じているのか
PDF
CloudSpiral 2014年度 Webアプリ講義(1日目)
PDF
FFRKを支えるWebアプリケーションフレームワークの技術
PDF
Building Scalable Application on the Cloud
PPTX
JSUG SpringOnePlatform 2016報告会 Case study2 - feed back - springoneplatform
PDF
Approach of Prototyping for making Application User Interface about iOS
PDF
Goji とレイヤ化アーキテクチャ
PDF
Signs;Gate - RESTfulなサイトの作り方 (Gunma.web #6 2011/09/03)
PDF
Typesafe Reactive Platformで作るReactive System
PDF
デブサミ2010 これからのアーキテクチャを見通す
PDF
社内システムの構造と設計、実装のはなし(下書きバージョン)
PDF
[AC11] サーバー管理よ、サヨウナラ。サーバーレスアーキテクチャの意義と実践
PPTX
爆速フレームワークでREST APIを作った話
20200708サーバーレスでのAPI管理の考え方
技術選択とアーキテクトの役割
Microsoft Azure Mobile Serviceによるアプリ構築
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
【 ヒカ☆ラボ 】LIFULL Home's androidアプリの開発の裏側について
RESTful Web API Design
RESTfulとは
私たちは何を Web っぽいと感じているのか
CloudSpiral 2014年度 Webアプリ講義(1日目)
FFRKを支えるWebアプリケーションフレームワークの技術
Building Scalable Application on the Cloud
JSUG SpringOnePlatform 2016報告会 Case study2 - feed back - springoneplatform
Approach of Prototyping for making Application User Interface about iOS
Goji とレイヤ化アーキテクチャ
Signs;Gate - RESTfulなサイトの作り方 (Gunma.web #6 2011/09/03)
Typesafe Reactive Platformで作るReactive System
デブサミ2010 これからのアーキテクチャを見通す
社内システムの構造と設計、実装のはなし(下書きバージョン)
[AC11] サーバー管理よ、サヨウナラ。サーバーレスアーキテクチャの意義と実践
爆速フレームワークでREST APIを作った話

脱RESTful API設計の提案

Editor's Notes

  • #25: HTTPリクエストの数も減るし一石二鳥
  • #26: ALL or Nothing
  • #27: ALL or Nothing
  • #28: ALL or Nothing