Commit c8cbe79e authored by Janos Guljas's avatar Janos Guljas

add debugapi and gracefully shadown http servers

parent afe42f9b
...@@ -3,12 +3,18 @@ package cmd ...@@ -3,12 +3,18 @@ package cmd
import ( import (
"context" "context"
"fmt" "fmt"
"log"
"net" "net"
"net/http" "net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/janos/bee/pkg/api" "github.com/janos/bee/pkg/api"
"github.com/janos/bee/pkg/debugapi"
"github.com/janos/bee/pkg/p2p/libp2p" "github.com/janos/bee/pkg/p2p/libp2p"
"github.com/janos/bee/pkg/pingpong" "github.com/janos/bee/pkg/pingpong"
) )
...@@ -20,6 +26,7 @@ func (c *command) initStartCmd() (err error) { ...@@ -20,6 +26,7 @@ func (c *command) initStartCmd() (err error) {
optionNameP2PAddr = "p2p-addr" optionNameP2PAddr = "p2p-addr"
optionNameP2PDisableWS = "p2p-disable-ws" optionNameP2PDisableWS = "p2p-disable-ws"
optionNameP2PDisableQUIC = "p2p-disable-quic" optionNameP2PDisableQUIC = "p2p-disable-quic"
optionNameDebugAPIAddr = "debug-api-addr"
optionNameBootnodes = "bootnode" optionNameBootnodes = "bootnode"
) )
...@@ -68,19 +75,81 @@ func (c *command) initStartCmd() (err error) { ...@@ -68,19 +75,81 @@ func (c *command) initStartCmd() (err error) {
cmd.Println(addr) cmd.Println(addr)
} }
h := api.New(api.Options{ // API server
apiListener, err := net.Listen("tcp", c.config.GetString(optionNameAPIAddr))
if err != nil {
return fmt.Errorf("api listener: %w", err)
}
apiServer := &http.Server{Handler: api.New(api.Options{
P2P: p2ps, P2P: p2ps,
Pingpong: pingPong, Pingpong: pingPong,
}) })}
go func() {
cmd.Println("api address:", apiListener.Addr())
l, err := net.Listen("tcp", c.config.GetString(optionNameAPIAddr)) if err := apiServer.Serve(apiListener); err != nil && err != http.ErrServerClosed {
log.Println("api server:", err)
}
}()
// Debug API server
debugAPIListener, err := net.Listen("tcp", c.config.GetString(optionNameDebugAPIAddr))
if err != nil { if err != nil {
return fmt.Errorf("listen TCP: %w", err) return fmt.Errorf("debug api listener: %w", err)
}
debugAPIServer := &http.Server{Handler: debugapi.New(debugapi.Options{})}
go func() {
cmd.Println("debug api address:", debugAPIListener.Addr())
if err := debugAPIServer.Serve(debugAPIListener); err != nil && err != http.ErrServerClosed {
log.Println("debug api server:", err)
}
}()
// Wait for termination or interrupt signals.
// We want to clean up things at the end.
interruptChannel := make(chan os.Signal, 1)
signal.Notify(interruptChannel, syscall.SIGINT, syscall.SIGTERM)
// Block main goroutine until it is interrupted
sig := <-interruptChannel
log.Println("received signal:", sig)
// Shutdown
done := make(chan struct{})
go func() {
defer func() {
if err := recover(); err != nil {
log.Println("shutdown panic:", err)
}
}()
defer close(done)
ctx, cancel := context.WithTimeout(ctx, 15*time.Second)
defer cancel()
if err := apiServer.Shutdown(ctx); err != nil {
log.Println("api server shutdown:", err)
}
if err := debugAPIServer.Shutdown(ctx); err != nil {
log.Println("debug api server shutdown:", err)
}
}()
// If shutdown function is blocking too long,
// allow process termination by receiving another signal.
// Blocking part
select {
case sig := <-interruptChannel:
log.Printf("received signal: %v\n", sig)
case <-done:
} }
cmd.Println("http address:", l.Addr()) return nil
return http.Serve(l, h)
}, },
} }
...@@ -89,6 +158,7 @@ func (c *command) initStartCmd() (err error) { ...@@ -89,6 +158,7 @@ func (c *command) initStartCmd() (err error) {
cmd.Flags().Bool(optionNameP2PDisableWS, false, "disable P2P WebSocket protocol") cmd.Flags().Bool(optionNameP2PDisableWS, false, "disable P2P WebSocket protocol")
cmd.Flags().Bool(optionNameP2PDisableQUIC, false, "disable P2P QUIC protocol") cmd.Flags().Bool(optionNameP2PDisableQUIC, false, "disable P2P QUIC protocol")
cmd.Flags().StringSlice(optionNameBootnodes, nil, "initial nodes to connect to") cmd.Flags().StringSlice(optionNameBootnodes, nil, "initial nodes to connect to")
cmd.Flags().String(optionNameDebugAPIAddr, ":6060", "Debug HTTP API listen address")
if err := c.config.BindPFlags(cmd.Flags()); err != nil { if err := c.config.BindPFlags(cmd.Flags()); err != nil {
return err return err
......
This diff is collapsed.
package debugapi
import (
"net/http"
)
type server struct {
Options
http.Handler
}
type Options struct{}
func New(o Options) http.Handler {
s := &server{
Options: o,
}
s.setupRouting()
return s
}
package debugapi
import (
"expvar"
"net/http"
"net/http/pprof"
"github.com/gorilla/handlers"
"resenje.org/web"
)
func (s *server) setupRouting() {
internalBaseRouter := http.NewServeMux()
internalRouter := http.NewServeMux()
internalBaseRouter.Handle("/", web.ChainHandlers(
handlers.CompressHandler,
web.NoCacheHeadersHandler,
web.FinalHandler(internalRouter),
))
internalRouter.Handle("/", http.NotFoundHandler())
internalRouter.HandleFunc("/health", s.statusHandler)
internalRouter.HandleFunc("/readiness", s.statusHandler)
internalRouter.Handle("/debug/pprof/", http.HandlerFunc(pprof.Index))
internalRouter.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline))
internalRouter.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile))
internalRouter.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol))
internalRouter.Handle("/debug/pprof/trace", http.HandlerFunc(pprof.Trace))
internalRouter.Handle("/debug/vars", expvar.Handler())
s.Handler = internalBaseRouter
}
package debugapi
import (
"fmt"
"net/http"
)
func (s *server) statusHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, `{"status":"ok"}`)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment