まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:management

読売新聞社様主催のジャイアンツハッカソン、4月27日に決勝に残ったチームによる最終審査が行われました:
http://www.giants.jp/G/gnews/news_3910572.html

2016042801



ITを通じてファンと球団との距離を縮め、試合観戦などをより楽しむことができるようなアイデアを広く募集し、アイデアを詰め、短期間で開発し、その出来栄えや実用性、ビジネス性を競い合う、というコンテストでした。数多くの独創的なアイデアや製品が生まれましたが、その中でもコミュニケーションツールを活用して選手をより身近に感じてもらうサービスを発表した "TEAM PAAK" チームが最優秀賞に輝きました。TEAM PAAK の皆様、おめでとうございます。また同ハッカソンに参加された多くの皆様、データ提供や審査などに参加頂いた協賛企業の皆様、大変お疲れ様でした。

同ハッカソンではアイデアを実現するためのお手伝いとして、データスタジアム様や読売巨人軍様から各種データ(試合/打席/投球/選手のデータや画像、球団グッズの売上記録など)を提供いただき、ハッカソン内で利用させていただきました。日本アイ・ビー・エムはサムライインキュベート様と共同で同データをアプリケーションから利用できるよう、各種データを API 化し、クラウドサービス(SoftLayer & Bluemix)と合わせて参加チームに提供しました。この「各種データの API 化」という部分のお手伝いをしたこともあり、この部分を少し掘り下げて紹介させていただきます。

簡単にいうと、データを提供する側の都合と、データを活用したい側の都合をあわせるための場を提供させていただきました。試合の記録データは本来有料で企業に提供されているもので、このハッカソンでの利用に限り、参加チームへは無料で提供いただきました。画像データや売上記録については、これら自体は売りものではありませんが、権利関係などで本来は公開されていないものを含めて提供いただきました。データを使う側からすると、これらのデータを丸ごと(例えばファイルごと)入手できると嬉しいかもしれませんが、上記のような事情からそういった形での提供は望まれていないものでした。 ではどのようにこれらのデータを提供するか、というのが我々の課題でした。

その答が API 化して、参加チーム毎の利用状況を管理しながら提供するという方法でした。この点についてもう少し詳しく説明します。

まずは「API 化」です。API とは Application Platform Interface の略で、ここでは「ウェブを通じて実行できる関数」という意味で使っています。少しわかりやすく説明すると、例えば「○○年□月△日、巨人戦の1回表。最初の打者の第×球目の結果は?」のような条件を与えて問い合わせをすると、「ピッチャーは●●、打者は■■、0対0、ノーアウトランナーなし、カウント 0-1、外角のスライダーで空振りストライク」のような結果が返ってくる仕組みを REST API と呼ばれる手法で用意しました。

これらのデータそのものはデータスタジアム様や読売巨人軍様から提供いただいているものです。1球毎、1打席ごと、1試合ごとなど、粒度の異なるデータを1年ちょっと全試合分提供いただきましたが、そのデータファイルそのものが流出するリスクは回避したい(つまりデータファイルは参加者に渡したくない)という事情がありました。そのため、上記のような問い合わせ条件にあうデータを取得できるような仕組みをウェブ API として(IBM Cloud を通じて)提供させていただきました。


ではそのようなウェブ API の仕組みをどのようにして短期間で(2日程度で)用意したのか? この答は実は以外とシンプルで、以下の3つの仕組みを組み合わせただけでした:
(0) 提供いただいたデータを全てリレーショナルデータベースに格納
(1) StrongLoop LoopBack を使ってデータベースを丸ごと API 化し、ウェブを通じて読み書き更新削除検索といった REST API を自動生成
(2) API Management サービスを使って (1) で作った API のうち、検索(問い合わせ)の API だけをハッカソン参加者に公開


2016042801


まず準備段階 (0) として、提供いただいたデータはいわゆる「ファイル(オフィスファイル、画像ファイル、テキストファイル混在)」でした。このままでは利用や配布/提供が難しかったため、一旦リレーショナルデータベースなどに全データをロードしました。今回は IBM の SoftLayer クラウドのサーバーを使い、その中にデータベースエンジンを導入して、全データをまとめてロードしました(要するにデータベース化しました)。 技術的にはこれでこのデータベースに適宜アクセスできるような仕組みを用意すれば外部から検索したりできる、のですが、上述の理由からデータベース丸ごとでの提供をするわけにはいかない、という背景がありました。

