gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/go-control-plane/pkg/test/server.go (about) 1 // Package test contains test utilities 2 package test 3 4 import ( 5 "context" 6 "fmt" 7 "gitee.com/ks-custle/core-gm/go-control-plane/pkg/server/v3" 8 "gitee.com/ks-custle/core-gm/go-control-plane/pkg/test/v3" 9 "log" 10 "net" 11 "net/http" 12 "time" 13 14 "gitee.com/ks-custle/core-gm/grpc" 15 "gitee.com/ks-custle/core-gm/grpc/keepalive" 16 17 gcplogger "gitee.com/ks-custle/core-gm/go-control-plane/pkg/log" 18 ) 19 20 const ( 21 grpcKeepaliveTime = 30 * time.Second 22 grpcKeepaliveTimeout = 5 * time.Second 23 grpcKeepaliveMinTime = 30 * time.Second 24 grpcMaxConcurrentStreams = 1000000 25 ) 26 27 // HTTPGateway is a custom implementation of [gRPC gateway](https://github.com/grpc-ecosystem/grpc-gateway) 28 // specialized to Envoy xDS API. 29 type HTTPGateway struct { 30 // Log is an optional log for errors in response write 31 Log gcplogger.Logger 32 33 Gateway server.HTTPGateway 34 } 35 36 // RunAccessLogServer starts an accesslog server. 37 func RunAccessLogServer(ctx context.Context, als *test.AccessLogService, alsPort uint) { 38 grpcServer := grpc.NewServer() 39 lis, err := net.Listen("tcp", fmt.Sprintf(":%d", alsPort)) 40 if err != nil { 41 log.Fatal(err) 42 } 43 44 test.RegisterAccessLogServer(grpcServer, als) 45 log.Printf("access log server listening on %d\n", alsPort) 46 47 go func() { 48 if err = grpcServer.Serve(lis); err != nil { 49 log.Println(err) 50 } 51 }() 52 <-ctx.Done() 53 54 grpcServer.GracefulStop() 55 } 56 57 // RunManagementServer starts an xDS server at the given port. 58 func RunManagementServer(ctx context.Context, srv server.Server, port uint) { 59 // gRPC golang library sets a very small upper bound for the number gRPC/h2 60 // streams over a single TCP connection. If a proxy multiplexes requests over 61 // a single connection to the management server, then it might lead to 62 // availability problems. Keepalive timeouts based on connection_keepalive parameter https://www.envoyproxy.io/docs/envoy/latest/configuration/overview/examples#dynamic 63 var grpcOptions []grpc.ServerOption 64 grpcOptions = append(grpcOptions, 65 grpc.MaxConcurrentStreams(grpcMaxConcurrentStreams), 66 grpc.KeepaliveParams(keepalive.ServerParameters{ 67 Time: grpcKeepaliveTime, 68 Timeout: grpcKeepaliveTimeout, 69 }), 70 grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{ 71 MinTime: grpcKeepaliveMinTime, 72 PermitWithoutStream: true, 73 }), 74 ) 75 grpcServer := grpc.NewServer(grpcOptions...) 76 77 lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) 78 if err != nil { 79 log.Fatal(err) 80 } 81 82 test.RegisterServer(grpcServer, srv) 83 84 log.Printf("management server listening on %d\n", port) 85 go func() { 86 if err = grpcServer.Serve(lis); err != nil { 87 log.Println(err) 88 } 89 }() 90 <-ctx.Done() 91 92 grpcServer.GracefulStop() 93 } 94 95 // RunManagementGateway starts an HTTP gateway to an xDS server. 96 func RunManagementGateway(ctx context.Context, srv server.Server, port uint, lg gcplogger.Logger) { 97 log.Printf("gateway listening HTTP/1.1 on %d\n", port) 98 hs := &http.Server{ 99 Addr: fmt.Sprintf(":%d", port), 100 Handler: &HTTPGateway{ 101 Gateway: server.HTTPGateway{Log: lg, Server: srv}, 102 Log: lg, 103 }, 104 } 105 go func() { 106 if err := hs.ListenAndServe(); err != nil { 107 log.Printf("failed to start listening: %s", err) 108 } 109 }() 110 <-ctx.Done() 111 112 // Cleanup our gateway if we receive a shutdown 113 if err := hs.Shutdown(ctx); err != nil { 114 log.Printf("failed to shut down: %s", err) 115 } 116 } 117 118 func (h *HTTPGateway) ServeHTTP(resp http.ResponseWriter, req *http.Request) { 119 bytes, code, err := h.Gateway.ServeHTTP(req) 120 121 if err != nil { 122 http.Error(resp, err.Error(), code) 123 return 124 } 125 126 if bytes == nil { 127 resp.WriteHeader(http.StatusNotModified) 128 return 129 } 130 131 if _, err = resp.Write(bytes); err != nil && h.Log != nil { 132 h.Log.Errorf("gateway error: %v", err) 133 } 134 }