サマリー
Microservices with Clojureより。前回はマイクロサービスアーキテクチャの概要について述べた。今回はマイクロサービスのためのRESTのAPI概要について述べる。
REST概要
RESTはrepresentational state transferの略で、分散型ハイパーメディアシステムのアーキテクチャスタイルを定義している。RESTは、ステートレスで拡張性の高い、独立したコンポーネント実装を作成することに重点を置いている。RESTをサポートするアプリケーションは、クライアントの状態に関する情報をサーバー側に一切保存しない。このようなアプリケーションでは、クライアント自身がステートを維持し、アプリケーションによって公開されるHTTP APIなどのRESTスタイルの実装を使用して、クライアントとサーバーの間でステートを転送する必要がある。REST APIを利用するクライアントは、サーバーに最新の状態を問い合わせ、クライアント側で同じ状態を表現することで、クライアントとサーバーを同期させることができる。
アプリケーションの状態は、システムのエンティティの状態によって定義される。エンティティは、RESTアーキテクチャにおけるリソースの概念と関連づけることができる。リソースは、RESTにおける情報の重要な抽象化である。これは、リソース識別子によって定義されるエンティティの集合への概念的なマッピングとなる。RESTのリソース識別子に名前を付けられる、またはその対象となる情報はすべてリソースとなり得る。例えば、コンシューマはサービス・コンシューマ・サービスのリソースであり、オーダーはオーダー・サービスのリソースである。
RESTにおけるリソース識別子は、HTTP URIにマッピングされたAPIエンドポイントとして定義される。URIは1つまたは複数のリソースを指し、前の画像に示すように、呼び出し側がリソースに対して操作を実行することを可能する。RESTがサポートするすべての操作はステートレスであり、クライアントの状態はサーバー側には一切保存されない。REST APIのステートレスな性質は、共有状態に依存せずに水平方向にスケールするサービスを作成するのに役立つ。
RESTスタイルは、直接通信を行い、エンティティにアクセスするための同期型APIを構築するマイクロサービスに適している。マイクロサービスによって管理される各エンティティは、RESTのリソースの概念に直接マッピングすることができる。
RESTの概念は、Roy Fieldingが2000年に「Architectural Styles and the Design of Network-based Software Architectures」という博士論文の一部として定義した(https://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation_2up.pdf)。RESTfulなシステムは、クライアントサーバー、ステートレス、キャッシュ可能性、レイヤーシステム、コードオンデマンド、統一インターフェースの6つの指導原則(https://en.wikipedia.org/wiki/ Representational_state_transfer#Architectural_constraints )に準拠している。
RESTful API
RESTアーキテクチャに準拠したWebサービスAPIはRESTful APIと呼ばれる。マイクロサービスの多くは、ステートレスで、リソースの表現にベースURIとメディアタイプ(https://en.wikipedia.org/wiki/Media_type)を持つ、HTTPベースのRESTful APIを実装しています。また、GET、POST、PUT、DELETEなどのHTTPメソッドにマッピングされた定義済みの標準的なオペレーションをサポートしている。
例えば、次の表に示すように、Order サービスではAPI /orders を定義し、保持しているオーダーにアクセスできるようにする。これは、すべての注文を検索したり、注文IDを指定して特定の注文を取得するためのGETメソッドをサポートすることができる。また、クライアントがPOSTメソッドを使用して新しいオーダーを作成したり、PUTメソッドを使用して特定のIDを持つオーダーを作成することもできる。同様に、注文の詳細を更新するためのPUTメソッドや、注文IDを明示的に指定して注文を削除するためのDELETEメソッドもサポートすることができる。
GET、PUT、POST、DELETEは、RESTful APIで最も広く使われているHTTPメソッドとなる。その他のメソッドとしては、HEAD、OPTIONS、PATCH、TRACE、CONNECTがある(https://en. wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods )。URIに送信された各リクエストは、HTML、JSON、XML、または任意の定義されたフォーマットである可能性がある応答を生成する。JSONは、アプリケーションのコア操作を処理するマイクロサービスにとって好ましい形式となる。例えば、OrderサービスのRESTful APIによって生成されるレスポンスは、注文詳細のJSONオブジェクトまたは注文のJSON配列を含み、各注文は注文詳細を含むキー-値ペアのJSONオブジェクトとして表現される。
Status codes
ステータスコードは、クライアントがリクエストの結果を理解し、レスポンスに対して必要なアクションを取るために重要となる。成功したリクエストは必要なリソースを表現したレスポンスを返すが、失敗したリクエストは代わりにエラーを表現したレスポンスを生成する。ステータスコードは、クライアントがレスポンスの内容をよく理解し、クライアント側で必要なアクションを起こすのに役立つ。
RESTful APIを持つすべてのマイクロサービスは、適切なHTTPステータスコード(https:/ /ja.wikipedia.org/wiki/List_of_HTTP_status_codes)をサポートし、要求した操作の結果に基づいてクライアントに送信しなければならない。マイクロサービスのすべてのAPIで実装する必要があるステータスコードの一部を以下に示す。
REST API では、上記のステータスコードを実装する必要がある。その他のステータスコードもAPIで使用される場合がある。定義されているすべてのステータスコードを確認するには、HTTPステータスコードガイドを参照のこと。
Naming conventions
REST APIは、システムのリソースを中心に構成され、URIを見ただけで理解しやすいものでなければならない。URIは、HTTPリクエストメソッドにマッピングされたオペレーションで、一度に1つのリソースタイプに焦点を当てなければならない。URIには、さらに入れ子にできる1つまたは複数の関連リソースを持つことができる。
URIの良い例は、/users、/consumers、/orders、/servicesであり、/getusers、/showordersなどではない。API URIを定義する際の基本的なルールは、名詞をリソース、動詞をHTTPメソッドとして対象とすることとなる。たとえば、/getusersというURIを作るのではなく、/usersというURIを用意し、HTTPメソッドをGETとすることが推奨される。同様に、/showordersの代わりに、レスポンスに含まれるすべての注文をクライアントに提供するために、URI GET /ordersを作成する必要がある。URIの命名に関するガイドラインは、次の図でさらに説明されている。
すべてのAPIでHTTPSベースのURIのみを使用し、常にSSL(https://en.wikipedia.org/wiki/Transport_Layer_ Security)を使用することが推奨されている。既存のサービスとの連携を崩すことなく、APIを随時バージョンアップしていくためには、APIのバージョン管理が必要となる。API のバージョンを指定するために、すべての API エンドポイントのプレフィックスとしてメジャーバージョンを使用することができる。サブバージョンはURIに追加してはいけない。必要であれば、カスタムヘッダーパラメーターを使用して指定することができる。
バージョンはメディアタイプで紹介することもできる。メディアタイプにサブバージョンを含めることは全く問題ない。バージョンはクライアントにとって破壊的な変更を含むかもしれないが、できるだけ後方互換性を保つことが推奨される。
URIには、対象となるコンポーネントや業務に応じてAPIエンドポイントを区分するアプリケーション修飾子も含まれることがある。各 URI は単一のリソースタイプに焦点を当てなければならず、その名前は複数形で使用されなければならない。指定されたタイプの特定のリソースを取得するためには、URIにIDを付加する必要がある。以下に、わかりやすい命名規則に従ったURIの例を示す。
Using RESTful APIs via cURL
cURL は、HTTP や HTTPS などのさまざまなプロトコルを使用してデータを転送するためのコマンドラインユーティリティとなる。cURL は、そのコマンドラインインタフェースを使用して RESTful API を試すのに広く使用されている。例えば、MetaWeather (https://www. metaweather.com/api/) が提供するAPIを利用して、ある場所に問い合わせ、その天気情報を取得する例を見てみる。これは有名な場所の天気情報を管理する公開APIなので、リソースの詳細を取得するためのGETリクエストのみを許可し、リソースの作成や更新は許可していない。
ある場所の天気を取得するために、MetaWeatherアプリケーションはシステムで定義されたリソースIDを必要とする。リソースIDを取得するために、MetaWeatherは検索クエリによってリソースを検索するための検索APIを提供している。検索APIは、リクエストのURLパラメータにクエリを指定してGETメソッドを使用し、ここに示すようにクエリにマッチするリソースをJSONレスポンスで返す。
% curl -XGET
"https://www.metaweather.com/api/location/search/?query=bangalore"
[{"title":"Bangalore","location_type":"City","woeid":2295420,"latt_long":"1
2.955800,77.620979"}]
レスポンスに含まれる woeid フィールドは、問い合わせた場所の天気の詳細を取得するために使用できる、天気 API が必要とするリソース ID である。
% curl -XGET "https://www.metaweather.com/api/location/2295420/"
{
"title": "Bangalore",
"location_type": "City",
"woeid": 2295420,
"latt_long": "12.955800,77.620979",
"timezone": "Asia/Kolkata",
"time": "2017-10-24T21:06:34.146240+05:30",
"sun_rise": "2017-10-24T06:11:13.036505+05:30",
"sun_set": "2017-10-24T17:56:02.483163+05:30",
"timezone_name": "LMT",
"parent": {
"title": "India",
"location_type": "Country",
"woeid": 23424848,
"latt_long": "21.786600,82.794762"
},
"consolidated_weather": [
{
"id": 6004071454474240,
"weather_state_name": "Heavy Cloud",
"weather_state_abbr": "hc",
"wind_direction_compass": "NE",
"created": "2017-10-24T15:10:08.268840Z",
"applicable_date": "2017-10-24",
"min_temp": 18.458000000000002,
"max_temp": 29.392000000000003,
"the_temp": 30.0,
"wind_speed": 1.9876466767411649,
"wind_direction": 51.745585344396069,
"air_pressure": 969.60500000000002,
"humidity": 63,
"visibility": 11.150816730295077, "predictability": 71
},
... ],
"sources": [
{
"title": "BBC",
"slug": "bbc",
"url": "http://www.bbc.co.uk/weather/",
"crawl_rate": 180
},
... ]
}
MetaWeatherアプリケーションAPIは、APIの詳細を調べるために使用できるOPTIONSメソッドもサポートしている。例えば、同じ検索APIにOPTIONS HTTPメソッドでリクエストを送ると、必要な詳細がレスポンスで提供される。
% curl -XOPTIONS
"https://www.metaweather.com/api/location/search/?query=bangalore"
{"name":"Location
Search","description":"","renders":["application/json"],"parses":["applicat
ion/json","application/x-www-form-urlencoded","multipart/form-data"]}
また、MetaWeatherアプリケーションは、無効なリソースIDに対して、適切なステータスコードとメッセージをレスポンスで返す。
% curl -v -XGET "https://www.metaweather.com/api/location/0/"
...
* Trying 172.217.26.179...
* Connected to www.metaweather.com (172.217.26.179) port 443 (#0)
...
* compression: NULL
* ALPN, server accepted to use http/1.1
> GET /api/location/0/ HTTP/1.1
> Host: www.metaweather.com
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 404 Not Found
< x-xss-protection: 1; mode=block
< Content-Language: en
< x-content-type-options: nosniff
< strict-transport-security: max-age=2592000; includeSubDomains < Vary: Accept-Language, Cookie
< Allow: GET, HEAD, OPTIONS
< x-frame-options: DENY
< Content-Type: application/json
< X-Cloud-Trace-Context: 507eec2981a7028e50e596fcb651acb7;o=1 < Date: Tue, 24 Oct 2017 16:07:36 GMT
< Server: Google Frontend
< Content-Length: 23
<
* Connection #0 to host www.metaweather.com left intact {"detail":"Not found."}
Summary
ここでは、RESTの概念と、わかりやすい命名規則でRESTfulなAPIを設計する方法について述べた。また、またさまざまなリクエストメソッドとステータスコードについて、いつ何を使うのかについても述べ、最後に、Helping Hands アプリケーションを再確認し、マイクロサービス間でアプリケーションに必要とされる REST API をリストアップした。
次回では、Helping Handsアプリケーションのマイクロサービスを設計するために使用するPedestal (http:// pedestal.io/)というClojureフレームワークについて述べる。また、Pedestalは様々なマイクロサービス操作のためのREST APIを公開するために使用される。
次回は、Pedestalを利用したClojureによる具体的なマイクロサービスの為のREST APIの実装について述べる。
コメント