次にこのデータベースを API 化しました(1)。IBM Bluemix でも提供されている StrongLoop LoopBack サーバーを使うと、各種データベースを指定するだけでその中身を読み書き更新するような REST API を自動生成してくれます。

また自動生成された API には削除したり更新したりできるものもありますが、今回のハッカソンではあくまで参照(問い合わせ) API だけを公開したい、という事情がありました(2)。作成した API をわざわざ無効にする、という方法もありますが、今回はこれも IBM Bluemix から提供されている API Management 機能を使って、実際には問い合わせの API だけを公開し、かつ利用状況も合わせてモニタリングできるような方法にしました。


なお、今回の API 生成で使ったこのような (0) (必要であれば)DB を準備、(1) API 化、(2) API を限定公開して監視 という3ステップについては、以前にこちらのブログエントリで詳しい手順を紹介しています。詳しい手順などはこちらを参照してください:
Bluemix だけで REST API を作成/公開/管理する


「API を用意する」と聞くと、ちと面倒そうな印象を受けるかもしれませんが、IBM Bluemix や SoftLayer 、そして これらから提供されている各種サービスを効率よく使うことで、面倒な作業を簡略化し、目的の API を(仕様書に相当するドキュメントごと)作って公開して管理する、といったことが簡単に実現できてしまいます。 もちろんデータベースの操作に慣れた方からすると、直接データベースを扱えた方が効率は良かったかもしれませんが、様々な事情を考慮した結果の1つの実現の形として、今回はこのような提供形態とさせていただきました。今回のジャイアンツハッカソンの成功を受け、「このやり方がある程度は正しかったのではないか」と思っています。もちろんまだ改良・改善の余地はあると思いますが、「データを取りまとめて API を提供する」という役割については一定レベルで果たせたのではないかと考えています。 そしてその作業は、上記のように(IBM クラウドを使うことで)結構簡単に実現できるものだと思っています。


IBM Bluemix だけの環境を使って、Web API を作り、公開して、更に API Management 機能を使って管理/監視する、というシステムを作ってみます。

これまでこのブログでも個別の機能を個別に紹介したりしていましたが、全てまとめたシステムを Bluemix 提供サービスだけを使って(外部サービスに頼らずに)行う、という前提条件で紹介します。もちろん実際には外部との連携も可能です、データベースは既存のものを使う、とかも可能、という意味です。


システム概要としての完成図は下図のような感じを想定します。まず格納するデータのデータベース(MySQL)と、その管理ツールとして phpMyAdmin(PHP ランタイム)を用意します。次にデータベース内のモデルを API として公開する LoopBack(Node.js ランタイム)。ここまでで CRUD の REST API ができますが、このサーバーは直接公開しません。加えてこの API を管理するため、API Management サービスでラッピングし、カスタム API を作って、これを利用者向けに公開します。それぞれ Bluemix 上のサービスアイコンと併せてのシステム図になっています:
2016020701


ではそれぞれのパーツを順に Bluemix 上に作っていきます。全部で3段階あります:

(1) MySQL と phpMyAdmin でデータベース環境を準備
2016020801

Bluemix 環境内に MySQL のデータベースサーバーを用意し、この中に API として管理するデータのモデル(テーブル)を作成します。MySQL の選択肢として ClearDB を使うこともできる(その場合は外部の MySQL コマンドラインクライアントから直接参照できる)のですが、今回はオープンソース版を使うことにします。オープンソース版では外部の MySQL コマンドラインクライアントからは参照できないので、テーブル定義のために PHP ランタイムと、そこで実行する phpMyAdmin の環境を構築します。そして phpMyAdmin から create table の SQL を実行して、モデルを作成します。

この Bluemix 環境内に MySQL データベースサーバーと phpMyAdmin アプリケーション環境を構築する際の手順についてはこちらで詳しく紹介しているので参照ください:
Bluemix で phpMyAdmin を動かす


(2) StrongLoop LoopBack で REST API 化

2016020802

