| @技術/プログラミング
CloudFront 転送量削減の試みで色々やっていて、そういやウェブサイトのキャッシュについての説明記事っぽいの読んだことないし、開発現場だと「じゃあキャッシュすればいいじゃん」みたいな発言が...

キャッシュ

CloudFront 転送量削減の試みで色々やっていて、そういやウェブサイトのキャッシュについての説明記事っぽいの読んだことないし、開発現場だと「じゃあキャッシュすればいいじゃん」みたいな発言が行き交うけど、ひとくちにキャッシュと言っても色々あって、ウェブ開発始めたばかりの人にはよく分からないんじゃないかと思ったので書いておきます。

キャッシュの目的

キャッシュの目的.png

キャッシュの目的は大きく二つあって、コンテンツ表示の高速化とコストの削減がある。コンテンツの表示高速化は、時間のかかる処理の結果を捨てずに再利用して二回目以降の表示を高速化すること、コストの削減は、処理結果の再利用によってコンピューターの利用時間を減らしたり、データの通信量を減らすことをそれぞれ目的としている。表示高速化とコスト削減はどちらか一方だけを達成するものではなく、多くの場合で両方が同時に実現される。

キャッシュに向いているコンテンツ

キャッシュには向いているコンテンツと向いていないコンテンツがある。

キャッシュに向いているコンテンツ.png

ウェブサイトで配信するものに関して何でもキャッシュできるわけではなく、多くの人が共通して閲覧するものか、更新頻度が低いものでないとキャッシュしてはいけない。更新頻度が低くて多くの人が共通して閲覧するもの(画像、 CSS 、 JavaScript など)はキャッシュしやすい。だがショッピングサイトの購入履歴などは人それぞれなので一律にキャッシュしてはいけない。

キャッシュの種類

キャッシュにはブラウザーキャッシュとサーバーサイドのキャッシュがある。

キャッシュの種類.png

ブラウザーキャッシュ

ブラウザーキャッシュは、同じ人が繰り返し訪問するサイトで繰り返し利用されるサイト内画像や JavaScript 、 CSS (静的コンテンツ)に対して提供するのに向いている。二回目以降のアクセス時に前回端末にダウンロードした内容を使い回し、転送量を削減してユーザーの閲覧体験を高速化する。

ブラウザーキャッシュ図解.png

同じ人が繰り返し訪問しないタイプのサイト( SNS でバズって多くの人が訪れるが、一ページ見ただけで離脱するようなサイト)ではブラウザーキャッシュをフルに効かせても転送量の削減効果はない。逆に一度訪れた人が何度も訪れるような再訪率の高いウェブサイトでは、静的コンテンツに対して Cache-Control ヘッダーを付与することでブラウザーキャッシュを効かせ、転送量の削減とコンテンツの表示速度を高速化させることができる。

ブラウザーキャッシュを聞かせるには、適切な HTTP ヘッダー( Cache-Control ヘッダーなど)を付けてレスポンスを返せばよい。

サーバーサイドキャッシュ

サーバーサイドでキャッシュできるのは多くの人が共通して閲覧する、更新頻度の低いデータだけということに注意が必要。ログインが必要なサイトで、アクセスする人によってコンテンツを出しわけないといけないようなシステムではサーバーサイドのキャッシュはあまり利用できない。

サーバーサイドキャッシュ図解.png

サーバーサイドのキャッシュには転送量の削減効果はない(少なくとも自サイト訪問者との通信では)が、ランキング集計処理や外部 API の呼び出しなど CPU への負荷や時間がかかる処理の結果をキャッシュし、コンテンツの表示を高速化したいときに有効。

例えばこのサイトでは Amazon のアフィリエイトを利用しているが、 Amazon の API にリクエスト回数制限やリクエスト間隔制限があるので適度にキャッシュを行い、リクエスト回数制限に引っかからないようにしている。

サーバーサイドのキャッシュのやり方は色々ある。アプリケーションにキャッシュするためのコードを書いてメモリ上に保持したり、テキストファイルに保存したり、データベースに保存したり、 Redis などを使ったり。ウェブサーバーのキャッシュを使う方法もある。このブログでもいくつかのキャッシュ機構を組み合わせている。

アプリケーションキャッシュ.png

表示に関わる部分の一部をキャッシュする場合や、キャッシュの無効化をアプリケーションでコントロールしたい場合はアプリケーションでキャッシュする必要がある。

