optimize http server

pull/432/merge
Darien Raymond 2017-04-17 22:35:20 +02:00
parent 54b441d690
commit 8868fe68ed
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
4 changed files with 127 additions and 44 deletions

View File

@ -1,6 +1,10 @@
package buf package buf
import "io" import (
"io"
"v2ray.com/core/common/errors"
)
// BytesToBufferReader is a Reader that adjusts its reading speed automatically. // BytesToBufferReader is a Reader that adjusts its reading speed automatically.
type BytesToBufferReader struct { type BytesToBufferReader struct {
@ -9,20 +13,40 @@ type BytesToBufferReader struct {
} }
// Read implements Reader.Read(). // Read implements Reader.Read().
func (v *BytesToBufferReader) Read() (MultiBuffer, error) { func (r *BytesToBufferReader) Read() (MultiBuffer, error) {
if err := v.buffer.Reset(ReadFrom(v.reader)); err != nil { if err := r.buffer.Reset(ReadFrom(r.reader)); err != nil {
return nil, err return nil, err
} }
mb := NewMultiBuffer() mb := NewMultiBuffer()
for !v.buffer.IsEmpty() { for !r.buffer.IsEmpty() {
b := New() b := New()
b.AppendSupplier(ReadFrom(v.buffer)) b.AppendSupplier(ReadFrom(r.buffer))
mb.Append(b) mb.Append(b)
} }
return mb, nil return mb, nil
} }
func (r *BytesToBufferReader) WriteTo(writer io.Writer) (int64, error) {
totalBytes := int64(0)
eof := false
for !eof {
if err := r.buffer.Reset(ReadFrom(r.reader)); err != nil {
if errors.Cause(err) == io.EOF {
eof = true
} else {
return totalBytes, err
}
}
nBytes, err := writer.Write(r.buffer.Bytes())
totalBytes += int64(nBytes)
if err != nil {
return totalBytes, err
}
}
return totalBytes, nil
}
type readerAdpater struct { type readerAdpater struct {
MultiBufferReader MultiBufferReader
} }
@ -38,45 +62,75 @@ type bufferToBytesReader struct {
} }
// fill fills in the internal buffer. // fill fills in the internal buffer.
func (v *bufferToBytesReader) fill() { func (r *bufferToBytesReader) fill() {
b, err := v.stream.Read() b, err := r.stream.Read()
if err != nil { if err != nil {
v.err = err r.err = err
return return
} }
v.current = b r.current = b
} }
func (v *bufferToBytesReader) Read(b []byte) (int, error) { func (r *bufferToBytesReader) Read(b []byte) (int, error) {
if v.err != nil { if r.err != nil {
return 0, v.err return 0, r.err
} }
if v.current == nil { if r.current == nil {
v.fill() r.fill()
if v.err != nil { if r.err != nil {
return 0, v.err return 0, r.err
} }
} }
nBytes, err := v.current.Read(b) nBytes, err := r.current.Read(b)
if v.current.IsEmpty() { if r.current.IsEmpty() {
v.current.Release() r.current.Release()
v.current = nil r.current = nil
} }
return nBytes, err return nBytes, err
} }
func (v *bufferToBytesReader) ReadMultiBuffer() (MultiBuffer, error) { func (r *bufferToBytesReader) ReadMultiBuffer() (MultiBuffer, error) {
if v.err != nil { if r.err != nil {
return nil, v.err return nil, r.err
} }
if v.current == nil { if r.current == nil {
v.fill() r.fill()
if v.err != nil { if r.err != nil {
return nil, v.err return nil, r.err
} }
} }
b := v.current b := r.current
v.current = nil r.current = nil
return b, nil return b, nil
} }
func (r *bufferToBytesReader) writeToInternal(writer io.Writer) (int64, error) {
if r.err != nil {
return 0, r.err
}
mbWriter := NewWriter(writer)
totalBytes := int64(0)
for {
if r.current == nil {
r.fill()
if r.err != nil {
return totalBytes, r.err
}
}
totalBytes := int64(r.current.Len())
if err := mbWriter.Write(r.current); err != nil {
return totalBytes, err
}
r.current = nil
}
}
func (r *bufferToBytesReader) WriteTo(writer io.Writer) (int64, error) {
nBytes, err := r.writeToInternal(writer)
if errors.Cause(err) == io.EOF {
return nBytes, nil
}
return nBytes, err
}