StrongLoop LoopBack インスタンスを作り、先程作成した MySQL データベースをバインドして、モデルを CRUD 可能な REST API 化します。

StrongLoop 環境の構築方法や Bluemix ランタイムへのプッシュ方法、そしてデータベースとして MySQL を指定する場合の手順などは以下を参照ください:


ただし、この REST API はこのまま公開はしません。あくまでプライベートな REST API として作成し、公開する時は参照系 API のみ(GET リクエストの API のみ)を公開するようにします。


(3) API Management で公開する API を絞り、カスタム API 化して管理
2016020701

LoopBack で作成した REST API の参照系 API のみをプロキシー URL とするようなカスタム API を API Management サービスを使って作成し、このカスタム API を Bluemix ユーザー向けに公開します。

API Management サービスでカスタム API を作って公開する手順はこちらを参照ください。(2) で作成した LoopBack の REST API を、ここで公開するカスタム API のプロキシーとして利用するための手順です:
IBM Bluemix の API Management サービス



と、こんな感じ。特別に目新しい情報ではないのですが、Bluemix のランタイムやサービスを組み合わせるだけで負荷に合わせてオートスケールする API を生成し、かつその API の制御管理を行う、という仕組みが構築できました。





 

IBM Bluemix から SaaS で提供されている API Management サービスを使うと、普通に提供されている Web API に対して、その提供範囲を一部だけに限定(例えば GET/POST で提供されている API のうち、POST のものだけを公開)したり、認証機能を追加したり、(利用頻度や回数などの)アクセス制限をかけたり、API 利用状況をモニタリングする機能をラッピングする形で提供できるようになります。この辺りに関してはこちらのブログエントリにまとめているので参照ください:
IBM Bluemix の API Management サービス


この API Management サービスを使って既存の API をラッピングした場合、既存の Web API で指定していたURL パラメータやパスパラメータを、ラッピング後にどのように指定すればよいか?という疑問が生じます。その辺りについて調べてまとめてみました。結論としては「あまり意識せずに使える」ことになります。


例えば、既にこのような Web API が存在していたとします:{item_id} の部分に ID を指定して GET リクエストすることで、指定した ID のレコードを取得できる、というものです:
http://xx.xx.xx.xx/abc/items/{item_id}

実際にウェブブラウザでリクエストした例がこちらです。この例では 1 という {item_id} を指定して目的のレコードを取得していますが、この 1 の部分を適宜変えることで目的のレコードを変更することができるような API になっている、という前提です:
2016020701


このような Web API を API Management でラッピングする場合、この {item_id} というパスパラメータの存在をどのように指定すればよいか? というのが本ブログエントリの目的です。

結論はかなり簡単で、API を定義する際のパスにパラメータを {xxx} 形式で指定します。またその実装においてもプロキシー URL を指定する際に同じパラメータを使って指定します。

具体的には以下のような /get 関数を定義します。公開する API の形式を /get/{item_id} のように指定し、その実装のプロキシーURL において、 http://xx.xx.xx.xx/abc/items/{item_id} のようにそのまま指定するようにします。これで /get/ の後に1つパラメータを受け取って動くような挙動になっていることを指定したことになります:
2016020703



また、URL パラメータはラッピング API を作成する際には特に宣言しなくても、そのまま使えます。例えば以下の URL を GET リクエストすると、レコードの一覧が取得できるような API が存在していて、limit=XX の部分で取得レコード数を指定できるような仕様になっていると仮定します:
http://xx.xx.xx.xx/abc/items?limit=100

この Web API を API Management でラッピングする場合は、URL パラメータのことは意識せずに、そのまま API を定義できます。下の例では公開 API に /list というパスを指定し、その実装のプロキシー URL は http://xx.xx.xx.xx/abc/items (URL パラメータ部分を省略したもの)までをそのまま指定します。これで /list 関数も定義できました:
2016020704


このような指定方法で作成/公開したラッピングの API で、パスパラメータや URL パラメータを指定するには以下のようにします。まずは公開したラッピング API は Bluemix 内では「カスタム API 」として利用可能になっています(API Management で公開後に再ログインする必要があります)。まずはこのカスタム API を自分のランタイムにバインドしておきます:
2016020705


バインドが成功すると、ランタイム内のサービスにカスタム API が追加できているはずです:
2016020706


