reverse proxy buffer pool
This commit is contained in:
parent
27033e5fcf
commit
e288c7c08c
|
@ -12,6 +12,7 @@ import (
|
||||||
"git.xeserv.us/xena/route/lib/tun2"
|
"git.xeserv.us/xena/route/lib/tun2"
|
||||||
proto "git.xeserv.us/xena/route/proto"
|
proto "git.xeserv.us/xena/route/proto"
|
||||||
"github.com/mtneug/pkg/ulid"
|
"github.com/mtneug/pkg/ulid"
|
||||||
|
"github.com/oxtoacart/bpool"
|
||||||
"golang.org/x/crypto/acme/autocert"
|
"golang.org/x/crypto/acme/autocert"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
|
@ -139,6 +140,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
Director: s.Director,
|
Director: s.Director,
|
||||||
Transport: s.ts,
|
Transport: s.ts,
|
||||||
FlushInterval: 1 * time.Second,
|
FlushInterval: 1 * time.Second,
|
||||||
|
BufferPool: bpool.NewBytePool(256, 4096),
|
||||||
}
|
}
|
||||||
|
|
||||||
rp.ServeHTTP(w, r)
|
rp.ServeHTTP(w, r)
|
||||||
|
|
|
@ -133,3 +133,4 @@ da118f7b8e5954f39d0d2130ab35d4bf0e3cb344 golang.org/x/net/context
|
||||||
0eb507a2ca07f13baf499f89d66cc566bf644643 (dirty) google.golang.org/grpc/credentials
|
0eb507a2ca07f13baf499f89d66cc566bf644643 (dirty) google.golang.org/grpc/credentials
|
||||||
737072b4e32b7a5018b4a7125da8d12de90e8045 github.com/mattn/go-runewidth
|
737072b4e32b7a5018b4a7125da8d12de90e8045 github.com/mattn/go-runewidth
|
||||||
44e365d423f4f06769182abfeeae2b91be9d529b github.com/olekukonko/tablewriter
|
44e365d423f4f06769182abfeeae2b91be9d529b github.com/olekukonko/tablewriter
|
||||||
|
4e1c5567d7c2dd59fa4c7c83d34c2f3528b025d6 github.com/oxtoacart/bpool
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
/*
|
||||||
|
Package bpool implements leaky pools of byte arrays and Buffers as bounded
|
||||||
|
channels. It is based on the leaky buffer example from the Effective Go
|
||||||
|
documentation: http://golang.org/doc/effective_go.html#leaky_buffer
|
||||||
|
*/
|
||||||
|
package bpool
|
|
@ -0,0 +1,40 @@
|
||||||
|
package bpool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BufferPool implements a pool of bytes.Buffers in the form of a bounded
|
||||||
|
// channel.
|
||||||
|
type BufferPool struct {
|
||||||
|
c chan *bytes.Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBufferPool creates a new BufferPool bounded to the given size.
|
||||||
|
func NewBufferPool(size int) (bp *BufferPool) {
|
||||||
|
return &BufferPool{
|
||||||
|
c: make(chan *bytes.Buffer, size),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gets a Buffer from the BufferPool, or creates a new one if none are
|
||||||
|
// available in the pool.
|
||||||
|
func (bp *BufferPool) Get() (b *bytes.Buffer) {
|
||||||
|
select {
|
||||||
|
case b = <-bp.c:
|
||||||
|
// reuse existing buffer
|
||||||
|
default:
|
||||||
|
// create new buffer
|
||||||
|
b = bytes.NewBuffer([]byte{})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put returns the given Buffer to the BufferPool.
|
||||||
|
func (bp *BufferPool) Put(b *bytes.Buffer) {
|
||||||
|
b.Reset()
|
||||||
|
select {
|
||||||
|
case bp.c <- b:
|
||||||
|
default: // Discard the buffer if the pool is full.
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package bpool
|
||||||
|
|
||||||
|
// BytePool implements a leaky pool of []byte in the form of a bounded
|
||||||
|
// channel.
|
||||||
|
type BytePool struct {
|
||||||
|
c chan []byte
|
||||||
|
w int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBytePool creates a new BytePool bounded to the given maxSize, with new
|
||||||
|
// byte arrays sized based on width.
|
||||||
|
func NewBytePool(maxSize int, width int) (bp *BytePool) {
|
||||||
|
return &BytePool{
|
||||||
|
c: make(chan []byte, maxSize),
|
||||||
|
w: width,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gets a []byte from the BytePool, or creates a new one if none are
|
||||||
|
// available in the pool.
|
||||||
|
func (bp *BytePool) Get() (b []byte) {
|
||||||
|
select {
|
||||||
|
case b = <-bp.c:
|
||||||
|
// reuse existing buffer
|
||||||
|
default:
|
||||||
|
// create new buffer
|
||||||
|
b = make([]byte, bp.w)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put returns the given Buffer to the BytePool.
|
||||||
|
func (bp *BytePool) Put(b []byte) {
|
||||||
|
select {
|
||||||
|
case bp.c <- b:
|
||||||
|
// buffer went back into pool
|
||||||
|
default:
|
||||||
|
// buffer didn't go back into pool, just discard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Width returns the width of the byte arrays in this pool.
|
||||||
|
func (bp *BytePool) Width() (n int) {
|
||||||
|
return bp.w
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package bpool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SizedBufferPool implements a pool of bytes.Buffers in the form of a bounded
|
||||||
|
// channel. Buffers are pre-allocated to the requested size.
|
||||||
|
type SizedBufferPool struct {
|
||||||
|
c chan *bytes.Buffer
|
||||||
|
a int
|
||||||
|
}
|
||||||
|
|
||||||
|
// SizedBufferPool creates a new BufferPool bounded to the given size.
|
||||||
|
// size defines the number of buffers to be retained in the pool and alloc sets
|
||||||
|
// the initial capacity of new buffers to minimize calls to make().
|
||||||
|
//
|
||||||
|
// The value of alloc should seek to provide a buffer that is representative of
|
||||||
|
// most data written to the the buffer (i.e. 95th percentile) without being
|
||||||
|
// overly large (which will increase static memory consumption). You may wish to
|
||||||
|
// track the capacity of your last N buffers (i.e. using an []int) prior to
|
||||||
|
// returning them to the pool as input into calculating a suitable alloc value.
|
||||||
|
func NewSizedBufferPool(size int, alloc int) (bp *SizedBufferPool) {
|
||||||
|
return &SizedBufferPool{
|
||||||
|
c: make(chan *bytes.Buffer, size),
|
||||||
|
a: alloc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gets a Buffer from the SizedBufferPool, or creates a new one if none are
|
||||||
|
// available in the pool. Buffers have a pre-allocated capacity.
|
||||||
|
func (bp *SizedBufferPool) Get() (b *bytes.Buffer) {
|
||||||
|
select {
|
||||||
|
case b = <-bp.c:
|
||||||
|
// reuse existing buffer
|
||||||
|
default:
|
||||||
|
// create new buffer
|
||||||
|
b = bytes.NewBuffer(make([]byte, 0, bp.a))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put returns the given Buffer to the SizedBufferPool.
|
||||||
|
func (bp *SizedBufferPool) Put(b *bytes.Buffer) {
|
||||||
|
b.Reset()
|
||||||
|
|
||||||
|
// Release buffers over our maximum capacity and re-create a pre-sized
|
||||||
|
// buffer to replace it.
|
||||||
|
// Note that the cap(b.Bytes()) provides the capacity from the read off-set
|
||||||
|
// only, but as we've called b.Reset() the full capacity of the underlying
|
||||||
|
// byte slice is returned.
|
||||||
|
if cap(b.Bytes()) > bp.a {
|
||||||
|
b = bytes.NewBuffer(make([]byte, 0, bp.a))
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case bp.c <- b:
|
||||||
|
default: // Discard the buffer if the pool is full.
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue