このガイドでは、Go の HTTP 応答処理におけるバッファリングの問題に取り組みます。通常、応答はバッファリングされ、ブロックで送信されます。リクエストが処理された後のクライアント。ストリーミング シナリオの場合、これは望ましくない可能性があります。
提供されたコード スニペットは、2 行のデータがストリーミングされるはずであるが、バッファリングのために同時に送信されるという問題を示しています。
これに対処する 1 つのアプローチは、応答バッファを明示的にフラッシュすることです。 Go の ResponseWriter は Flush メソッドを提供しますが、その可用性は特定の実装によって異なります。
たとえば、次の変更されたコードにはフラッシュが組み込まれています。
func handle(res http.ResponseWriter, req *http.Request) { fmt.Fprintf(res, "sending first line of data") if f, ok := res.(http.Flusher); ok { f.Flush() } sleep(10) //not real code fmt.Fprintf(res, "sending second line of data") }
外部コマンドの出力のストリーミングなど、特定のシナリオでは、直接フラッシュでは不十分な場合があります。 Go のパイプ メカニズムにより、コマンドの出力と応答ライター間の直接ストリーミングが可能になります。
実装例は次のとおりです:
pipeReader, pipeWriter := io.Pipe() cmd.Stdout = pipeWriter cmd.Stderr = pipeWriter go writeCmdOutput(res, pipeReader) err := cmd.Run() pipeWriter.Close() func writeCmdOutput(res http.ResponseWriter, pipeReader *io.PipeReader) { buffer := make([]byte, BUF_LEN) for { n, err := pipeReader.Read(buffer) if err != nil { pipeReader.Close() break } data := buffer[0:n] res.Write(data) if f, ok := res.(http.Flusher); ok { f.Flush() } //reset buffer for i := 0; i < n; i++ { buffer[i] = 0 } } }
柔軟性を高めるには、TCP 接続の直接制御を許可する TCP ハイジャッカーを使用することが可能です。ただし、このアプローチにはネットワーク プログラミングについてのより深い理解が必要であり、一般的な使用例にはあまり推奨されません。
ネットワーク コンポーネントまたはクライアント アプリケーション内でバッファリングが発生する可能性があることに注意してください。これは、特定のユースケースを評価して、明示的なフラッシュまたは代替ソリューションの必要性を判断するために重要です。
以上がGolang で HTTP 応答をストリーミングし、デフォルトのバッファリングを回避するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。