次にこの API を利用する際に必要な client_id と client_secret を確認します。メニューから「環境変数」を選び、このカスタム API を利用するための credentials 情報を確認します。そして url, client_id, client_secret の3つの値を確認してメモしておきます(この値はランタイムの環境変数 VCAP_SERVICES から参照できるので、アプリケーション内で動的に取得も可能です):
2016020707


では実際に API Management を使って公開された API をパラメータを付けて利用してみましょう。まずレコードの ID をパス内で指定してレコードを取得する API の場合は、その ID をそのまま URL の最後に指定してブラウザでアクセスします。なお API Management 管理下の API にアクセスするには client_id と client_secret の値が必要なので、上記の環境変数から取得したそれぞれの値をそれぞれ指定して、以下のようなアドレスにウェブブラウザでアクセスします(以下は {item_id} に 1 を指定した例です):
(環境変数の url の値)/get/1?client_id=(環境変数 client_id の値)&client_secret=(環境変数 client_secret の値)

すると、上記のラッピング前の Web API で実行した時と同じ結果を確認することができます。{item_id} の値を変更しても、正しい値が得られるはずです。これでパスパラメータについては API Management で管理できることがわかりました:
2016020708


もう1つの、URL パラメータを指定する例も確認してみます。今度も client_id と client_secret と、更に limit の値も含めて URL パラメータに指定して、以下の様なアドレスにアクセスします(以下は limit に 10 を指定した例です):
(環境変数の url の値)/list?client_id=(環境変数 client_id の値)&client_secret=(環境変数 client_secret の値)&limit=2

この場合もラッピング前の Web API で実行した時と同じ結果が確認できるはずです(limit の値を変更すると、指定した数を上限とする結果セットが得られるはずです)。URL パラメータについては特に何もしなくても API Management に引き継いで管理できることが確認できました:
2016020709


結論として、API Management でパラメータを使う場合は、以下の様な指定が必要です:
(1) URL パラメータの場合は、特に指定不要でそのまま
(2) パスパラメータの場合は、指定するパラメータを { } で括ったものを API 定義とプロキシー URL の両方に指定する





IBM Bluemix が提供するサービスの1つに "API Management" と呼ばれるものがあります:
2015090901


このサービスは少し特殊なものです。これ単体で何かのサービス機能を提供するものではなく、特定の組織やグループ向けに Bluemix 上で使える独自 API サービスを生成するためのサービスです。また、この API Management サービスを使って提供される API サービスに関しては、名前のとおりに利用状況を把握したり、利用制限をしたり、といった API の管理機能も利用できるようになります。


少し前に API を Bluemix の公式なサービスとして登録するための手順をこのブログで紹介しました:
API を Bluemix のサービスとして登録するには?

ここで紹介した内容はあくまで公式な Bluemix サービスとして、世界中の全 Bluemix ユーザーを対象に公開する API を登録するための手順を紹介しました。技術的な要件はもちろんですが、無料枠の準備なども含めて営業的なハードルもある内容であると思っています。

一方、今回紹介するこの API Management サービスを使った場合、特定の Bluemix ユーザーだけが対象になりますが、そのユーザーに対して、Bluemix 上の(いわば)プライベートサービスを公開して管理する、ということを目的としています。何のセキュリティもない素の REST API に認証機能を追加したり、利用制限をかけたり、利用状況を監視したりする、といったことを実現します。


ではこの API Management サービスを実際に使って独自 API を Bluemix 開発者向けにサービス提供し、Bluemix 上のアプリケーションから利用し、その利用状況を確認するまでの手順を以下に紹介します。API Management ではおおまかに2段階の手順を行う必要があります:
(1) API の定義
(2) API を公開する条件の設定


まず最初に、この API Management を利用して管理/公開する独自 API を用意します。開発者の方で、既に自分の API をお持ちであればそれを使っていただいても構いません。ここでは以下の公開された為替情報 API を使って一連の流れを紹介することにします:
http://fx.mybluemix.net/

2015090905


上記 URL にブラウザでアクセスするとわかるのですが、ほぼリアルタイムに20種類の為替情報が JSON フォーマットで得ることができる、という俺製の REST API です。ドメインを見ればわかるように Bluemix 上で(Liberty Java の 256MB メモリ1インスタンスで)動いているサービスですが、ここで登録するサービスは Bluemix の外のサービスでも構いません。

