第56話で、イトはstandard portの200をcontrol responseだと決めなかった。
full authority、TCP listener、network policy、service identityを照合し、control requestをexact endpointへ届けた。
返ってきたのは、studio操作画面のasset requestだ。
targetはhttps://cdn.picoroute.test/assets/control.css。
origin fixtureでは、violetのrelease assetへ十秒前に更新されている。
near edge shelfには、blueの一つ前のcopyが残っていた。
cache lampはHIT。
Ageは35秒、freshness lifetimeは120秒。
イトはnear copyをpublish trayへ置いた。
「近くてfreshなら、これが最新だよね」
previewのbuttonは、violetではなくblueのままだった。
studio公開確定まで、あと六十秒。
freshでも、originの現在copyとは限らない
イトはblue assetのままpublish sealを下ろそうとした。
ピコはassetへ触れず、edge clockとorigin update clockを別holderへ照らした。
イト
fresh lampが点いているのに、どうして古いblueが返るの?
ピコ
freshはcacheの期限内という意味だよ。originの最新bitsという名前じゃない
イト
じゃあCDNは、近いcopyをいつ使って、いつoriginへ戻るの?
ピコ
requestに合うentryか、まだreuseできるか、validationが要るかを順に見よう
この話のorigin、edge、asset、cache policy、clock、purge consoleは、外のInternetから切り離した学習fixtureだ。
hostnameはreserved .testを使う。
live CDN distribution、real credential、production purge、request floodingは扱わない。
見るのは、cache key、freshness、validation、versioned target、観察結果の境界だ。
CDNは、stored responseを再利用する
RFC 9111 HTTP Cachingは、HTTP cacheの目的を、以前のresponse messageを再利用してperformanceを改善することと説明する。
CDNのedge cacheはshared cacheとして働く場合がある。
requestに使えるstored responseがあれば、originまで毎回content bodyを取りに行かずに返せる。
latencyとnetwork overheadを減らし、同じcontentを複数requestへ再利用できる。
ただし「利用者に物理的に近い」は、reuse可能性を決める全条件ではない。
近いedgeへrequestが着いても、matching entryがなければorigin側へforwardする場合がある。
entryがあっても、freshnessやrequest条件を満たさなければvalidationが必要になる。
CDNは「近いcopyを無条件で返す倉庫」ではない。
cache keyが、どのcopyを候補にするか決める
RFC 9111のcache keyは、少なくともrequest methodとtarget URIから構成される。
多くのHTTP cacheはGET responseを扱い、URIをkeyの中心にする。
同じ見た目のCSSでも、target URIが違えば別entry候補になる。
/assets/control.cssと/assets/control.8f2c.cssは、同じkeyではない。
responseにVaryがあれば、指定されたrequest header fieldもmatchingへ影響する。
RFC 9110のVaryは、methodとtarget URI以外に、どのrequest部分がresponse selectionへ影響したかを示す。
cache keyへ何でも追加すればよいわけではない。
variantを必要以上に細かく分ければhitしにくくなる。
逆に必要な差をkeyへ入れなければ、別条件のresponseを取り違え得る。
まずexact targetと、このfixtureで選んだVary条件を合わせる。
freshは、freshness lifetimeがAgeを上回る状態
RFC 9111のFreshnessでは、responseのageがfreshness lifetimeをまだ超えていなければfreshだ。
式にすると、この関係になる。
freshness_lifetime > current_age
originはCache-Control: max-ageやExpiresでexplicit expirationを示せる。
shared cacheではs-maxageが該当する場合もある。
Age response fieldは、originでresponseが生成またはvalidationされてからの推定秒数を伝える。
今回のold entryはAge 35、freshness lifetime 120。
だからcache rule上はfreshで、originへvalidationせずreuseできる。
しかしorigin assetは十秒前にblueからvioletへ置き換わった。
cacheはその変更を自動で知ったとは限らない。
「fresh entry」と「originで最後に保存されたfile」は、同じ言葉ではない。
staleになったら、validationできる
stored responseがfreshでなく、そのままreuseできないとき、cacheはconditional requestでvalidationできる。
RFC 9111のValidationでは、stored responseのvalidator metadataを使い、current representationと同等かを次のserverへ問い合わせる。
たとえばETagを使うfixtureなら、流れを二つに分けられる。
validatorが一致し、304 Not Modifiedが返れば、cacheはstored responseのmetadataを更新できる。
representationが変わっていれば、new responseを受け取ってstored responseを置き換える。
no-cacheは「絶対に保存しない」と同じではない。
reuse前にsuccessful validationを要求するresponse directiveだ。
保存自体を禁止するno-storeとは分ける。
この話では、fresh entryのvalidationを毎requestへ強制する設定変更はしない。
release assetのtarget designを直す。
HIT / MISSは、最新・安全の合格印ではない
HITは、そのCDN実装がmatching cached responseを使ったという観察結果として読める。
MISSは、matching reusable entryがなく、origin側へrequestをforwardした等の結果として読める。
ただしheader名やstatus語、collapse、revalidationの見せ方はCDN productごとに違う。
HITだからcurrent originと同じ、MISSだから失敗、とは決めない。
Amazon CloudFrontのstandard logにも、expired objectをoriginへ確認したRefreshHitなど複数result typeがある。
運用ではvendor公式のresponse header / log定義と、request target、time、region、response content identityを一緒に残す。
このclosed fixtureでは、HIT / MISS / REVALIDATEDを別lampに固定して学ぶ。
イトの前に、三つの選択肢が開く
studio公開確定まで、あと三十秒。
A near edgeのfresh HITを、そのまま最新として採用する
最も速く返る。
だがblue assetのままpublishされ、originのviolet releaseと食い違う。
B 全edgeの全pathを、確認せずglobal purgeする
old copyを消せる可能性はある。
しかしunrelated assetまでmissへ変え、origin trafficと影響範囲を広げる。
C publishを止め、versioned targetへ参照を切り替えて結果を照合する
new assetを/assets/control.8f2c.cssとしてorigin fixtureへ置く。
HTML fixtureの参照をnew targetへ切り替え、first requestのMISSとorigin response、second requestのHITを比べる。
ピコはpublish sealにもpurge consoleにも触れなかった。
「近いかどうかより先に、どのversionをrequestしたかを残す」
イトはCを選んだ。
自分でpublish sealを上げ、old targetのrequestを止めた。
new target、expected violet asset identity、cache policyをrelease holderへ並べた。
new targetのfirst requestだけが、originへ進んだ
イトは/assets/control.8f2c.cssへfirst requestを送った。
near edgeにはmatching entryがない。
fixture resultはMISS。
requestはorigin fixtureへ進み、violet asset、expected content identity、max-age=120を受け取った。
edgeはresponseを保存し、viewerへviolet assetを返した。
イトは同じnew targetへsecond requestを送った。
fixture resultはHIT。
Ageは3秒。
response content identityはfirst requestと一致し、preview buttonはvioletになった。