ウェブサーバーキャッシュ

レスポンス全体をキャッシュしてよい場合にはウェブサーバーのキャッシュを使うとよい。その方がアプリケーション層までリクエストが届かず、コンピューターリソースを節約できる。

様々なキャッシュの組み合わせ

更新頻度が低く、多くの人が共通して閲覧するコンテンツはサーバーサイドでもキャッシュできるしブラウザーキャッシュを効かせることができる。画像、 CSS 、 JavaScript などがそれで、これらのファイルはよく CDN ( Content Delivery Network )から配信される。 AWS だと CloudFront というのがある。この手のサービスはサーバーサイドのキャッシュとブラウザーキャッシュを効かせることに特化したもので、コンテンツの転送量を抑えつつウェブサイトの表示速度を高速化してくれる。

CDN もそうだが、サーバーサイドキャッシュとブラウザーキャッシュを併用すると、コンテンツを更新したいときに問題が出てくる。画像ファイルを新しいものに差し替えたが CSS が更新されず古いキャッシュが参照され、画像が非表示になってしまったり、ということが発生する。そういうことが起こらないように、 HTTP にはいくつか仕組みがある。

CDN だと ETag も自動付与してくれて、コンテンツの衝突を抑えてくれる。 CDN はよくできているのでよく分からない人はまずは CloudFront を使って勉強してみるとよいだろう。

特に注意が必要なのがアプリケーションキャッシュとウェブサーバーキャッシュの組み合わせだ。異なるレイヤーでキャッシュを効かせてしまうと、キャッシュを無効化したいときに狙い通りに無効化されず、意図しない障害になってしまったりする。コンテンツの特性に応じて、キャッシュは一つのレイヤーで行うようにするとよいだろう。画像や CSS はウェブサーバーでキャッシュし、更新頻度が低いが動的に生成される JSON はアプリケーションレイヤーでキャッシュするなど。

まとめ

  • ウェブサイトのコンテンツは何でもキャッシュすれば良いわけでない
  • サーバーサイドのキャッシュとブラウザーキャッシュの違いを理解する
  • 多段キャッシュに注意(特にアプリケーションキャッシュとウェブサーバーキャッシュの併用)

| @Mac/iPhone
Mac や iOS 用カレンダーアプリの Fantastical が買い切り型のビジネスモデルからサブスクリプションに移行した。Fantastical 2 を買っていたユーザーは既存機能は無料で...

Mac や iOS 用カレンダーアプリの Fantastical が買い切り型のビジネスモデルからサブスクリプションに移行した。

Fantastical 2 を買っていたユーザーは既存機能は無料で使えるみたいだけど、 iPhone 上でカレンダーセットを複数使ったり、複数のカレンダーに存在する別のイベントを統合して表示する機能はサブスクリプションに登録しないと使えない。

サブスクリプション、よさげなビジネスモデルに見えるが、何でもサブスクリプションにすればよいというものではないと思う。サブスクリプションにすることで、ビジネス側にもユーザー側にもメリットがなければ意味がない。 Netflix や Amazon Prime 、 Adobe CC に関しては個別に買ったりレンタルしてたら膨大な金額がかかるものがサブスクリプションになることで月々の負担を抑えながら利用でき、その結果ユーザー数が増えることでビジネスサイド、ユーザーサイドの両方にメリットがある。一方で、もともと 5000 円程度の買い切りソフトウェアが月額 600 円のサブスクリプションに移行しても既存ユーザーにとっては値上げでしかなく、 5000 円の買い切り価格に逡巡していたユーザーが加入する後押しにもならないのでパイが拡大しない。誰にとってもメリットがない。こういうのは本当に無駄なのでやめてほしい。

| @ブログ
一つ前の記事で結構 Feed Crawler からのアクセスが多いことがわかった。フィードは PubSubHubbub で利用する都合上、キャッシュしていない。しかもいまは 20 件記事を配信し...

一つ前の記事で結構 Feed Crawler からのアクセスが多いことがわかった。

フィードは PubSubHubbub で利用する都合上、キャッシュしていない。しかもいまは 20 件記事を配信しているのでレスポンスが遅い。平均で 4 秒くらいかかっている。何とか効率的にキャッシュできないものかと思って FeedBurner を試してみることにした(サービス終了したかと思っていたけど、 .jp ドメインは終了しているものの .com の方は Google の中のサービスとして生き残っていた)。

