Cloudflareを導入してECサイトの負荷対策をした話・・・


# 導入の経緯
我がサイマでは2020年7月下旬に関東/関西でTVCMを放映することになりました。
サイマでは2年ぶりの試みであり、過去にない規模での放映ということもありこれまでにない数の流入が予想されました、CMをご覧になったお客様のサイトへの流入が殺到することを想定してWeb/DBサーバへの負荷を軽減することが求められます。

そこで白羽の矢が立ったのがCloudflareです。

# これまで
サイトの配信にCDNを利用しておりませんでした、このCM放映を機にサイト側もCDNを設けてサイト配信の効率化を図ります。
※画像ではAkamaiなどを利用しておりました。

# Cloudflareの導入にあたって
## その目的
最大の目的はCloudflareのCDNへサイトをキャッシュさせサイマのWeb/DBサーバへ処理を到達させる数を少なくすること、それによってサーバの高負荷を原因としたレスポンス遅延をなくすことです。

## 注意すべき点
サイマはRuby on Rails製のモノリシックなアプリケーションです、バックエンドの処理に基づいて作成しているコンテンツがありCDNにキャッシュさせるとユーザーに対して意図しない断面でサイトが配信されてしまいます。
キャッシュによる意図しないサイト配信でお客様へご迷惑がかからないように注意しなければなりません。

## 注意点の解決案
### キャッシュ化の棲み分け
主にキャッシュ対象とするページは個人情報を含むページとカートページ／決済ページなどを省いたページとしました。
元々PVが多いもしくはCMを視聴されてサイマに訪れる方はGoogleで「サイマ」などの検索から流入することが多いと予想されますのでそれを考慮に加えております。

- TOPページ
- 車種カテゴリページ
- 商品特集ページ
- 記事ページ

### Page Rulesによるキャッシュの設定
この棲み分けはCloudflareの`Page Rules`を利用して実現しました。

#### 動的コンテンツのキャッシュ
CloudflareはデフォルトだとimageやHTMLといった静的コンテンツしかキャッシュしないのでRailsなどで生成される動的コンテンツは別途キャッシュをさせるための設定が必要です。
特にRailsの場合だとデフォルトでresponseヘッダの`cache control`に`private`の設定を入れてしまいます、これではCloudflareはキャッシュをしてくれないのでRails側の改修も必要です。

##### 参考までに
以下のコードで`cache control`に`public`の設定を入れることができます。
該当ページのコントローラーなどに記述してください。

``` ruby
expires_in 1.hour, public: true
```

##### CloudflareのPage Rulesでできる主なキャッシュ設定属性
 - URL単位でのキャッシュ
    - `*`などのワイルドカードが利用できる
 - 優先順位
 - 有効期限
 
