Skip to content

Commit 3344856

Browse files
authored
Add support to route both GRPC and HTTP over the HTTP server (weaveworks#288)
* add support for grpc on the http port Signed-off-by: Joe Elliott <number101010@gmail.com>
1 parent 102db1b commit 3344856

File tree

3 files changed

+63
-19
lines changed

3 files changed

+63
-19
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ require (
2626
github.com/prometheus/exporter-toolkit v0.8.2
2727
github.com/sercand/kuberesolver/v4 v4.0.0
2828
github.com/sirupsen/logrus v1.6.0
29+
github.com/soheilhy/cmux v0.1.5 // indirect
2930
github.com/stretchr/testify v1.8.1
3031
github.com/uber/jaeger-client-go v2.28.0+incompatible
3132
github.com/uber/jaeger-lib v2.2.0+incompatible

go.sum

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,8 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
668668
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
669669
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
670670
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
671+
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
672+
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
671673
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
672674
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
673675
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
@@ -794,6 +796,7 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R
794796
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
795797
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
796798
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
799+
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
797800
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
798801
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
799802
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=

server/server.go

Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/prometheus/client_golang/prometheus"
1818
"github.com/prometheus/client_golang/prometheus/promhttp"
1919
"github.com/prometheus/exporter-toolkit/web"
20+
"github.com/soheilhy/cmux"
2021
"golang.org/x/net/context"
2122
"golang.org/x/net/netutil"
2223
"google.golang.org/grpc"
@@ -96,6 +97,7 @@ type Config struct {
9697
HTTPMiddleware []middleware.Interface `yaml:"-"`
9798
Router *mux.Router `yaml:"-"`
9899
DoNotAddDefaultHTTPMiddleware bool `yaml:"-"`
100+
RouteHTTPToGRPC bool `yaml:"-"`
99101

100102
GPRCServerMaxRecvMsgSize int `yaml:"grpc_server_max_recv_msg_size"`
101103
GRPCServerMaxSendMsgSize int `yaml:"grpc_server_max_send_msg_size"`
@@ -185,6 +187,13 @@ type Server struct {
185187
grpcListener net.Listener
186188
httpListener net.Listener
187189

190+
// These fields are used to support grpc over the http server
191+
// if RouteHTTPToGRPC is set. the fields are kept here
192+
// so they can be initialized in New() and started in Run()
193+
grpchttpmux cmux.CMux
194+
grpcOnHTTPListener net.Listener
195+
GRPCOnHTTPServer *grpc.Server
196+
188197
HTTP *mux.Router
189198
HTTPServer *http.Server
190199
GRPC *grpc.Server
@@ -242,6 +251,15 @@ func New(cfg Config) (*Server, error) {
242251
httpListener = netutil.LimitListener(httpListener, cfg.HTTPConnLimit)
243252
}
244253

254+
var grpcOnHTTPListener net.Listener
255+
var grpchttpmux cmux.CMux
256+
if cfg.RouteHTTPToGRPC {
257+
grpchttpmux = cmux.New(httpListener)
258+
259+
httpListener = grpchttpmux.Match(cmux.HTTP1Fast())
260+
grpcOnHTTPListener = grpchttpmux.Match(cmux.HTTP2())
261+
}
262+
245263
network = cfg.GRPCListenNetwork
246264
if network == "" {
247265
network = DefaultNetwork
@@ -384,6 +402,7 @@ func New(cfg Config) (*Server, error) {
384402
grpcOptions = append(grpcOptions, grpc.Creds(grpcCreds))
385403
}
386404
grpcServer := grpc.NewServer(grpcOptions...)
405+
grpcOnHttpServer := grpc.NewServer(grpcOptions...)
387406

388407
// Setup HTTP server
389408
var router *mux.Router
@@ -446,17 +465,20 @@ func New(cfg Config) (*Server, error) {
446465
}
447466

448467
return &Server{
449-
cfg: cfg,
450-
httpListener: httpListener,
451-
grpcListener: grpcListener,
452-
handler: handler,
453-
454-
HTTP: router,
455-
HTTPServer: httpServer,
456-
GRPC: grpcServer,
457-
Log: log,
458-
Registerer: reg,
459-
Gatherer: gatherer,
468+
cfg: cfg,
469+
httpListener: httpListener,
470+
grpcListener: grpcListener,
471+
grpcOnHTTPListener: grpcOnHTTPListener,
472+
handler: handler,
473+
grpchttpmux: grpchttpmux,
474+
475+
HTTP: router,
476+
HTTPServer: httpServer,
477+
GRPC: grpcServer,
478+
GRPCOnHTTPServer: grpcOnHttpServer,
479+
Log: log,
480+
Registerer: reg,
481+
Gatherer: gatherer,
460482
}, nil
461483
}
462484

@@ -509,19 +531,37 @@ func (s *Server) Run() error {
509531

510532
go func() {
511533
err := s.GRPC.Serve(s.grpcListener)
512-
if err == grpc.ErrServerStopped {
513-
err = nil
514-
}
515-
516-
select {
517-
case errChan <- err:
518-
default:
519-
}
534+
handleGRPCError(err, errChan)
520535
}()
521536

537+
// grpchttpmux will only be set if grpchttpmux RouteHTTPToGRPC is set
538+
if s.grpchttpmux != nil {
539+
go func() {
540+
err := s.grpchttpmux.Serve()
541+
handleGRPCError(err, errChan)
542+
}()
543+
go func() {
544+
err := s.GRPCOnHTTPServer.Serve(s.grpcOnHTTPListener)
545+
handleGRPCError(err, errChan)
546+
}()
547+
}
548+
522549
return <-errChan
523550
}
524551

552+
// handleGRPCError consolidates GRPC Server error handling by sending
553+
// any error to errChan except for grpc.ErrServerStopped which is ignored.
554+
func handleGRPCError(err error, errChan chan error) {
555+
if err == grpc.ErrServerStopped {
556+
err = nil
557+
}
558+
559+
select {
560+
case errChan <- err:
561+
default:
562+
}
563+
}
564+
525565
// HTTPListenAddr exposes `net.Addr` that `Server` is listening to for HTTP connections.
526566
func (s *Server) HTTPListenAddr() net.Addr {
527567
return s.httpListener.Addr()

0 commit comments

Comments
 (0)