Skip to content
This repository has been archived by the owner on Apr 12, 2023. It is now read-only.

ETag による通信量削減 #199

Open
i-maruyama opened this issue May 27, 2021 · 12 comments · May be fixed by #233
Open

ETag による通信量削減 #199

i-maruyama opened this issue May 27, 2021 · 12 comments · May be fixed by #233
Labels
confirmed 開発内部管理用 enhancement 新しい機能や改善のリクエスト

Comments

@i-maruyama
Copy link
Contributor

i-maruyama commented May 27, 2021

その機能リクエストは何らかの問題に関連しますか / Is your feature request related to a problem?

  1. 接触確認毎に毎回TEKリストを DLし、無駄な通信量が多い問題。
  2. CDN サーバーは ETag を付与しているが、有効活用していない問題。

なお接触確認が走る頻度はバックグラウンド (6 時間毎) あるいは, 手動によるホームページ再表示毎です. URL は https://covid19radar-jpn-prod.azureedge.net/c19r/440/list.json です. zip に比べれば対した通信量ではないと思いますが、電源消費も抑えられるかもしれません。

解決策についてお書きください / Describe the solution you'd like

  • ETag を利用し通信量を削減する

現在は、 TEK リストは毎回 DL し、 LastProcessTekTimestamp より新しい TEK(zip) をDL して接触確認し、成功すれば LastProcessTekTimestamp を更新しています。 以下では、サーバーが付与する ETag をローカルに保存して、 ETag が違えば DL する通信(If-None-Match)を行う実装案を紹介します。重要なのは、 LastProcessTekTimestamp と同じタイミングで ローカル ETag を更新することです。もし、 接触確認失敗のときに、 ローカル ETag だけ更新すると TEK リストが DL されなくなり、 ETag がサーバー側で更新されるまで(現状では1日)接触確認できなくなります。それを考慮した実装案が以下です。

  1. ETag 利用のため, HttpDataService.cs (GetCdnAsync) を改変します. ETagの一時的なやり取りは Xamarin.Essentials.PreferenceKey を用います。
  2. ETag 保存のため, LastProcessTekTimestamp と同じ枠組みを使います。対応のため改変するのは2ファイルです
    -- PreferenceKey.cs (PreferenceKey.ETag追加)
    -- ExposureNotificationService.cs (Get&Set method追加。及び RemoveLastProcessTekTimestamp の中で ETag も 消去し再DL可能に)
  3. ETag 更新のため, ExposureNotificationHandler.cs を改変します

あなたが考える代替案についてご説明ください / Describe alternatives you've considered

  • (今後サーバー側の ETag 不対応等がある場合など) Last-Modified と If-Modified-Since を使う.

1日様子を見た範囲(Android)では、ETag は機能していそうです(以下のスクショ)。もう少し様子を見ます。

  • ETag の一時的なやり取りをXamarin.Essentials.PreferenceKey 以外を使う

アドバイスあれば。

その他 / Additional context

ETag


Internal Tracking Code: NFR 2527

i-maruyama added a commit to i-maruyama/cocoa that referenced this issue May 28, 2021
@i-maruyama
Copy link
Contributor Author

i-maruyama commented May 29, 2021

三日目も ETag は付与されていました。ETag が同じ値の場合には、 status も 304 を返しています。

上の i-maruyama@32c1c57 上、サンプルコードを載せています。(私自身はMockの方でテストしていますが、 Debug 系がPR 中なので、別途ブランチ作りました)

その中で疑問点があるのですが、以下のコードで2回同じコード(await)が必要なのは、この結果で result.StatusCode が変更されるからでしょうか?