old targetとunrelated assetは、勝手に消えなかった
イトはold /assets/control.cssへcomparison requestを送った。
blue copyはまだfreshで、HIT。
originのvioletと違うままだ。
new versionへ切り替えただけでは、old URIのstored responseを消したことにならない。
次にunrelated /assets/logo.41a0.svgを確認した。
green logo entryはHITのまま。
global invalidation countは0。
origin fetchはnew targetのfirst request 1回だけだった。
studio公開previewはviolet assetを使い、publish ready lampがgreenになった。
invalidationは、対象と目的を決めて使う
緊急にold objectを配信停止したい場合、expiryを待たずにCDN productのinvalidation / purgeを使う選択肢がある。
CloudFrontのInvalidation公式資料は、edge cacheからfileをinvalidateする方法と、different nameのversioned fileを使う方法を分ける。
invalidation後のnext requestはoriginへnew versionを取りに行く。
一方、frequent updateではversioned filenameが、client cacheや別proxyにold nameが残る状況も含めてversionを制御しやすいと説明する。
どちらを選ぶかは、削除の緊急性、更新頻度、cache policy、cost、rollback、利用productの保証で変わる。
wildcard purgeを「cacheが怪しい」の一言で押さない。
exact path / tag等の対象、expected result、origin capacity、rollback、実行権限を確認する。
HTTP unsafe method後のinvalidationも、それだけで世界中の全cacheが消える保証ではない。
RFC 9111のInvalidating Stored Responsesは、state-changing requestが通ったcacheのtarget URI等を無効化する規則で、global purge protocolではない。
近さではなく、reuse contractを残す
workbenchには、七つの証拠が残った。
old targetのfresh blue HIT。
origin fixtureのcurrent violet asset。
new versioned target。
new targetのfirst MISS。
origin fetch 1。
new targetのsecond violet HIT。
unrelated logo HITとglobal invalidation 0。
CDNを「近いから最新」と判断しない。まずexact targetとcache keyを合わせ、Ageとfreshness lifetime、validation resultを確認する。急ぐ静的asset更新では、旧targetを無差別にpurgeする前にversioned targetへ参照を切り替え、first missとsecond hitの内容を比べる。freshはcache期限内であり、originの最新bitsという意味ではない。
「freshなのはcopyの期限。ぼくが届けたいrelease versionとは、別に照合するんだ」
イトはold blue HITをpublish trayへ戻さず、new targetとviolet response identityのpairをcurrent releaseへ残した。
そのnew asset requestの前に、二つのedge counterが開いた。
一つは距離が近いがqueueが長い。
もう一つは少し遠いが、すぐ受け取れる。
requestは、どちらのedge serverへ向かうのだろうか。
次回:一番近いedgeが、いつも選ばれる?
イトはmap上で最短のedge counterへrequest cardを置こうとした。
「CDNなら、物理的に一番近いserverへ行くんだよね」
ピコはcardを動かさず、routing policy、availability、queueの三lampを照らした。
次回、ピコルート第58話。
イトは、一番近いedge serverが必ず選ばれると決めなかった|requestはどのcounterへ行く?

