Skip to content
Snippets Groups Projects
Commit 7c1711be authored by ale's avatar ale
Browse files

Upgrade go-common (enforce rpc timeouts)

parent 3ecaec92
Branches
No related tags found
No related merge requests found
......@@ -221,7 +221,7 @@ func (b *balancedBackend) do(ctx context.Context, seq *sequence, req *http.Reque
client := &http.Client{
Transport: b.transportCache.getTransport(target),
}
resp, err = client.Do(req.WithContext(ctx))
resp, err = client.Do(propagateDeadline(ctx, req))
if err == nil && resp.StatusCode != 200 {
err = remoteErrorFromResponse(resp)
if !isStatusTemporary(resp.StatusCode) {
......@@ -235,6 +235,19 @@ func (b *balancedBackend) do(ctx context.Context, seq *sequence, req *http.Reque
return
}
const deadlineHeader = "X-RPC-Deadline"
// Propagate context deadline to the server using a HTTP header.
func propagateDeadline(ctx context.Context, req *http.Request) *http.Request {
req = req.WithContext(ctx)
if deadline, ok := ctx.Deadline(); ok {
req.Header.Set(deadlineHeader, strconv.FormatInt(deadline.UTC().UnixNano(), 10))
} else {
req.Header.Del(deadlineHeader)
}
return req
}
var errNoTargets = errors.New("no available backends")
type targetGenerator interface {
......
......@@ -11,6 +11,7 @@ import (
_ "net/http/pprof"
"os"
"os/signal"
"strconv"
"syscall"
"time"
......@@ -26,6 +27,7 @@ var gracefulShutdownTimeout = 3 * time.Second
type ServerConfig struct {
TLS *TLSServerConfig `yaml:"tls"`
MaxInflightRequests int `yaml:"max_inflight_requests"`
RequestTimeoutSecs int `yaml:"request_timeout"`
TrustedForwarders []string `yaml:"trusted_forwarders"`
}
......@@ -60,11 +62,18 @@ func (config *ServerConfig) buildHTTPServer(h http.Handler) (*http.Server, error
}
}
// Wrap the handler with a TimeoutHandler if 'request_timeout'
// is set.
h = addDefaultHandlers(h)
if config.RequestTimeoutSecs > 0 {
h = http.TimeoutHandler(h, time.Duration(config.RequestTimeoutSecs)*time.Second, "")
}
// These are not meant to be external-facing servers, so we
// can be generous with the timeouts to keep the number of
// reconnections low.
return &http.Server{
Handler: defaultHandler(h),
Handler: h,
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 600 * time.Second,
......@@ -134,7 +143,7 @@ func Serve(h http.Handler, config *ServerConfig, addr string) error {
return nil
}
func defaultHandler(h http.Handler) http.Handler {
func addDefaultHandlers(h http.Handler) http.Handler {
root := http.NewServeMux()
// Add an endpoint for HTTP health checking probes.
......@@ -154,11 +163,30 @@ func defaultHandler(h http.Handler) http.Handler {
// Prometheus instrumentation (requests to /metrics and
// /health are not included).
root.Handle("/", promhttp.InstrumentHandlerInFlight(inFlightRequests,
promhttp.InstrumentHandlerCounter(totalRequests, h)))
promhttp.InstrumentHandlerCounter(totalRequests,
propagateDeadline(h))))
return root
}
const deadlineHeader = "X-RPC-Deadline"
// Read an eventual deadline from the HTTP request, and set it as the
// deadline of the request context.
func propagateDeadline(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if hdr := req.Header.Get(deadlineHeader); hdr != "" {
if deadlineNano, err := strconv.ParseInt(hdr, 10, 64); err == nil {
deadline := time.Unix(0, deadlineNano)
ctx, cancel := context.WithDeadline(req.Context(), deadline)
defer cancel()
req = req.WithContext(ctx)
}
}
h.ServeHTTP(w, req)
})
}
func guessEndpointName(addr string) string {
_, port, err := net.SplitHostPort(addr)
if err != nil {
......
......@@ -5,26 +5,26 @@
{
"checksumSHA1": "oUOxU+Tw1/jOzWVP05HuGvVSC/A=",
"path": "git.autistici.org/ai3/go-common",
"revision": "c165311f4270e8a2d75d9a610abdfb54d72ae4e5",
"revisionTime": "2020-01-06T11:09:19Z"
"revision": "d4396660b1f09d2d07a7271b8a480726c5d29a6e",
"revisionTime": "2020-02-06T11:03:59Z"
},
{
"checksumSHA1": "k/t0n698YTZJR6ncd9gzSvymXsE=",
"checksumSHA1": "/uo2RHmQ/sae2RMYKm81zb6OUn4=",
"path": "git.autistici.org/ai3/go-common/clientutil",
"revision": "c165311f4270e8a2d75d9a610abdfb54d72ae4e5",
"revisionTime": "2020-01-06T11:09:19Z"
"revision": "d4396660b1f09d2d07a7271b8a480726c5d29a6e",
"revisionTime": "2020-02-06T11:03:59Z"
},
{
"checksumSHA1": "Xm0ZN1urTQaagPJ5kJlCjeGONOU=",
"checksumSHA1": "xrew5jDNLDh5bhTZ4jgO0rX0N+4=",
"path": "git.autistici.org/ai3/go-common/serverutil",
"revision": "c165311f4270e8a2d75d9a610abdfb54d72ae4e5",
"revisionTime": "2020-01-06T11:09:19Z"
"revision": "d4396660b1f09d2d07a7271b8a480726c5d29a6e",
"revisionTime": "2020-02-06T11:03:59Z"
},
{
"checksumSHA1": "y5pRYZ/NhfEOCFslPEuUZTYXcro=",
"path": "git.autistici.org/ai3/go-common/tracing",
"revision": "c165311f4270e8a2d75d9a610abdfb54d72ae4e5",
"revisionTime": "2020-01-06T11:09:19Z"
"revision": "d4396660b1f09d2d07a7271b8a480726c5d29a6e",
"revisionTime": "2020-02-06T11:03:59Z"
},
{
"checksumSHA1": "5WLGZjUV9Ly/rMdQwo9j8FJSlQA=",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment