1. はじめに
1.1. この記事の目的
今日、多様なサービスがインターネットを経由して提供されています。サービスの仕様を検討する際に、ユーザーの位置情報に応じ、最寄りの店舗情報を提供したい、というようなケースは比較的多く存在しているのではないでしょうか。
これを実現するためには、ユーザーの位置情報(緯度、経度)、店舗の位置情報、そして最寄りの店舗を検索する機能が必要です。この記事ではAkamai EdgeWorkersを利用し、この機能を実現する方法を紹介します。
この仕組みは、例えば複数の店舗を持つ企業が、ユーザーの場所に基づき最寄りの店舗情報を応答する、といった場合などに役立てることができます。
なお、この仕組み自体は、Akamai TechDocsに掲載されているEdgeWorkers チュートリアルの1つである"Store locator"に記載があります。
1.2. この記事の対象読者
この記事の対象読者は以下を想定しています。
- ユーザーの位置情報に基づき異なるWebページや機能を提供する方法を模索されている方、もしくはそういった方法の提案を行う立場の方
- Akamai EdgeWorkersとAkamai配信設定を実装し検証可能な権限と環境をお持ちの方(必須ではありませんが、本記事を確認しながらご自身の検証環境でハンズオン頂くとより理解が深まる内容になっています)
2. Webシステム構成概要
2.1. Webシステム構成概要図
まず、今回紹介するAkamai Edgeworkersを利用したWebシステム構成の全体像を確認します。
2.2. 基本的な処理の流れ
エンドユーザーはまずAkamaiのCDN(正確にはEdge Server)に接続する構成になっています。
キャッシュできないコンテンツは、Akamai CDNを経由しOriginからコンテンツを取得します。
キャッシュ可能なコンテンツは、キャッシュがあればAkamai CDNよりコンテンツを取得します。
キャッシュがない場合やキャッシュの有効期限が切れている場合は、Akamai CDNを経由しOriginからコンテンツを取得します。
ここまではAkamaiのCDNを利用したごく一般的なWebシステムの処理の流れです。
2.3. ユーザーの位置情報に基づく処理の流れ
次にユーザーの位置情報に基づく処理の流れ、すなわちAkamai EdgeWorkersがユーザーの位置情報を判別しそれぞれに応じた店舗情報の応答を行う部分について確認していきます。
エンドユーザーから位置情報に基づく処理を行うURL(path)にリクエストが来ます。
Akamai CDNのEdgeWorkersコードが実行され、ユーザーの位置情報、具体的にはユーザーの緯度、経度情報を識別します。
一方、EdgeWorkersコード内には店舗の場所情報(緯度と経度を含む)も記述されています。
ユーザーの位置情報と店舗の所在地をもとに、最も近い場所にある店舗情報を検索します。
そして店舗情報の応答を返します。
このようにAkamai CDNによる一般的な処理とは異なり、Akamai EdgeWorkersがリクエスト内容を確認し、然るべきリダイレクト応答をするという処理となります。またこの処理に限定して言えばOriginシステムは必要ありません。
2.4. 実現できること
この仕組みにより、以下のようなことが実現されます。
- QueryParameterに記述した緯度、経度情報をInputに、最寄りの店舗情報を応答する(アメリカに店舗を持つウォルマートの店舗情報を利用する)
実際のサービスではユーザーの緯度、経度情報を取得する方法として、ブラウザの位置情報APIを利用する方式があげられます。
ユーザーが位置情報の提供を許可した場合は正確な位置情報を取得することができます。
この情報をQueryParameterに格納した店舗検索用URLへアクセスさせることで最寄りの店舗情報を応答できます。
今回のチュートリアルではブラウザの位置情報APIの実装箇所は省略し、その情報が取得できた前提でQueryParameterに緯度、経度情報を手動入力する形で進めます。
また、ユーザーが位置情報の提供を許可しない場合の対策として、ユーザーのIPベースで位置情報を概算する方法も簡単に紹介します。
加えて、ウォルマートの店舗情報を、東京の水飲み場情報にupdateする方法も簡単に紹介してみたいと思います。
3. EdgeWorkersとAkamai配信設定の実装方法
3.1. 前提構成
それでは実際に上記のAkamai EdgeWorkersの仕組みをWebシステム上に構築していきます。AkamaiのCDNを利用したWebシステムがすでに存在していることを前提とします。
この仕組みを実装するにあたりOriginシステム側に変更は必要ありません。AkamaiのCDNで利用している配信設定の変更作業と、EdgeWorkersの新規設定作成により実現可能となります。
3.2. EdgeWorkersの実装
3.2.1. EdgeWorker IDの作成
まずEdgeWorker IDを作成します。EdgeWorker IDとは、「あるAkamai EdgeWorkersのコードを実行するための実行環境」のようなイメージと捉えてください。実行したいコードごとにEdgeWorker IDを用意し、それぞれのコードをデプロイ/処理させます。この作成が終わった時の構成イメージは以下のとおりです。
EdgeWorker IDが作成されていますが、実行するためのコードがデプロイされていません。またAkamai CDN上でどの配信設定とも関連付いておらず、まだ利用されることはありません。
手順は以下のとおりです。
Akamai Control Center(以下ACC)にアクセスします。アクセスしたら左上の☰をクリックします。
次にCDN > EdgeWorkersリンクをクリックします。
Create EdgeWorker IDをクリックします。
ポップアップしたウィンドウにて必要事項を入力し、Create EdgeWorker IDボタンをクリックします。
(補足)
- Name: 任意の名前を入力します。将来複数のEdgeWorker IDを利用する際の識別性などを考慮します。
- Group: 自身の権限のあるグループの中から選択します。主に本EdgeWorker IDの管理をどのグループに属するユーザーにて実施するかという観点で選択します。
- Contact ID: 基本的に選択肢は1つしかないはずです。複数表示される場合はACC管理者に確認の上選択します。
- Resource tier: Dynamic ComputeとBasic Computeが選択可能です。それぞれリソースの制限が異なります。各リソースの制限はこちらより確認可能です。検証/ハンズオン目的であればBasic Computeでも問題ありません。(コストの違いについてはACC管理者に確認してください)
- Description: 必要に応じ入力します。(空欄でもOK)
3.2.2. EdgeWorkers コードの作成
次に先ほど作成した、EdgeWorker ID(実行環境)で実際に動作させるコードを作成します。この作成が終わった時の構成イメージは以下のとおりです。
EdgeWorker ID上のコードがありますが、まだAkamai CDN上でactiveな状態にありません。またAkamai CDN上でどの配信設定とも関連付いておらず、まだ利用されることはありません。
手順は以下のとおりです。
まずはじめに、GitとNode.jsがご自身の端末にインストールされていない場合はインストールします。
次に、以下のコマンドを実行しAkamai EdgeWorkersサンプルリポジトリからソースコードを複製します。
git clone https://github.com/akamai/edgeworkers-examples.git
上記コマンドにより、今回実装する店舗検索機能以外のサンプルコードも複製されます。そのため、店舗検索機能のディレクトリへ移動します。
cd edgeworkers-examples/edgecompute/examples/personalization/storelocator
以下のnpmコマンドより今回の機能に必要な依存関係をインストールします。
npm install
以下のnpmを使用してEdgeWorkersコードをビルドします。
npm run build
これによりコード(ACCにuploadする拡張子tgzのファイル)は以下に生成されます。
dist/storelocator.tgz
次に、ACCに戻り先ほど作成したEdgeWorker IDをクリックします。
ポップアップした画面にて、先ほど作成したstorelocator.tgzをDrag and dropします。
Drag and dropが完了したら、Create versionボタンをクリックします。
3.2.3. EdgeWorkers コードのStagingデプロイ
コードの作成(EdgeWorker IDにコードを登録する作業)が終わったら、Akamai CDN上で実行する準備をします。
具体的にはAkamai Staging ネットワークへのデプロイを行います。この作業が終わった時の構成イメージは以下のとおりです。
EdgeWorker ID上のコードがあり、Akamai CDNのStaging ネットワークでactiveな状態です。ただ、Akamai CDN上でどの配信設定とも関連付いておらず、まだ利用されることはありません。
ここで、Akamai Production / Staging ネットワークについて補足しておきます。Akamai Productionネットワークは本番用プラットフォームです。Akamai CDNを利用した際、エンドユーザーが利用する環境です。Akamai Stagingネットワークは試験用プラットフォームです。エンドユーザーが利用することはありません。特殊な方法でStagingネットワークのEdge ServerのIPを調べ、検証用端末のhostsファイルに手動登録することでアクセスが可能になります。設定方法の詳細はこちらの記事をご確認ください。
手順の解説に戻ります。
ACCに戻り、作成中のEdgeWorker IDのコードを作成したVersion(上記手順を実施している場合は0.1 ※画面キャプチャは1.0.0となっておりますが0.1に読み替えてください。)の右端Actionsリンクをクリックし、展開されるメニューよりActivate Versionをクリックします。
ポップアップする画面から、Stagingを選択し、Activate versionボタンをクリックします。(ボタンクリック後5分前後でStagingデプロイが完了します)
3.3. Akamai配信設定の実装
3.3.1. Akamai配信設定へのEdgeWorkers Behaviorの追加&Staging デプロイ
Akamai Stagingネットワークに、コードのデプロイが完了し、EdgeWorkersコードの実行準備が整いました。あとはAkamai CDNの配信設定とこのEdgeWorker IDを紐付けることで利用可能な構成に変更していきます。この作業が終わった時の構成イメージは以下のとおりです。
EdgeWorker ID上のコードがあり、Akamai CDNのStaging ネットワークでactiveな状態です。またAkamai CDN上の配信設定と関連付いており、利用可能な構成になっています(Akamai Stagingネットワーク限定)。
手順は以下のとおりです。
EdgeWorkersのコードを実行させたいhost名を持つ配信設定を開き、新規versionを作成します。
その上で以下のようなルールを作成します。作成後、この配信設定もAkamai Stagingネットワークに展開します。
(補足)
- ルール名: 任意の名前をつけます(以下例ではStoreLocatorという名前にしています)
- Criteria: EdgeWorkersのコードを実行させたい条件を設定します(以下例では、pathが/storelocatorだったら、という条件としています)
- Behaviors: EdgeWorkersビヘイビアを追加/有効化します。また作成したEdgeWorker IDと紐付けます)
3.4. 動作検証
EdgeWorkersのコードを実行し動作検証する準備が整いました。早速動作検証をしてみます。
以下のcurlコマンドを利用し、Akamai Stagingネットワークにて動作確認をしてみます。(Akamai Stagingネットワークについては、3.2.3.章参照)(緯度、経度は東京駅の情報を利用)
curl "https://[yourhostname]/storelocator?lat=35.6812362&lon=139.7645445" --connect-to ::[yourhostname].edgekey-staging.net -H "Pragma: akamai-x-ew-debug" -sD - -sD -
curlコマンドより、以下の結果が出力されます。
HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
Content-Length: 1608
Date: Mon, 26 Aug 2024 03:16:35 GMT
Connection: keep-alive
X-Akamai-EdgeWorker-onClientResponse-Info: ew=[EdgeWorker ID] v:[EdgeWokrer ID name]; status=UnimplementedEventHandler
X-Akamai-EdgeWorker-onClientRequest-Info: ew=[EdgeWorker ID] v0.1:[EdgeWokrer ID name]; status=Success
X-Akamai-Staging: ESSL
[
{
"distance": 3840.004235962559,
"location": {
"type": "node",
"id": 4219907189,
"lat": 21.3914495,
"lon": -158.0345534,
"tags": {
"addr:city": "Waipahu",
"addr:country": "US",
"addr:housenumber": "94-595",
"addr:postcode": "96797",
"addr:state": "HI",
"addr:street": "Kupuohi Street",
"brand": "Walmart",
"brand:wikidata": "Q483551",
"brand:wikipedia": "en:Walmart",
"name": "Walmart",
"opening_hours": "Mo-Su 05:00-01:00",
"operator": "Walmart",
"phone": "+1-808-688-0066",
"ref:walmart": "2314",
"shop": "department_store",
"website": "https://www.walmart.com/store/2314/waipahu-hi/whats-new"
}
}
},
{
"distance": 3854.0641309505672,
"location": {
"type": "node",
"id": 1475451307,
"lat": 21.2946963,
"lon": -157.8423653,
"tags": {
"addr:city": "Honolulu",
"addr:country": "US",
"addr:housenumber": "700",
"addr:postcode": "96814",
"addr:state": "HI",
"addr:street": "Keeaumoku Street",
"brand": "Walmart",
"brand:wikidata": "Q483551",
"brand:wikipedia": "en:Walmart",
"level": "1",
"name": "Walmart",
"opening_hours": "24/7",
"operator": "Walmart",
"phone": "+1-808-955-8441",
"ref:walmart": "3478",
"shop": "department_store",
"website": "https://www.walmart.com/store/3478/honolulu-hi/whats-new",
"wheelchair": "yes"
}
}
}
]
上記の結果より以下のことがわかります。
- X-Akamai-EdgeWorker-onClientRequest-Infoヘッダ: 実行されたEdgeWorker ID/version/name、そして実行statusが確認できます。
- X-Akamai-Stagingヘッダ: Akamai Stagingネットワークを利用している場合に表示されるヘッダです。Akamai Stagingネットワークに接続できていることが確認可能です。
- response body: ウォルマート店舗情報2件を確認可能です。ハワイにある店舗情報が表示され、確かに東京から最寄りの店舗情報が応答されていることが確認できます。
3.5. IPベースの位置情報でユーザーの所在地を概算する
次に、IPベースの位置情報でユーザーの所在地を概算する方法を試してみます。ユーザーが位置情報の提供を許可しない場合の対策の一つになります。
bundle.jsonを編集します。
{
"edgeworker-version": "0.2",
"description" : "Example"
}
main.jsを以下の通り編集します。
(省略)
- 変更前 -
export function onClientRequest (request) {
// Extract longitude and latitude from query string
const params = new URLSearchParams(request.query);
const lat = Number(params.get('lat'));
const lon = Number(params.get('lon'));
- 変更後 -
export function onClientRequest (request) {
// Extract longitude and latitude from edgescape data
const lat = request.userLocation.latitude;
const lon = request.userLocation.longitude;
以下のnpmを使用してEdgeWorkersコードをビルドします。
npm run build
※「default imported from external module 'url-search-params' but never used」のエラーは今回は無視します。
これによりコードは以下に生成されます。
dist/storelocator.tgz
上述の手順により、コードをAkamai Stagingネットワークに展開します。
展開が終わったら動作確認をしてみます。
ユーザーの位置情報が変わると、店舗情報は本当に変わるのでしょうか。
ACCには、様々な国からcurlコマンドを実行するためのtoolが用意されています。このツールを利用し、今回実現したい処理を検証してみます。
ACCにアクセスする前に、以下のdigコマンドにて、Akamai Stagingネットワーク上のEdge ServerのIPを調べておきます。(Akamai Stagingネットワークについては、3.2.3.章参照)
dig [yourhostname].edgekey-staging.net +short
次にACCにアクセスします。アクセスしたら左上の☰をクリックします。
次にSupport> Edgediagnosticsリンクをクリックします。
Request Content(CURL)リンクをクリックします。
URLにEdgeWorkersコードを実行するためのURLを入力します(例:https://[yourhostname]/storelocator)
Sourceには任意の場所を選択します。Newyorkを選択してみます。
Spoof to edge server IPには、digコマンドで事前に調べたAkamai StagingネットワークのEdge Server IPを入力します。
それ以外はdefaultのままで問題ありません。Submitボタンをクリックします。
Submitボタンを押すと、Curl結果が表示されます。
Downloadリンクよりresponse bodyを確認することが可能です。
response bodyの中身はNewyorkのウォルマート店舗情報となっており、最寄りの店舗が応答されていそうです。
[
{
"distance": 0.47465280411285565,
"location": {
"type": "node",
"id": 5491576146,
"lat": 40.7568576,
"lon": -73.9972051,
"tags": {
"addr:city": "New York",
"addr:housenumber": "455",
"addr:postcode": "10018",
"addr:state": "NY",
"addr:street": "West 37 St",
"amenity": "pharmacy",
"brand": "Walmart",
"brand:wikidata": "Q483551",
"brand:wikipedia": "en:Walmart",
"dispensing": "yes",
"healthcare": "pharmacy",
"name": "Walmart Pharmacy",
"operator": "Walmart",
"operator:wikidata": "Q483551",
"operator:wikipedia": "en:Walmart",
"phone": "212-643-63090"
}
}
},
{
"distance": 8.470166489478801,
"location": {
"type": "node",
"id": 6923937633,
"lat": 40.8619541,
"lon": -74.0626008,
"tags": {
"amenity": "pharmacy",
"brand": "Walmart",
"brand:wikidata": "Q483551",
"brand:wikipedia": "en:Walmart",
"dispensing": "yes",
"healthcare": "pharmacy",
"name": "Walmart Pharmacy"
}
}
}
]
アメリカの別の都市でも実行してみてください。
おそらく店舗情報の応答結果が違うものになると思います。
3.6. 東京の水飲み場情報への変更
最後に、アメリカのウォルマート店舗情報を、東京の水飲み場情報へ変更してみたいと思います。緯度、経度情報はQuery parameterより取得する方法に戻します。
bundle.jsonを編集します。
{
"edgeworker-version": "0.3",
"description" : "Example"
}
main.jsを編集します。(変更箇所のみ記載します)
(変更前)
export function onClientRequest (request) {
// Extract longitude and latitude from edgescape data
const lat = request.userLocation.latitude;
const lon = request.userLocation.longitude;
(変更後)
export function onClientRequest (request) {
// Extract longitude and latitude from query string
const params = new URLSearchParams(request.query);
const lat = Number(params.get('lat'));
const lon = Number(params.get('lon'));
次に、位置情報データの編集をしていきます。
その前に、東京都の水飲み場データを生成する必要があります。
まず、Overpass Turboにアクセスします。
以下のクエリを入力し実行します。
[out:json][timeout:2500];
{{geocodeArea:"Tokyo"}}->.searchArea;
(
node[amenity=drinking_water](area.searchArea);
);
out body;
>;
out skel qt;
これにより、東京都の水飲み場情報を取得することができました。
このデータをダウンロードします。画面左上部付近の「エクスポート」リンクをクリックし、
以下「Overpass API」ボタンよりjsonデータを出力します。
上記で出力させたjsonデータをdata/locations.jsonに差しかえます。
あとは同様な手順にてビルド、展開していきます。
以下のnpmを使用してEdgeWorkersコードをビルドします。
npm run build
これによりコードは以下に生成されます。
dist/storelocator.tgz
上述の手順により、コードをAkamai Stagingネットワークに展開します。
展開が終わったら動作確認をしてみます。
以下curlコマンドを実行します。(緯度、経度は東京駅の情報を利用)
curl "https://[yourhostname]/storelocator?lat=35.6812362&lon=139.7645445" --connect-to ::[yourhostname].edgekey-staging.net
結果は以下の通りです。
[
{
"distance": 0.3500820960504309,
"location": {
"type": "node",
"id": 7090615443,
"lat": 35.6831867,
"lon": 139.7587888,
"tags": {
"amenity": "drinking_water",
"man_made": "water_tap"
}
}
},
{
"distance": 0.37819929840839767,
"location": {
"type": "node",
"id": 4160585870,
"lat": 35.6758419,
"lon": 139.7634091,
"tags": {
"amenity": "drinking_water"
}
}
}
]%
緯度、経度情報しか含まれず、本当に最寄りの水飲み場が表示されているかわかりません。
地図情報サービスを利用し具体的な場所を確認すると東京駅最寄りの水飲み場が得られていることが確認できます。
東京駅以外の緯度、経度でも試してみてください。最寄りの水飲み場情報が得られるはずです。
3.7. 本番リリース
通常の開発作業においては、動作検証(機能テストやリグレッションテスト)が問題なく完了したらAkamai Productionネットワークにデプロイします。まず、EdgeWorker ID(今回作成したversion)をAkamai Productionネットワークにデプロイします(このタイミングでは本番サービスにユーザーの位置情報に基づく処理は適用されません)。
次に、Akamai配信設定をAkamai Productionネットワークにデプロイします。このタイミングでユーザーの位置情報に基づく処理が実サービスに適用されます。エンドユーザーも利用可能な構成になります。
4. さいごに
このように、Akamai EdgeWorkersを利用することで、ユーザーの位置情報に基づく処理を簡単に実装することが可能です。
また、Akamaiを利用しユーザーの位置情報に基づく処理を実現することで以下のメリットを得ることができます。
- ユーザーの近い場所で位置情報を判別し処理を実行できる(レイテンシー/処理速度の向上)
- Originシステムの負荷/コスト削減(Originシステムでユーザーの位置情報に基づく処理を実現した場合と比べて)
- Akamai CDN同様、インフラ運用の考慮は不要。(EdgeWorkersで動かすコードとAkamai配信設定の管理のみで良い)