-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhttp_runtime.go
More file actions
79 lines (70 loc) · 2.17 KB
/
Copy pathhttp_runtime.go
File metadata and controls
79 lines (70 loc) · 2.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package main
import (
"net/http"
"time"
)
const (
maxInFlightRequests = 512
maxQueueWait = 150 * time.Second
serverReadHeaderTimeout = 5 * time.Second
serverWriteTimeout = 120 * time.Second
serverIdleTimeout = 120 * time.Second
serverMaxHeaderBytes = 1 << 20
upstreamMaxIdleConns = 256
upstreamMaxConnsPerHost = 256
upstreamIdleConnTimeout = 90 * time.Second
upstreamResponseTimeout = 30 * time.Second
)
func newUpstreamTransport() *http.Transport {
baseTransport, ok := http.DefaultTransport.(*http.Transport)
if !ok {
return &http.Transport{
Proxy: http.ProxyFromEnvironment,
MaxIdleConns: upstreamMaxIdleConns,
MaxIdleConnsPerHost: upstreamMaxConnsPerHost,
MaxConnsPerHost: upstreamMaxConnsPerHost,
IdleConnTimeout: upstreamIdleConnTimeout,
TLSHandshakeTimeout: 5 * time.Second,
ResponseHeaderTimeout: upstreamResponseTimeout,
ExpectContinueTimeout: 1 * time.Second,
}
}
transport := baseTransport.Clone()
transport.MaxIdleConns = upstreamMaxIdleConns
transport.MaxIdleConnsPerHost = upstreamMaxConnsPerHost
transport.MaxConnsPerHost = upstreamMaxConnsPerHost
transport.IdleConnTimeout = upstreamIdleConnTimeout
transport.TLSHandshakeTimeout = 5 * time.Second
transport.ResponseHeaderTimeout = upstreamResponseTimeout
transport.ExpectContinueTimeout = 1 * time.Second
return transport
}
func limitMiddleware(maxInFlight int, next http.Handler) http.Handler {
if maxInFlight <= 0 {
return next
}
sem := make(chan struct{}, maxInFlight)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
timer := time.NewTimer(maxQueueWait)
defer timer.Stop()
select {
case sem <- struct{}{}:
defer func() { <-sem }()
next.ServeHTTP(w, r)
case <-r.Context().Done():
return
case <-timer.C:
http.Error(w, http.StatusText(http.StatusServiceUnavailable), http.StatusServiceUnavailable)
default:
select {
case sem <- struct{}{}:
defer func() { <-sem }()
next.ServeHTTP(w, r)
case <-r.Context().Done():
return
case <-timer.C:
http.Error(w, http.StatusText(http.StatusServiceUnavailable), http.StatusServiceUnavailable)
}
}
})
}