http プロトコルでは、リクエストのキャンセルまたはデータ送信の中断が発生する可能性があります。この時点で、クライアントはデータの一部を受信しており、後でリクエストするときに残りの部分 (ブレークポイント送信再開) をリクエストするのが最善です。より大きなファイルの場合は、クライアントのマルチスレッド フラグメント ダウンロードをサポートできます...
上記は通常のアプリケーションの多くの製品でサポートされており、その原理は http プロトコルの Range に関連しています。
Range は HTTP/1.1 の新しいリクエスト ヘッダー フィールドです。rfc ドキュメント: RFC 7233: Hypertext Transfer Protocol (HTTP/1.1): Range Requests HTTP プロトコルは広範かつ奥深く、多くの独創的な設計があります。Range は次のいずれかです。彼らです。
1. 範囲プロトコル:
1) サーバーが範囲をサポートしているかどうかを確認します。
クライアントがリクエストを開始し、サーバーがリクエストを受信した後、レスポンスのヘッダーに Accept-Ranges: バイトがある場合、Range がサポートされていることを示します。
たとえば、curl -I を通じてリクエストを開始して、応答ヘッダー情報を表示します (curl -I は、ドキュメント情報のみを表示することを意味します)。
$ curl -I http://127.0.0.1/rt1/2.mp4
HTTP/1.1 200 OK
Server: openresty/1.19.9.1
Date: Thu, 12 Jan 2023 08:04:32 GMT
Content-Type: video/mp4
Content-Length: 505199705
Last-Modified: Fri, 08 Jul 2022 07:09:25 GMT
Connection: keep-alive
ETag: "62c7d825-1e1cbc59"
Accept-Ranges: bytes
上の Accept-Ranges: bytes は、範囲を定義する単位がバイトであることを示し、Content-Length はファイル サイズを示します。サーバーがヘッダー コンテンツ Accept-Ranges: none で応答した場合、それはサポートされていないことを意味します。
2) 範囲プロトコル形式:
クライアントは、範囲リクエストが開始されたことを示す範囲情報をヘッダーに追加します。その形式は次のとおりです。
範囲:単位=最初のバイト位置-[最後のバイト位置]
例: 単位 (バイトなど) = 開始バイト位置 - 終了バイト位置。
サーバーは、ヘッダーに範囲情報を追加して応答します。
Content-Range: 単位の最初のバイト位置 - [最後のバイト位置]/[エンティティの長さ]
例: Content-Range: バイトの開始バイト位置 - 終了バイト位置/ファイル サイズ。
注: 最初のバイトの pos は 0 から始まります。
例を見てみましょう: サイズが 5000 バイトのファイルがあり、マルチスレッド ダウンロード (たとえば 4) を有効にしたいとします。各スレッドは一部のダウンロードを担当し、それを分割できます。の中へ:
Range: bytes=0-1199 头1200个字节
Range: bytes=1200-2399 第二个1200字节
Range: bytes=2400-3599 第三个1200字节
Range: bytes=3600-5000 最后的1400字节
服务器给出响应:
// 第1个响应
Content-Length:1200
Content-Range:bytes 0-1199/5000
// 第2个响应
Content-Length:1200
Content-Range:bytes 1200-2399/5000
// 第3个响应
Content-Length:1200
Content-Range:bytes 2400-3599/5000
// 第4个响应
Content-Length:1400
Content-Range:bytes 3600-5000/5000
Content-Length は対応する範囲のサイズを示し、Content-Range はリクエストに対応する範囲を返します。
3) Range リクエストの応答コード:
サーバーは、リクエスト ヘッダーの Range: bytes=0-xxx によって Range リクエストであるかどうかを判断し、この値が存在し、有効であれば、ファイル コンテンツのリクエストされた部分と、そのステータス コードのみを返します。応答は Partial Content. を示す 206 となり、Content-Range を設定します。無効な場合は、要求範囲が満たされないことを示す 416 ステータス コードが返されます。リクエストヘッダーに Range がない場合、サーバーは通常どおり応答し、Content-Range は設定されません。
- 206: リクエストが成功すると、サーバーは 206 Partial Content ステータス コードを返します。
- 416: 要求された範囲が範囲外である (範囲値がリソースのサイズを超えている) 場合、サーバーは 416 Requested Range Not Satisfiable (要求された範囲を満たすことができない) ステータス コードを返します。
- 200: サーバーが Range リクエストをサポートしていない場合、サーバーは 200 OK ステータス コードを返します。
4) チャンク転送エンコーディングとの比較
Transfer-Encoding ヘッダーを使用すると、チャンク エンコーディングが可能になります。これは、データ量が大きく、要求が完全に処理されるまで応答のサイズがわからない場合に役立ちます。サーバーは、バッファリングや応答の正確なサイズの決定を行わずに、データをクライアントに直接送信します。後者は待ち時間を増大させます。範囲リクエストはチャンク転送と互換性があり、単独で使用することも、一緒に使用することもできます。
2. サーバーに特定の範囲のデータをリクエストします
1) 単一範囲:
クライアントがリクエストを行う際、ヘッダの Range でリクエストの範囲を示すことができますが、このときサーバーが Range をサポートしていればステータスコード 206 を返し、指定された範囲のデータを返し、Content-Range を追加します。ヘッダー内; それ以外の場合は、 をサポートせず、200 を返します。
例: (curl -i は応答ヘッダーを出力することを意味します)
$ curl -i -H "Range: bytes=0-102300" http://127.0.0.1/f1.txt
HTTP/1.1 206 Partial Content
Server: openresty/1.19.9.1
Date: Thu, 12 Jan 2023 09:34:49 GMT
Content-Type: text/plain
Content-Length: 10
Last-Modified: Thu, 12 Jan 2023 09:34:44 GMT
Connection: keep-alive
ETag: "63bfd434-a"
Content-Range: bytes 0-9/10
123456789
2) マルチスコープ:
$ curl -i -H "Range: bytes=0-1,4-5" http://127.0.0.1/f1.txt
HTTP/1.1 206 Partial Content
Server: openresty/1.19.9.1
Date: Thu, 12 Jan 2023 09:36:21 GMT
Content-Type: multipart/byteranges; boundary=00000000000000000001
Content-Length: 198
Last-Modified: Thu, 12 Jan 2023 09:34:44 GMT
Connection: keep-alive
ETag: "63bfd434-a"
--00000000000000000001
Content-Type: text/plain
Content-Range: bytes 0-1/10
12
--00000000000000000001
Content-Type: text/plain
Content-Range: bytes 4-5/10
56
--00000000000000000001--
Range ヘッダーは、ドキュメントの複数の部分を一度にリクエストすることもサポートしています。リクエスト範囲はカンマで区切られます。
サーバーは 206 Partial Content ステータス コードと Content-Type: multipart/byteranges;boundary=00000000000000000001 ヘッダーを返し、Content-Type: multipart/byteranges は応答に複数のバイト範囲があることを示します。byterange の各部分には独自の Content-type ヘッダーと Content-Range があり、境界パラメータを使用して本文を分割します。
3) 条件の範囲:
(中断後) さらなるリソース フラグメントの要求が再開される場合、最後のフラグメントが受信されてからリソースが変更されていないことを確認する必要があります。
If -Rangeリクエスト ヘッダーを使用して、条件付き範囲リクエストを生成できます。条件が満たされると、条件付きリクエストが有効になり、サーバーはステータス コード206 Partial と対応するメッセージ本文を 含む応答を返します。 条件が満たされない場合は、ステータス コード 200 OK の応答が返され、リソース全体が返されます。このヘッダーは Last-Modified バリデーターまたは ETagとともに 使用できますが、両方を同時に使用することはできません。
参考:
Range、Content-Range | HTTP の HappyCoding について話しましょう:)
3. 例: nginx はビデオ ダウンロード サービスを提供します
http の Range は範囲リクエストを提供でき、最も重要なアプリケーションはビデオ再生です。
1) nginx 設定:
openrestyのdocker sceneを使用して起動します。構成は次のとおりです
server {
listen 80;
server_name localhost;
location = /f1.txt {
root /data/;
}
location = /rt1/2.mp4 {
root /data/;
}
次のファイルを作成します: /data/rt1/2.mp4 /data/f1.txt
注: nginx 自体は Range をサポートしており、nginx は Range back-to-source をサポートする ngx_http_slice_module モジュール (--with-http_slice_module パラメーター) も提供していることがわかります。
2) ブラウザアクセス:
nginx を設定した後、ブラウザ経由でアクセスします: http://127.0.0.1/rt1/2.mp4 Chrome コントロール パネルを開き、ネットワーク タブ ページに切り替えます。
複数のリクエストがあり、最初のリクエストのステータス コードは 200 で、残りのリクエストのステータス コードはすべて 206 (部分コンテンツ-部分コンテンツ) であることがわかります。また、Chrome は、内蔵のビデオ デコード ツールを使用して MP4 ファイルを再生できるように非常によく考えられており、一時停止ボタンもあります。(再生後に一時停止しない場合、nginx は引き続き chrome にデータを吐き出し、このプロセスは中断されません。一時停止ボタンを押すと通信が中断され接続が切断され、このとき nginx はアクセス ログを書き込みます)。