FeedBurner からのアクセスの時だけ動的にフィードを生成し、それ以外の UA からのアクセスのときは FeedBurner の URL にリダイレクトするようにしてある。この記事を公開してちゃんと機能しているか確認したい。

追記

PubSubHubbub が機能しなくなってしまった😰 Googlebot に対しても動的なフィードを読ませないといけないのかもしれない…

| @ブログ
このブログのフィードを誰が読みに来ているのか調べてみた。一ヶ月間で 100 回以上見に来ている上位の UA は以下。なんと一位はフィードリーダーの bot ではなく Slackbot だった。 ...

今宿駅近くのバー

このブログのフィードを誰が読みに来ているのか調べてみた。一ヶ月間で 100 回以上見に来ている上位の UA は以下。

Feed Crawler Ranking

なんと一位はフィードリーダーの bot ではなく Slackbot だった。 Googlebot よりも多い。もはや Slack が一番のフィードリーダーになっているのかもしれない。こうなると PubSubHubbub とかの仕組みに乗っかって無駄なクローリングが発生しないようにして欲しい。フィードを購読する Slack の Workspace が増えるほどクローリング回数が増えてしまうと負荷がバカにならない。

三番目の Hatena::Russia::Crawler/0.01 ってのは Hatena と名前に入っているが本当にはてなのクローラーなのだろうか。 Russia という文字列が怪しい。

Feedly はもっと多いかと思ったが非常に少なかった。意外と Fastladder が多い。みんなどこかのサーバーで運用しているのだろう。ご苦労様です。

今回、ログを調べていて Feedeen といったサービスが存在していることを初めて知った。他に Feedbin などいくつか有料の RSS リーダーが存在しているようだ。 Google Reader や Livedoor Reader が終了した後、国内外で有料のフィードリーダーが開発されサービス提供されているのだろう。 Feedeen は料金が月 200 円で安い。日本人が作っているというのも安心感がある。自分は Google Reader 終了後はまず The Old Reader を使っていたけどいまは Inoreader を使っている。 Inoreader も開発元はルーマニアのインディー感あふれる会社で、フィードリーダーの世界は独立系の企業やデベロッパーによって活況を呈しているようだ。よいことだと思う。昔のインターネットを思い出す。

ちなみにフィードリーダー系の Crawler は UA にそのフィードの購読者数を表示しているのがおもしろい。こんだけ購読者数がいるんですよ、ということをブログ主に伝えて UA でブロックされないようにしているのだろう。

| @技術/プログラミング
Amazon Product Advertising API ( PA API )が 5.0 になるらしい。 4.0 は 3 月で廃止になるそうだ(当初は 2 月 11 日と言われていたが、 3...

DSC_4022.jpeg

Amazon Product Advertising API ( PA API )が 5.0 になるらしい。 4.0 は 3 月で廃止になるそうだ(当初は 2 月 11 日と言われていたが、 3 月まで伸びたみたい)。

最近 4.0 に対応させたのにな、と思って調べてみたら何と 4.0 対応したのは 10 年以上前だった。

PA API 4.0 までは AWS アカウントで利用する感じ1だったが、 PA API 5.0 では AWS から独立して Product Advertising API 専用のアカウントを登録しなければならないようだ。

AWS は US Amazon でアカウントを作るのに PA API のレポート画面へのログインでは Amazon Japan のアカウントを使うのは変だなと思っていたけど、 PA API 専用アカウントを設けることでその辺のねじれも解消されるだろう。

クライアントライブラリにはこれまで ecs という gem を使ってきたが、 PA API 5.0 対応はされてなくて、別の人が作った vacuum という gem に乗り換えた。

ecs という gem の名前に違和感をもつ人がいるかもしれない。いまでは Amazon で ECS といえば AWS の ECS ( Elastic Container Service ) のことを指すが、昔は Amazon 自身が PA API という名前ではなく Amazon ECS という名前でアフィリエイト用のシステムを提供していた。 Amazon は命名が色々紛らわしい。

PA API 5.0 は RESTful API ではなく GraphQL のような感じで、欲しいフィールド名を指定して API リクエストする感じになっている。レスポンスのサイズが小さくなって便利になった。

ちなみに移行ガイドは以下にあります。

DSC_4119.jpeg


  1. 10 年前にペパボの面接を受けに行ったときに「 AWS 使えますか?」と聞かれて「はい、使えます。アフィリエイトで小銭を稼いでいます」と答えてしまった。