Skip to content

Instantly share code, notes, and snippets.

@erikdubbelboer
Created August 12, 2019 16:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erikdubbelboer/0b5468f1a7ba9679b435973b0590d685 to your computer and use it in GitHub Desktop.
Save erikdubbelboer/0b5468f1a7ba9679b435973b0590d685 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"net"
"runtime"
"sync"
"sync/atomic"
"time"
"github.com/valyala/fasthttp"
)
var (
// Important to do these conversions only once an not
// every time we need them.
strSlashA = []byte("/a")
strSlashB = []byte("/b")
strDefaultBody = []byte("test")
strDestURLSlashA = []byte("http://127.0.0.1:1337/a")
strDestURLSlashB = []byte("http://127.0.0.1:1337/b")
client = &fasthttp.Client{
NoDefaultUserAgentHeader: true, // Don't send: User-Agent: fasthttp
MaxConnsPerHost: 10000,
ReadBufferSize: 4096, // Make sure to set this big enough that your whole request can be read at once.
WriteBufferSize: 4096, // Same but for your response.
ReadTimeout: time.Second,
WriteTimeout: time.Second,
MaxIdleConnDuration: time.Minute,
DisableHeaderNamesNormalizing: true, // If you set the case on your headers correctly you can enable this.
}
// Put everything in pools to prevent garbage.
bytesPool = sync.Pool{
New: func() interface{} {
b := make([]byte, 0)
return &b
},
}
responsePool = sync.Pool{
New: func() interface{} {
return make(chan *fasthttp.Response)
},
}
// Our request counters.
requests int64
)
func handler(ctx *fasthttp.RequestCtx) {
atomic.AddInt64(&requests, 1)
// Just send some default body.
ctx.SetBody(strDefaultBody)
ctx.Response.SetStatusCode(fasthttp.StatusOK)
}
func main() {
// Completely disable memory profiling if we aren't going to use it.
// If we don't do this the profiler will take a sample every 0.5MiB bytes allocated.
runtime.MemProfileRate = 0
ln, err := net.Listen("tcp4", "127.0.0.1:1337")
if err != nil {
panic(err)
}
defer ln.Close()
s := &fasthttp.Server{
Handler: handler,
NoDefaultServerHeader: true, // Don't send Server: fasthttp
ReadBufferSize: 4096, // Make sure these are big enough.
WriteBufferSize: 4096,
ReadTimeout: time.Second,
WriteTimeout: time.Second,
IdleTimeout: time.Minute, // This can be long for keep-alive connections.
DisableHeaderNamesNormalizing: true, // If you're not going to look at headers or know the casing you can set this.
NoDefaultContentType: true, // Don't send Content-Type: text/plain if no Content-Type is set manually.
}
go func() {
if err := s.Serve(ln); err != nil {
panic(err)
}
}()
for i := 0; i < 5; i++ {
go func() {
for {
req := fasthttp.AcquireRequest()
res := fasthttp.AcquireResponse()
req.SetRequestURIBytes(strDestURLSlashA)
if err := fasthttp.Do(req, res); err != nil {
println(err.Error())
}
if len(res.Body()) != len(strDefaultBody) {
println(string(res.Body()))
}
fasthttp.ReleaseRequest(req)
fasthttp.ReleaseResponse(res)
}
}()
}
// Print the request counters every second.
for {
time.Sleep(time.Second)
r := atomic.SwapInt64(&requests, 0)
fmt.Println(r, runtime.NumGoroutine())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment