github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/interop/grpclb_fallback/client_linux.go (about) 1 /* 2 * 3 * Copyright 2019 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 // Binary grpclb_fallback is an interop test client for grpclb fallback. 20 package main 21 22 import ( 23 "context" 24 "flag" 25 "log" 26 "net" 27 "os" 28 "os/exec" 29 "syscall" 30 "time" 31 32 grpc "github.com/hxx258456/ccgo/grpc" 33 _ "github.com/hxx258456/ccgo/grpc/balancer/grpclb" 34 "github.com/hxx258456/ccgo/grpc/credentials" 35 "github.com/hxx258456/ccgo/grpc/credentials/alts" 36 "github.com/hxx258456/ccgo/grpc/credentials/google" 37 _ "github.com/hxx258456/ccgo/grpc/xds/googledirectpath" 38 "golang.org/x/sys/unix" 39 40 testgrpc "github.com/hxx258456/ccgo/grpc/interop/grpc_testing" 41 testpb "github.com/hxx258456/ccgo/grpc/interop/grpc_testing" 42 ) 43 44 var ( 45 customCredentialsType = flag.String("custom_credentials_type", "", "Client creds to use") 46 serverURI = flag.String("server_uri", "dns:///staging-grpc-directpath-fallback-test.googleapis.com:443", "The server host name") 47 unrouteLBAndBackendAddrsCmd = flag.String("unroute_lb_and_backend_addrs_cmd", "", "Command to make LB and backend address unroutable") 48 blackholeLBAndBackendAddrsCmd = flag.String("blackhole_lb_and_backend_addrs_cmd", "", "Command to make LB and backend addresses blackholed") 49 testCase = flag.String("test_case", "", 50 `Configure different test cases. Valid options are: 51 fast_fallback_before_startup : LB/backend connections fail fast before RPC's have been made; 52 fast_fallback_after_startup : LB/backend connections fail fast after RPC's have been made; 53 slow_fallback_before_startup : LB/backend connections black hole before RPC's have been made; 54 slow_fallback_after_startup : LB/backend connections black hole after RPC's have been made;`) 55 infoLog = log.New(os.Stderr, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile) 56 errorLog = log.New(os.Stderr, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile) 57 ) 58 59 func doRPCAndGetPath(client testgrpc.TestServiceClient, timeout time.Duration) testpb.GrpclbRouteType { 60 infoLog.Printf("doRPCAndGetPath timeout:%v\n", timeout) 61 ctx, cancel := context.WithTimeout(context.Background(), timeout) 62 defer cancel() 63 req := &testpb.SimpleRequest{ 64 FillGrpclbRouteType: true, 65 } 66 reply, err := client.UnaryCall(ctx, req) 67 if err != nil { 68 infoLog.Printf("doRPCAndGetPath error:%v\n", err) 69 return testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_UNKNOWN 70 } 71 g := reply.GetGrpclbRouteType() 72 infoLog.Printf("doRPCAndGetPath got grpclb route type: %v\n", g) 73 if g != testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_FALLBACK && g != testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_BACKEND { 74 errorLog.Fatalf("Expected grpclb route type to be either backend or fallback; got: %d", g) 75 } 76 return g 77 } 78 79 func dialTCPUserTimeout(ctx context.Context, addr string) (net.Conn, error) { 80 control := func(network, address string, c syscall.RawConn) error { 81 var syscallErr error 82 controlErr := c.Control(func(fd uintptr) { 83 syscallErr = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, 20000) 84 }) 85 if syscallErr != nil { 86 errorLog.Fatalf("syscall error setting sockopt TCP_USER_TIMEOUT: %v", syscallErr) 87 } 88 if controlErr != nil { 89 errorLog.Fatalf("control error setting sockopt TCP_USER_TIMEOUT: %v", syscallErr) 90 } 91 return nil 92 } 93 d := &net.Dialer{ 94 Control: control, 95 } 96 return d.DialContext(ctx, "tcp", addr) 97 } 98 99 func createTestConn() *grpc.ClientConn { 100 opts := []grpc.DialOption{ 101 grpc.WithContextDialer(dialTCPUserTimeout), 102 } 103 switch *customCredentialsType { 104 case "tls": 105 creds := credentials.NewClientTLSFromCert(nil, "") 106 opts = append(opts, grpc.WithTransportCredentials(creds)) 107 case "alts": 108 creds := alts.NewClientCreds(alts.DefaultClientOptions()) 109 opts = append(opts, grpc.WithTransportCredentials(creds)) 110 case "google_default_credentials": 111 opts = append(opts, grpc.WithCredentialsBundle(google.NewDefaultCredentials())) 112 case "compute_engine_channel_creds": 113 opts = append(opts, grpc.WithCredentialsBundle(google.NewComputeEngineCredentials())) 114 default: 115 errorLog.Fatalf("Invalid --custom_credentials_type:%v", *customCredentialsType) 116 } 117 conn, err := grpc.Dial(*serverURI, opts...) 118 if err != nil { 119 errorLog.Fatalf("Fail to dial: %v", err) 120 } 121 return conn 122 } 123 124 func runCmd(command string) { 125 infoLog.Printf("Running cmd:|%v|\n", command) 126 if err := exec.Command("bash", "-c", command).Run(); err != nil { 127 errorLog.Fatalf("error running cmd:|%v| : %v", command, err) 128 } 129 } 130 131 func waitForFallbackAndDoRPCs(client testgrpc.TestServiceClient, fallbackDeadline time.Time) { 132 fallbackRetryCount := 0 133 fellBack := false 134 for time.Now().Before(fallbackDeadline) { 135 g := doRPCAndGetPath(client, 1*time.Second) 136 if g == testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_FALLBACK { 137 infoLog.Println("Made one successul RPC to a fallback. Now expect the same for the rest.") 138 fellBack = true 139 break 140 } else if g == testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_BACKEND { 141 errorLog.Fatalf("Got RPC type backend. This suggests an error in test implementation") 142 } else { 143 infoLog.Println("Retryable RPC failure on iteration:", fallbackRetryCount) 144 } 145 fallbackRetryCount++ 146 } 147 if !fellBack { 148 infoLog.Fatalf("Didn't fall back before deadline: %v\n", fallbackDeadline) 149 } 150 for i := 0; i < 30; i++ { 151 if g := doRPCAndGetPath(client, 20*time.Second); g != testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_FALLBACK { 152 errorLog.Fatalf("Expected RPC to take grpclb route type FALLBACK. Got: %v", g) 153 } 154 time.Sleep(time.Second) 155 } 156 } 157 158 func doFastFallbackBeforeStartup() { 159 runCmd(*unrouteLBAndBackendAddrsCmd) 160 fallbackDeadline := time.Now().Add(5 * time.Second) 161 conn := createTestConn() 162 defer conn.Close() 163 client := testgrpc.NewTestServiceClient(conn) 164 waitForFallbackAndDoRPCs(client, fallbackDeadline) 165 } 166 167 func doSlowFallbackBeforeStartup() { 168 runCmd(*blackholeLBAndBackendAddrsCmd) 169 fallbackDeadline := time.Now().Add(20 * time.Second) 170 conn := createTestConn() 171 defer conn.Close() 172 client := testgrpc.NewTestServiceClient(conn) 173 waitForFallbackAndDoRPCs(client, fallbackDeadline) 174 } 175 176 func doFastFallbackAfterStartup() { 177 conn := createTestConn() 178 defer conn.Close() 179 client := testgrpc.NewTestServiceClient(conn) 180 if g := doRPCAndGetPath(client, 20*time.Second); g != testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_BACKEND { 181 errorLog.Fatalf("Expected RPC to take grpclb route type BACKEND. Got: %v", g) 182 } 183 runCmd(*unrouteLBAndBackendAddrsCmd) 184 fallbackDeadline := time.Now().Add(40 * time.Second) 185 waitForFallbackAndDoRPCs(client, fallbackDeadline) 186 } 187 188 func doSlowFallbackAfterStartup() { 189 conn := createTestConn() 190 defer conn.Close() 191 client := testgrpc.NewTestServiceClient(conn) 192 if g := doRPCAndGetPath(client, 20*time.Second); g != testpb.GrpclbRouteType_GRPCLB_ROUTE_TYPE_BACKEND { 193 errorLog.Fatalf("Expected RPC to take grpclb route type BACKEND. Got: %v", g) 194 } 195 runCmd(*blackholeLBAndBackendAddrsCmd) 196 fallbackDeadline := time.Now().Add(40 * time.Second) 197 waitForFallbackAndDoRPCs(client, fallbackDeadline) 198 } 199 200 func main() { 201 flag.Parse() 202 if len(*unrouteLBAndBackendAddrsCmd) == 0 { 203 errorLog.Fatalf("--unroute_lb_and_backend_addrs_cmd unset") 204 } 205 if len(*blackholeLBAndBackendAddrsCmd) == 0 { 206 errorLog.Fatalf("--blackhole_lb_and_backend_addrs_cmd unset") 207 } 208 switch *testCase { 209 case "fast_fallback_before_startup": 210 doFastFallbackBeforeStartup() 211 log.Printf("FastFallbackBeforeStartup done!\n") 212 case "fast_fallback_after_startup": 213 doFastFallbackAfterStartup() 214 log.Printf("FastFallbackAfterStartup done!\n") 215 case "slow_fallback_before_startup": 216 doSlowFallbackBeforeStartup() 217 log.Printf("SlowFallbackBeforeStartup done!\n") 218 case "slow_fallback_after_startup": 219 doSlowFallbackAfterStartup() 220 log.Printf("SlowFallbackAfterStartup done!\n") 221 default: 222 errorLog.Fatalf("Unsupported test case: %v", *testCase) 223 } 224 }