View File

@ -8,8 +8,8 @@ type BufferToBytesWriter struct {
} }
// Write implements Writer.Write(). Write() takes ownership of the given buffer. // Write implements Writer.Write(). Write() takes ownership of the given buffer.
func (v *BufferToBytesWriter) Write(mb MultiBuffer) error { func (w *BufferToBytesWriter) Write(mb MultiBuffer) error {
if mw, ok := v.writer.(MultiBufferWriter); ok { if mw, ok := w.writer.(MultiBufferWriter); ok {
_, err := mw.WriteMultiBuffer(mb) _, err := mw.WriteMultiBuffer(mb)
return err return err
} }
@ -17,7 +17,7 @@ func (v *BufferToBytesWriter) Write(mb MultiBuffer) error {
defer mb.Release() defer mb.Release()
bs := mb.ToNetBuffers() bs := mb.ToNetBuffers()
_, err := bs.WriteTo(v.writer) _, err := bs.WriteTo(w.writer)
return err return err
} }
@ -42,3 +42,22 @@ func (w *bytesToBufferWriter) Write(payload []byte) (int, error) {
func (w *bytesToBufferWriter) WriteMulteBuffer(mb MultiBuffer) (int, error) { func (w *bytesToBufferWriter) WriteMulteBuffer(mb MultiBuffer) (int, error) {
return mb.Len(), w.writer.Write(mb) return mb.Len(), w.writer.Write(mb)
} }
func (w *bytesToBufferWriter) ReadFrom(reader io.Reader) (int64, error) {
mbReader := NewReader(reader)
totalBytes := int64(0)
eof := false
for !eof {
mb, err := mbReader.Read()
if err == io.EOF {
eof = true
} else if err != nil {
return totalBytes, err
}
totalBytes += int64(mb.Len())
if err := w.writer.Write(mb); err != nil {
return totalBytes, err
}
}
return totalBytes, nil
}

View File

@ -1,12 +1,17 @@
package buf_test package buf_test
import ( import (
"bufio"
"bytes" "bytes"
"crypto/rand" "crypto/rand"
"testing" "testing"
"context"
"io"
. "v2ray.com/core/common/buf" . "v2ray.com/core/common/buf"
"v2ray.com/core/testing/assert" "v2ray.com/core/testing/assert"
"v2ray.com/core/transport/ray"
) )
func TestWriter(t *testing.T) { func TestWriter(t *testing.T) {
@ -24,3 +29,17 @@ func TestWriter(t *testing.T) {
assert.Error(err).IsNil() assert.Error(err).IsNil()
assert.Bytes(expectedBytes).Equals(writeBuffer.Bytes()) assert.Bytes(expectedBytes).Equals(writeBuffer.Bytes())
} }
func TestBytesWriterReadFrom(t *testing.T) {
assert := assert.On(t)
cache := ray.NewStream(context.Background())
reader := bufio.NewReader(io.LimitReader(rand.Reader, 8192))
_, err := reader.WriteTo(ToBytesWriter(cache))
assert.Error(err).IsNil()
mb, err := cache.Read()
assert.Error(err).IsNil()
assert.Int(mb.Len()).Equals(8192)
assert.Int(len(mb)).Equals(4)
}

View File

@ -235,12 +235,8 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, rea
requestDone := signal.ExecuteAsync(func() error { requestDone := signal.ExecuteAsync(func() error {
request.Header.Set("Connection", "close") request.Header.Set("Connection", "close")
requestWriter := buf.NewBufferedWriter(buf.ToBytesWriter(ray.InboundInput())) requestWriter := buf.ToBytesWriter(ray.InboundInput())
err := request.Write(requestWriter) if err := request.Write(requestWriter); err != nil {
if err != nil {
return err
}
if err := requestWriter.Flush(); err != nil {
return err return err
} }
return nil return nil
@ -271,12 +267,7 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, rea
response.Header.Set("Connection", "close") response.Header.Set("Connection", "close")
response.Header.Set("Proxy-Connection", "close") response.Header.Set("Proxy-Connection", "close")
} }
responseWriter := buf.NewBufferedWriter(writer) if err := response.Write(writer); err != nil {
if err := response.Write(responseWriter); err != nil {
return err
}
if err := responseWriter.Flush(); err != nil {
return err return err
} }
return nil return nil