で、前提としては「この API を作ったけどまだ未公開で、これを Bluemix ユーザー向け API として公開/提供したい」とします。つまり上記 URL はサービスとしてはできていて、ここにアクセスすれば API としては動くんだけど、まだ管理できないから公開はしていない(誰もこの URL を知らない、或いは認証をかけている)状態であるとします。この API を Bluemix の API Management サービスを使って Bluemix の管理下で運用できるように公開する、というのが今回の目的です。


では、まずは Bluemix にログインして、この API Management サービスを追加します。ダッシュボードの「サービスまたは API の使用」をクリックします:
2015090901


サービスの一覧が表示されるので、「統合」カテゴリ内の "API Management" サービスをクリックします:
2015090902


API Management サービスの説明が表示されます。このサービスは特定のランタイムにバインドして使うものではなく、サービス単体で利用します。そのまま「使用」をクリックして、サービスインスタンスを作成します:
2015090903


サービスインスタンスが生成されると API Management 入門の画面が表示されます(ダッシュボードから作成済みの API Management サービスを選択してもこの画面になります)。この中の "API MANAGER に移動" ボタンをクリックして、サービス管理画面に移動します:
2015090904


サービス管理画面の初期状態の画面がこちらです。まだ API を1つも登録していないので何も表示されていませんが、登録 API があると、この画面から利用状況を確認することができるようになります:
2015090905


では早速先程の為替情報 API をここに新規登録してみます。画面左のメニュー上から3番目の API マークをクリックし、API ページ内の "+API" と書かれた箇所から「作成」を選択します:
2015090906


まずは API そのものの情報を指定します。「タイトル」と「基本パス」は必須入力です。「基本パス」とは、この後登録する API のベースとなる共通 URL パスです。ここでは "/fx" と指定しているので、実際に呼び出す API のエンドポイントは "/fx/****(?a=x&b=Y&...)" という形式になります。最後に「追加」ボタンをクリックします:
2015090907

(注 このタイトルは半角英数字で入力してください。日本語は使えますが、公開時に問題が発生します)



新規に API が追加され、指定した内容が画面に表示されます。続いて具体的な API エンドポイントを追加します。画面下部の「操作」タブから「+操作」をクリックします:
2015090901


今回は最新の為替情報を表示する API 1つを追加します。この例ではパスに "/status" と指定していますが、上記でベースパスとして "/fx" を指定しているので、この API は "/fx/status" というパスで呼び出すことになります。また今回の例では GET メソッドで情報を取り出すだけの API を用意するので、POST メソッドは不要です。POST の×印をクリックして POST メソッドを削除します(GET メソッドだけを残します)。最後に「追加」ボタンをクリックします:
2015090902


"/status" GET メソッドが追加されました。ではこの "/status" GET メソッドの具体的な内容を定義するため、編集ボタンをクリックします:
2015090903


"/status" の具体的な内容を定義する画面が表示されます。今回は http://fx.mybluemix.net/ を単純に呼び出した結果をこのメソッドの結果として定義するようにします。このような場合は「実装」タブの「プロキシー」を選択し、プロキシー URL に "http://fx.mybluemix.net/" を指定します。最後に画面右上の「保存」ボタンをクリックして、この変更内容を保存します:
2015090904


これで API の定義は完成しました。API Management サービスを使って API を公開するには、API 利用者が参照できるような公開プランを定義する必要があります。続いてこの API のための公開プランを作成します。メニューの上から2番目の「プラン」セクションを選択し、「+プラン」をクリックします:
2015090905


新規プランの作成ダイアログが表示されます。API のタイトル(この例では "FX")等を指定して「追加」ボタンをクリックします:
2015090906


"FX" プランが作成できました。このプランの中で許可するエンドポイントを追加するため、画面下部の「+操作」をクリックします:
2015090907


「操作の追加」ダイアログが表示されます。今回は "/status" GET メソッド1つだけしか用意していないので1つしか表示されませんが、このプランで公開したい操作にチェックを入れて「追加」ボタンをクリックします:
2015090908