更に詳しいことは公式のドキュメントを参照してください。

 - [Cloudflareのデフォルトのキャッシュ動作について理解する](https://support.cloudflare.com/hc/ja/articles/200172516-Cloudflare%E3%81%AECDN%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E7%90%86%E8%A7%A3%E3%81%99%E3%82%8B)
 - [CloudflareのCDNについて理解する](https://support.cloudflare.com/hc/ja/articles/200172516-Cloudflare%E3%81%AECDN%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E7%90%86%E8%A7%A3%E3%81%99%E3%82%8B)

## こんな失敗しました
### DNSの移行
サイマではこれまでAWSのRoute53を利用しておりましたのでCloudflareのDNSへ移行をおこないました。
この時DNS移行を手動で行いましたがその際に移行するレコードセットに漏れがありましてサイト上から30分ほど画像が表示されなくなる状態が続きました。
CloudflareではDNSの移行する際に元から自動で設定を移行してくれますがこれは全て網羅されるわけではなく一部移行はマニュアルです、この際に単独での作業と目視でのチェックしかしてなかったので移行漏れが発生したのです。
`単独での作業と目視でのチェック`ですが自身でやっておいてですがこれはかなり危険です。

## じゃあどうする？
### 自動化できると良いかと
時間と環境が許せば自動化をしたほうが良いと思います。
CloudflareではDNSを操作するためのAPIが設けられているようです。
[Cloudflare API v4 DNS Records for a Zone](https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records) 

もしAWSのRoute53からDNSを移行する場合、AWS CLIとの組み合わせで自動化が実現しそうです。

### 最悪ダブルチェックしよう
時間が足りないなどそれぞれ組織やタイミングにおいては自動化することができないことがあるでしょう。
そんなときは最悪２人以上での作業を心がけて漏れが起きにくい体制を用意しましょう。
DNSの設定は頻度の多い作業ではないと思いますのでコストパフォーマンス的には優秀かと思います。

# キャッシュ戦略を取るにあたって諦めたこと
今回のCDNを利用したキャッシュ戦略ではサイトの運用の中で諦めたことが2点かありました。
これらはサイト実装上を都合を販売セクションに説明し合意を取ったうえで実施いたしました。

### ログの取得
サイトの利用状況に関してログを取得しております。
このログはサイト運営上様々なシーンで利用されますがこのログはバックエンド側によって生成されますCM放映中にCDNにサイトをキャッシュさせる場合お客様へのサイトの配信はCDNからされますのでバックエンドまでは到達しないためこのログが取得不可となりました。

### 動的コンテンツ 
今回キャッシュ化をしたページにはお客様ひとりひとりにパーソナライズされたコンテンツがいくつかありました。
これらの殆どがバックエンドのRailsによって機能していため対策する必要があり静的なコンテンツへシフトするか無効化する処置を取りました。


## 諦めたことを諦めなくてもいいように・・・
### 基本方針
前述のとおりサイマはEC2上で動作するRails製のアプリです。
それを**マネージド・サービス／サーバレスへ移行していく**といいかと考えます。

### ログの取得
処理を分散する意味でも以下のようにしては？
`S3` → `API GW` → `AWS Lambda` →　`DynamoDB/Redshift etc`

- javascriptで`API GW`へリクエストする
- フロントエンドのアプリは`S3`で運用する

### 動的コンテンツ
こちらも処理を分散させるために以下のようにしてみては？
`S3` ←→ `API GW` ←→ `AWS Lambda` ←→　`Aurora`
もしくは`AWS Lambda`の箇所をサービス化してインフラ的に負荷分散する。
DBがボトルネックになるかも・・・

これら２案は一旦草案として今後練り上げて参ります。

# その他の問題・・・
それ以外にも

- デバイスによるキャッシュの出し分け問題
    - UAによるデバイスの判定ができない`Enterprise`プランならできるようです。
    - Cloudflare Workersで解決
- 画像のリサイズ問題
    - 画像リサイズの機能はありますがサイマの過去実績からするとコストが想定以上にかかるため断念
    - cloudfrontを間に挟んでLambda@Edgeで処理することに

などありましたが今回は詳しいことは割愛致します、別の機会に投稿するかもです。

# まとめ
インフラの導入や改修はその作業影響が大きいです、私としてもサイト上の全ての画像が見れなくなるという障害をおこしてしまいました。
私のような駆け出しインフラ担当者は構想段階では想定しきれなかった問題が作業段階で発生するものです、特に気をつけないといけないと思うのはこういった作業段階での問題に関してインフラ領域はリカバリの難易度が高いということです。
インフラは導入にコストがかかったり、もしくは利用契約に時間がかかったりするので導入しようとしているサービスが高価で予算が足りないとか週明けから必要なのに契約に2週間かかるなんてことになったら目も当てられません。
そんな時のために2手目、3手目の施策をスタンバイさせておくことが特に重要だと今回で学びました。
インフラ改修はプログラムの改修とは違い影響範囲が大きくものです、私が今回引き起こしたサイトから画像が消えてしまうようなサイト全体に影響する障害が起きえてしまいます、そうなれば事業に与えるインパクトは大きいです、画像が見れないECサイトで商品を買おうと思うお客様がお見えになるとは思えません。

今回CDN導入を行ってインフラ担当はサッカーでいうところのGKのように思いました。サッカーでGKというのは１０回の守備機会で１回でもミスをするとチームが試合に負けかねません、インフラも一度障害を起こすとサービスが停止したりしかねません**GKは守って当たり前／インフラは稼働していて当たり前**なのです、故に周囲からは地味に見えがちですががその役割は極めて重要で影響度が高いということです。

私はインフラを担当するようになってまだ日が浅く知識も技術もまだまだでわからないことだらけですがこの役割にやりがいを感じ志願して務めております、これ以降も色々と経験を積んで今後のサイマの事業発展を促進するようなインフラを提案できるよう精進していきます。