From 149ffd400f38243baaa0e95120b0a663a2b89851 Mon Sep 17 00:00:00 2001 From: GoEdgeLab Date: Mon, 4 Apr 2022 19:45:57 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BC=93=E5=AD=98=E6=96=87=E4=BB=B6=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0Sendfile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/caches/storage_file.go | 8 ++++++++ internal/caches/storage_interface.go | 3 +++ internal/caches/storage_memory.go | 5 +++++ internal/nodes/http_request_cache.go | 10 +++++++++- internal/nodes/http_writer.go | 4 +++- internal/nodes/http_writer_ext.go | 9 +++++++++ internal/utils/writers/writer_bytes_counter.go | 4 ++++ 7 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 internal/nodes/http_writer_ext.go diff --git a/internal/caches/storage_file.go b/internal/caches/storage_file.go index 83d8e0d..44bed8f 100644 --- a/internal/caches/storage_file.go +++ b/internal/caches/storage_file.go @@ -819,6 +819,14 @@ func (this *FileStorage) IgnoreKey(key string) { this.ignoreKeys.Push(key) } +// CanSendfile 是否支持Sendfile +func (this *FileStorage) CanSendfile() bool { + if this.options == nil { + return false + } + return this.options.EnableSendfile +} + // 绝对路径 func (this *FileStorage) dir() string { return this.options.Dir + "/p" + strconv.FormatInt(this.policy.Id, 10) + "/" diff --git a/internal/caches/storage_interface.go b/internal/caches/storage_interface.go index 6c03d52..be12bff 100644 --- a/internal/caches/storage_interface.go +++ b/internal/caches/storage_interface.go @@ -51,4 +51,7 @@ type StorageInterface interface { // IgnoreKey 忽略某个Key,即不缓存某个Key IgnoreKey(key string) + + // CanSendfile 是否支持Sendfile + CanSendfile() bool } diff --git a/internal/caches/storage_memory.go b/internal/caches/storage_memory.go index de30e28..201ddc0 100644 --- a/internal/caches/storage_memory.go +++ b/internal/caches/storage_memory.go @@ -347,6 +347,11 @@ func (this *MemoryStorage) IgnoreKey(key string) { this.ignoreKeys.Push(key) } +// CanSendfile 是否支持Sendfile +func (this *MemoryStorage) CanSendfile() bool { + return false +} + // 计算Key Hash func (this *MemoryStorage) hash(key string) uint64 { return xxhash.Sum64String(key) diff --git a/internal/nodes/http_request_cache.go b/internal/nodes/http_request_cache.go index 718deba..957fbeb 100644 --- a/internal/nodes/http_request_cache.go +++ b/internal/nodes/http_request_cache.go @@ -540,7 +540,15 @@ func (this *HTTPRequest) doCacheRead(useStale bool) (shouldStop bool) { this.writer.Prepare(resp, fileSize, reader.Status(), false) this.writer.WriteHeader(reader.Status()) - _, err = io.CopyBuffer(this.writer, resp.Body, buf) + if storage.CanSendfile() { + if fp, canSendFile := this.writer.canSendfile(); canSendFile { + this.writer.sentBodyBytes, err = io.CopyBuffer(this.writer.rawWriter, fp, buf) + } else { + _, err = io.CopyBuffer(this.writer, resp.Body, buf) + } + } else { + _, err = io.CopyBuffer(this.writer, resp.Body, buf) + } if err == io.EOF { err = nil } diff --git a/internal/nodes/http_writer.go b/internal/nodes/http_writer.go index 84b15fa..dfa0d69 100644 --- a/internal/nodes/http_writer.go +++ b/internal/nodes/http_writer.go @@ -1058,7 +1058,9 @@ func (this *HTTPWriter) Close() { } } - this.sentBodyBytes = this.counterWriter.TotalBytes() + if this.sentBodyBytes == 0 { + this.sentBodyBytes = this.counterWriter.TotalBytes() + } } // Hijack Hijack diff --git a/internal/nodes/http_writer_ext.go b/internal/nodes/http_writer_ext.go new file mode 100644 index 0000000..5fcb93d --- /dev/null +++ b/internal/nodes/http_writer_ext.go @@ -0,0 +1,9 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. +//go:build !plus +// +build !plus + +package nodes + +func (this *HTTPWriter) canSendfile() (*os.File, bool) { + return nil, false +} diff --git a/internal/utils/writers/writer_bytes_counter.go b/internal/utils/writers/writer_bytes_counter.go index 9a5bdaf..7ec18a4 100644 --- a/internal/utils/writers/writer_bytes_counter.go +++ b/internal/utils/writers/writer_bytes_counter.go @@ -13,6 +13,10 @@ func NewBytesCounterWriter(rawWriter io.Writer) *BytesCounterWriter { return &BytesCounterWriter{writer: rawWriter} } +func (this *BytesCounterWriter) RawWriter() io.Writer { + return this.writer +} + func (this *BytesCounterWriter) Write(p []byte) (n int, err error) { n, err = this.writer.Write(p) this.count += int64(n)