"FX" プラン内に "/status" GET メソッドが追加されました。このまま使ってもいいのですが、折角なので管理っぽい機能を1つ追加してみましょう。このまま使うと利用制限なしに使えてしまいますが、1分間に利用できる呼び出し回数に制限を付けてみます。"/status" GET メソッド行のレート制限変更ボタンをクリックします:
2015090901


「レート制限」ダイアログが表示されます。ここで1分間に呼び出せる回数として "10" を指定して「適用」をクリックします:
2015090902


指定した内容にレート制限が変更されたことを確認します。これで "/status" GET メソッドには1分間に 10 回しか呼び出せない制約が付けられたことになります:
2015090903


ここまでの内容を Bluemix ユーザー向けに公開しますが、公開対象を変更する画面についても確認しておきます。画面左のメニュー上から5番目の「開発者」を選択します。デフォルト状態では自分と同じ Bluemix 組織に属しているユーザーに対してのみ、この API が公開されるような設定になっている点を確認します。他の組織や他のユーザーにこの API を公開する場合は、この画面から開発者を追加します:
2015090904


では、改めて今回作成した API を Bluemix ユーザーに公開します。画面左メニューから「プラン」を選び、公開するプラン(今回の例では "FX" )をクリックします:
2015090905


まずこのサービスを Sandbox 環境にステージングします。画面上部の「ステージ」ボタンをクリックします:
2015090906


ステージングに成功したことを確認します:
2015090907


続いて画面左メニューから「管理」画面を選び、ステージング状態になったサービスの歯車アイコンから「公開」を選択します:
2015090908


公開範囲を指定するダイアログが表示されるので、内容を確認して「公開」ボタンをクリックします:
2015090901


しばらく待つと「公開済み」ステータスに変更されます。これで定義した API が Bluemix 利用者(の自分と同じ組織に属しているユーザー)に公開されました:
2015090902


この状態で一度 Bluemix からログアウトして、ログインし直します:
2015090903


Bluemix に再ログインすると API Management で追加された FX サービスが「カスタムAPI」カテゴリに追加されている(見えるようになっている)はずです:
2015090901


もちろん、Bluemix 上に作ったランタイムのサービスとして追加することも可能です。試しに追加してみます:
2015090902


このカスタム API サービスを追加したランタイムの環境変数を見ると、この API を使うためのクレデンシャル情報を取得することができます:
2015090903


この内容は以下の様な内容になっています、この "credentials" として書かれた3つの内容は後で使うのでメモしておきます:
  :
  :
    "credentials": {
            "client_id": "(client_id の値)",
            "client_secret": "(client_secret の値)",
            "url": "(url の値)"
    }
  :
  :

この情報を使うと、目的の API にアクセスすることができます。例えば "/status" の情報にアクセスするにはウェブブラウザを使って、上記 "credentials" 情報に含まれる情報を使った以下の URL にアクセスしてみます:
  ("url" の値)/status?client_id=(client_id の値)&client_secret=(client_secret の値)

(パラメータとして client_id と client_secret の値を指定して呼び出す)
2015090904


当初の目的通りに、期待通りの API が、API Management サービスの管理下で(本来の URL を公開することなく)作成/実行できました。この API を使ったアプリケーションを開発して Bluemix 上で動かす、ということも可能ですが、制限を加えているので1分間に10回しか呼びさせないようになっているはずです。

また、Bluemix の API Management サービスのポータル画面を確認すると、この API の利用状況を確認することもできます:
2015090906


以上が API Management サービスの使い方についてひと通りの実践を紹介した形になります。既存の(或いはこれから作成する)ウェブサービスを管理して Bluemix サービスに統合するためのサービス、という位置付けであることがお分かりいただけるでしょうか?

興味ある方は是非実際にご自身でウェブサービス API を作って、上記の手順を試していただきたいと思います。自分が作った API の利用制限や認証、利用状況監視などを外付けで実現できるというのはなんとも不思議な気分です。 自分でウェブサービスを作るような立場でない方も、本エントリで紹介している為替 API を使って試してみていただいても構いません。ただ 256 MB メモリ×1インスタンスの比較的貧弱なサーバーで動かしているサービスなので、ご利用はお手柔らかに。。



このページのトップヘ