await result.Content.ReadAsStringAsync();
if (result.StatusCode == System.Net.HttpStatusCode.OK)
{
return await result.Content.ReadAsStringAsync();

もしご存じでしたら、ご教示ください。

https://docs.microsoft.com/ja-jp/dotnet/api/system.net.http.httpcontent.readasstringasync?view=net-5.0

@keiji keiji added the enhancement 新しい機能や改善のリクエスト label Jun 2, 2021
@b-wind
Copy link

b-wind commented Jun 9, 2021

三日目も ETag は付与されていました

ETag を付けるか付けないか・どのように付けるかはサーバー依存なので観測するよりサーバー側の設定を確認して貰った方が良いかと。
Azure CDN の様なので特に何もしなくても付くような気はします。

https://docs.microsoft.com/ja-jp/azure/cdn/cdn-how-caching-works

(今後サーバー側の ETag 不対応等がある場合など) Last-Modified と If-Modified-Since を使う.

あまり深く考えずにEtagでの判定と併用してしまって良いと思います。

Etag(等)の保存場所としては CacheDirectory を使用する方が良い気がしますが、使い方はイマイチ理解していません。
https://docs.microsoft.com/ja-jp/xamarin/essentials/file-system-helpers?tabs=android

i-maruyama@32c1c57

PR の形にして貰った方が他の人が見やすいかと。
見る限り、304 応答( System.Net.HttpStatusCode.NotModified )の場合の対応が不足しているようです。

通信量削減という意味では、ファイル圧縮も有効です。(現時点で有効化されていないようです)
https://docs.microsoft.com/ja-jp/azure/cdn/cdn-improve-performance

余談ですが curl がインストールされている環境では、以下の様に Etag...etc を確認出来ますね。

$ curl --head https://covid19radar-jpn-prod.azureedge.net/c19r/440/list.json
HTTP/2 200
accept-ranges: bytes
age: 2373
cache-control: max-age=3600
content-md5: lLePHwXKvuIBFSaaBiOKig==
content-type: application/octet-stream
date: Wed, 09 Jun 2021 20:03:43 GMT
etag: 0x8D92B5745276DD3
expires: Wed, 09 Jun 2021 21:03:43 GMT
last-modified: Wed, 09 Jun 2021 15:00:07 GMT
server: ECAcc (osa/2B63)
x-cache: HIT
x-ms-blob-type: BlockBlob
x-ms-lease-status: unlocked
x-ms-request-id: 1fd18309-501e-0003-1965-5df4ac000000
x-ms-version: 2009-09-19
content-length: 13427

@i-maruyama
Copy link
Contributor Author

見る限り、304 応答( System.Net.HttpStatusCode.NotModified )の場合の対応が不足しているようです。

コードをご覧いただきありがとうございます。 304 への対応は、 d21e8cf のようにしています。PRにしますね。

余談ですが curl がインストールされている環境では、以下の様に Etag...etc を確認出来ますね。

教えていただきありがとうございます。content-length も見たいなと思っていたところでした。

@b-wind
Copy link

b-wind commented Jun 12, 2021

実際の所、通信量の削減は必要とされているのかがよく分かりませんね。
私自身はネットワーク屋として推奨していますが、関係者のご意見も聞いてみたいところ。

@i-maruyama i-maruyama linked a pull request Jun 12, 2021 that will close this issue
@i-maruyama
Copy link
Contributor Author

PRしました。128kbps 環境なら、このETag による 13kB の通信量削減は体感できるかもしれません。

@b-wind
Copy link

b-wind commented Jun 13, 2021

サーバー側でも差分ダウンロードさせてくれれば良いのにと思っているのは秘密です。

@b-wind
Copy link

b-wind commented Jun 13, 2021

余談ですが、list.json のサイズが約 13kbyte , ファイル圧縮を有効にしたと仮定すると約 1.1kbyte 程度まで縮小できますね。
基本的には肥大化する一方の様なので、ファイル圧縮も有効化して欲しいなとは思います。

@b-wind
Copy link

b-wind commented Jun 13, 2021

gzip だけじゃ無く brotli も使えるのかな? だとしたらもう少し小さく出来そう。

@b-wind
Copy link

b-wind commented Jun 13, 2021

brotli での想定ファイルサイズは 663byte になりますね。流石の圧縮率。

@b-wind
Copy link

b-wind commented Jun 13, 2021

Xamarin.Android/iOS の要求バージョンは満たしているように見えますね。

https://docs.microsoft.com/ja-jp/dotnet/api/system.net.decompressionmethods?view=net-5.0

@b-wind
Copy link

b-wind commented Jun 13, 2021

Accept-Encoding ヘッダに br, gzip を指定するだけ。
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Accept-Encoding

@b-wind
Copy link

b-wind commented Jun 13, 2021

AutomaticDecompression を設定すれば透過的に扱ってくれそう。
https://stackoverflow.com/questions/20990601/decompressing-gzip-stream-from-httpclient-response/27327208#27327208

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
confirmed 開発内部管理用 enhancement 新しい機能や改善のリクエスト
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants