github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/balancer/grpclb/grpclb_test.go (about) 1 /* 2 * 3 * Copyright 2016 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 package grpclb 20 21 import ( 22 "context" 23 "errors" 24 "fmt" 25 "io" 26 "net" 27 "strconv" 28 "strings" 29 "sync" 30 "sync/atomic" 31 "testing" 32 "time" 33 34 "github.com/google/go-cmp/cmp" 35 "github.com/google/go-cmp/cmp/cmpopts" 36 37 grpc "github.com/hxx258456/ccgo/grpc" 38 "github.com/hxx258456/ccgo/grpc/balancer" 39 grpclbstate "github.com/hxx258456/ccgo/grpc/balancer/grpclb/state" 40 "github.com/hxx258456/ccgo/grpc/codes" 41 "github.com/hxx258456/ccgo/grpc/credentials" 42 "github.com/hxx258456/ccgo/grpc/internal/grpctest" 43 "github.com/hxx258456/ccgo/grpc/internal/testutils" 44 "github.com/hxx258456/ccgo/grpc/metadata" 45 "github.com/hxx258456/ccgo/grpc/peer" 46 "github.com/hxx258456/ccgo/grpc/resolver" 47 "github.com/hxx258456/ccgo/grpc/resolver/manual" 48 "github.com/hxx258456/ccgo/grpc/status" 49 50 durationpb "github.com/golang/protobuf/ptypes/duration" 51 lbgrpc "github.com/hxx258456/ccgo/grpc/balancer/grpclb/grpc_lb_v1" 52 lbpb "github.com/hxx258456/ccgo/grpc/balancer/grpclb/grpc_lb_v1" 53 testpb "github.com/hxx258456/ccgo/grpc/test/grpc_testing" 54 ) 55 56 var ( 57 lbServerName = "lb.server.com" 58 beServerName = "backends.com" 59 lbToken = "iamatoken" 60 61 // Resolver replaces localhost with fakeName in Next(). 62 // Dialer replaces fakeName with localhost when dialing. 63 // This will test that custom dialer is passed from Dial to grpclb. 64 fakeName = "fake.Name" 65 ) 66 67 const ( 68 defaultTestTimeout = 10 * time.Second 69 defaultTestShortTimeout = 10 * time.Millisecond 70 testUserAgent = "test-user-agent" 71 grpclbConfig = `{"loadBalancingConfig": [{"grpclb": {}}]}` 72 ) 73 74 type s struct { 75 grpctest.Tester 76 } 77 78 func Test(t *testing.T) { 79 grpctest.RunSubTests(t, s{}) 80 } 81 82 type serverNameCheckCreds struct { 83 mu sync.Mutex 84 sn string 85 } 86 87 func (c *serverNameCheckCreds) ServerHandshake(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { 88 if _, err := io.WriteString(rawConn, c.sn); err != nil { 89 fmt.Printf("Failed to write the server name %s to the client %v", c.sn, err) 90 return nil, nil, err 91 } 92 return rawConn, nil, nil 93 } 94 func (c *serverNameCheckCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { 95 c.mu.Lock() 96 defer c.mu.Unlock() 97 b := make([]byte, len(authority)) 98 errCh := make(chan error, 1) 99 go func() { 100 _, err := rawConn.Read(b) 101 errCh <- err 102 }() 103 select { 104 case err := <-errCh: 105 if err != nil { 106 fmt.Printf("test-creds: failed to read expected authority name from the server: %v\n", err) 107 return nil, nil, err 108 } 109 case <-ctx.Done(): 110 return nil, nil, ctx.Err() 111 } 112 if authority != string(b) { 113 fmt.Printf("test-creds: got authority from ClientConn %q, expected by server %q\n", authority, string(b)) 114 return nil, nil, errors.New("received unexpected server name") 115 } 116 return rawConn, nil, nil 117 } 118 func (c *serverNameCheckCreds) Info() credentials.ProtocolInfo { 119 return credentials.ProtocolInfo{} 120 } 121 func (c *serverNameCheckCreds) Clone() credentials.TransportCredentials { 122 return &serverNameCheckCreds{} 123 } 124 func (c *serverNameCheckCreds) OverrideServerName(s string) error { 125 return nil 126 } 127 128 // fakeNameDialer replaces fakeName with localhost when dialing. 129 // This will test that custom dialer is passed from Dial to grpclb. 130 func fakeNameDialer(ctx context.Context, addr string) (net.Conn, error) { 131 addr = strings.Replace(addr, fakeName, "localhost", 1) 132 return (&net.Dialer{}).DialContext(ctx, "tcp", addr) 133 } 134 135 // merge merges the new client stats into current stats. 136 // 137 // It's a test-only method. rpcStats is defined in grpclb_picker. 138 func (s *rpcStats) merge(cs *lbpb.ClientStats) { 139 atomic.AddInt64(&s.numCallsStarted, cs.NumCallsStarted) 140 atomic.AddInt64(&s.numCallsFinished, cs.NumCallsFinished) 141 atomic.AddInt64(&s.numCallsFinishedWithClientFailedToSend, cs.NumCallsFinishedWithClientFailedToSend) 142 atomic.AddInt64(&s.numCallsFinishedKnownReceived, cs.NumCallsFinishedKnownReceived) 143 s.mu.Lock() 144 for _, perToken := range cs.CallsFinishedWithDrop { 145 s.numCallsDropped[perToken.LoadBalanceToken] += perToken.NumCalls 146 } 147 s.mu.Unlock() 148 } 149 150 func atomicEqual(a, b *int64) bool { 151 return atomic.LoadInt64(a) == atomic.LoadInt64(b) 152 } 153 154 // equal compares two rpcStats. 155 // 156 // It's a test-only method. rpcStats is defined in grpclb_picker. 157 func (s *rpcStats) equal(o *rpcStats) bool { 158 if !atomicEqual(&s.numCallsStarted, &o.numCallsStarted) { 159 return false 160 } 161 if !atomicEqual(&s.numCallsFinished, &o.numCallsFinished) { 162 return false 163 } 164 if !atomicEqual(&s.numCallsFinishedWithClientFailedToSend, &o.numCallsFinishedWithClientFailedToSend) { 165 return false 166 } 167 if !atomicEqual(&s.numCallsFinishedKnownReceived, &o.numCallsFinishedKnownReceived) { 168 return false 169 } 170 s.mu.Lock() 171 defer s.mu.Unlock() 172 o.mu.Lock() 173 defer o.mu.Unlock() 174 return cmp.Equal(s.numCallsDropped, o.numCallsDropped, cmpopts.EquateEmpty()) 175 } 176 177 func (s *rpcStats) String() string { 178 s.mu.Lock() 179 defer s.mu.Unlock() 180 return fmt.Sprintf("Started: %v, Finished: %v, FinishedWithClientFailedToSend: %v, FinishedKnownReceived: %v, Dropped: %v", 181 atomic.LoadInt64(&s.numCallsStarted), 182 atomic.LoadInt64(&s.numCallsFinished), 183 atomic.LoadInt64(&s.numCallsFinishedWithClientFailedToSend), 184 atomic.LoadInt64(&s.numCallsFinishedKnownReceived), 185 s.numCallsDropped) 186 } 187 188 type remoteBalancer struct { 189 lbgrpc.UnimplementedLoadBalancerServer 190 sls chan *lbpb.ServerList 191 statsDura time.Duration 192 done chan struct{} 193 stats *rpcStats 194 statsChan chan *lbpb.ClientStats 195 fbChan chan struct{} 196 balanceLoadCh chan struct{} // notify successful invocation of BalanceLoad 197 198 wantUserAgent string // expected user-agent in metadata of BalancerLoad 199 wantServerName string // expected server name in InitialLoadBalanceRequest 200 } 201 202 func newRemoteBalancer(wantUserAgent, wantServerName string, statsChan chan *lbpb.ClientStats) *remoteBalancer { 203 return &remoteBalancer{ 204 sls: make(chan *lbpb.ServerList, 1), 205 done: make(chan struct{}), 206 stats: newRPCStats(), 207 statsChan: statsChan, 208 fbChan: make(chan struct{}), 209 balanceLoadCh: make(chan struct{}, 1), 210 wantUserAgent: wantUserAgent, 211 wantServerName: wantServerName, 212 } 213 } 214 215 func (b *remoteBalancer) stop() { 216 close(b.sls) 217 close(b.done) 218 } 219 220 func (b *remoteBalancer) fallbackNow() { 221 b.fbChan <- struct{}{} 222 } 223 224 func (b *remoteBalancer) updateServerName(name string) { 225 b.wantServerName = name 226 } 227 228 func (b *remoteBalancer) BalanceLoad(stream lbgrpc.LoadBalancer_BalanceLoadServer) error { 229 md, ok := metadata.FromIncomingContext(stream.Context()) 230 if !ok { 231 return status.Error(codes.Internal, "failed to receive metadata") 232 } 233 if b.wantUserAgent != "" { 234 if ua := md["user-agent"]; len(ua) == 0 || !strings.HasPrefix(ua[0], b.wantUserAgent) { 235 return status.Errorf(codes.InvalidArgument, "received unexpected user-agent: %v, want prefix %q", ua, b.wantUserAgent) 236 } 237 } 238 239 req, err := stream.Recv() 240 if err != nil { 241 return err 242 } 243 initReq := req.GetInitialRequest() 244 if initReq.Name != b.wantServerName { 245 return status.Errorf(codes.InvalidArgument, "invalid service name: %q, want: %q", initReq.Name, b.wantServerName) 246 } 247 b.balanceLoadCh <- struct{}{} 248 resp := &lbpb.LoadBalanceResponse{ 249 LoadBalanceResponseType: &lbpb.LoadBalanceResponse_InitialResponse{ 250 InitialResponse: &lbpb.InitialLoadBalanceResponse{ 251 ClientStatsReportInterval: &durationpb.Duration{ 252 Seconds: int64(b.statsDura.Seconds()), 253 Nanos: int32(b.statsDura.Nanoseconds() - int64(b.statsDura.Seconds())*1e9), 254 }, 255 }, 256 }, 257 } 258 if err := stream.Send(resp); err != nil { 259 return err 260 } 261 go func() { 262 for { 263 req, err := stream.Recv() 264 if err != nil { 265 return 266 } 267 b.stats.merge(req.GetClientStats()) 268 if b.statsChan != nil && req.GetClientStats() != nil { 269 b.statsChan <- req.GetClientStats() 270 } 271 } 272 }() 273 for { 274 select { 275 case v := <-b.sls: 276 resp = &lbpb.LoadBalanceResponse{ 277 LoadBalanceResponseType: &lbpb.LoadBalanceResponse_ServerList{ 278 ServerList: v, 279 }, 280 } 281 case <-b.fbChan: 282 resp = &lbpb.LoadBalanceResponse{ 283 LoadBalanceResponseType: &lbpb.LoadBalanceResponse_FallbackResponse{ 284 FallbackResponse: &lbpb.FallbackResponse{}, 285 }, 286 } 287 case <-stream.Context().Done(): 288 return stream.Context().Err() 289 } 290 if err := stream.Send(resp); err != nil { 291 return err 292 } 293 } 294 } 295 296 type testServer struct { 297 testpb.UnimplementedTestServiceServer 298 299 addr string 300 fallback bool 301 } 302 303 const testmdkey = "testmd" 304 305 func (s *testServer) EmptyCall(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) { 306 md, ok := metadata.FromIncomingContext(ctx) 307 if !ok { 308 return nil, status.Error(codes.Internal, "failed to receive metadata") 309 } 310 if !s.fallback && (md == nil || len(md["lb-token"]) == 0 || md["lb-token"][0] != lbToken) { 311 return nil, status.Errorf(codes.Internal, "received unexpected metadata: %v", md) 312 } 313 grpc.SetTrailer(ctx, metadata.Pairs(testmdkey, s.addr)) 314 return &testpb.Empty{}, nil 315 } 316 317 func (s *testServer) FullDuplexCall(stream testpb.TestService_FullDuplexCallServer) error { 318 return nil 319 } 320 321 func startBackends(sn string, fallback bool, lis ...net.Listener) (servers []*grpc.Server) { 322 for _, l := range lis { 323 creds := &serverNameCheckCreds{ 324 sn: sn, 325 } 326 s := grpc.NewServer(grpc.Creds(creds)) 327 testpb.RegisterTestServiceServer(s, &testServer{addr: l.Addr().String(), fallback: fallback}) 328 servers = append(servers, s) 329 go func(s *grpc.Server, l net.Listener) { 330 s.Serve(l) 331 }(s, l) 332 } 333 return 334 } 335 336 func stopBackends(servers []*grpc.Server) { 337 for _, s := range servers { 338 s.Stop() 339 } 340 } 341 342 type testServers struct { 343 lbAddr string 344 ls *remoteBalancer 345 lb *grpc.Server 346 backends []*grpc.Server 347 beIPs []net.IP 348 bePorts []int 349 350 lbListener net.Listener 351 beListeners []net.Listener 352 } 353 354 func startBackendsAndRemoteLoadBalancer(numberOfBackends int, customUserAgent string, statsChan chan *lbpb.ClientStats) (tss *testServers, cleanup func(), err error) { 355 var ( 356 beListeners []net.Listener 357 ls *remoteBalancer 358 lb *grpc.Server 359 beIPs []net.IP 360 bePorts []int 361 ) 362 for i := 0; i < numberOfBackends; i++ { 363 // Start a backend. 364 beLis, e := net.Listen("tcp", "localhost:0") 365 if e != nil { 366 err = fmt.Errorf("failed to listen %v", err) 367 return 368 } 369 beIPs = append(beIPs, beLis.Addr().(*net.TCPAddr).IP) 370 bePorts = append(bePorts, beLis.Addr().(*net.TCPAddr).Port) 371 372 beListeners = append(beListeners, testutils.NewRestartableListener(beLis)) 373 } 374 backends := startBackends(beServerName, false, beListeners...) 375 376 // Start a load balancer. 377 lbLis, err := net.Listen("tcp", "localhost:0") 378 if err != nil { 379 err = fmt.Errorf("failed to create the listener for the load balancer %v", err) 380 return 381 } 382 lbLis = testutils.NewRestartableListener(lbLis) 383 lbCreds := &serverNameCheckCreds{ 384 sn: lbServerName, 385 } 386 lb = grpc.NewServer(grpc.Creds(lbCreds)) 387 ls = newRemoteBalancer(customUserAgent, beServerName, statsChan) 388 lbgrpc.RegisterLoadBalancerServer(lb, ls) 389 go func() { 390 lb.Serve(lbLis) 391 }() 392 393 tss = &testServers{ 394 lbAddr: net.JoinHostPort(fakeName, strconv.Itoa(lbLis.Addr().(*net.TCPAddr).Port)), 395 ls: ls, 396 lb: lb, 397 backends: backends, 398 beIPs: beIPs, 399 bePorts: bePorts, 400 401 lbListener: lbLis, 402 beListeners: beListeners, 403 } 404 cleanup = func() { 405 defer stopBackends(backends) 406 defer func() { 407 ls.stop() 408 lb.Stop() 409 }() 410 } 411 return 412 } 413 414 func (s) TestGRPCLB(t *testing.T) { 415 r := manual.NewBuilderWithScheme("whatever") 416 417 tss, cleanup, err := startBackendsAndRemoteLoadBalancer(1, testUserAgent, nil) 418 if err != nil { 419 t.Fatalf("failed to create new load balancer: %v", err) 420 } 421 defer cleanup() 422 423 tss.ls.sls <- &lbpb.ServerList{ 424 Servers: []*lbpb.Server{ 425 { 426 IpAddress: tss.beIPs[0], 427 Port: int32(tss.bePorts[0]), 428 LoadBalanceToken: lbToken, 429 }, 430 }, 431 } 432 433 cc, err := grpc.Dial(r.Scheme()+":///"+beServerName, 434 grpc.WithResolvers(r), 435 grpc.WithTransportCredentials(&serverNameCheckCreds{}), 436 grpc.WithContextDialer(fakeNameDialer), 437 grpc.WithUserAgent(testUserAgent)) 438 if err != nil { 439 t.Fatalf("Failed to dial to the backend %v", err) 440 } 441 defer cc.Close() 442 testC := testpb.NewTestServiceClient(cc) 443 444 rs := grpclbstate.Set(resolver.State{ServiceConfig: r.CC.ParseServiceConfig(grpclbConfig)}, 445 &grpclbstate.State{BalancerAddresses: []resolver.Address{{ 446 Addr: tss.lbAddr, 447 ServerName: lbServerName, 448 }}}) 449 r.UpdateState(rs) 450 451 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 452 defer cancel() 453 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}); err != nil { 454 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 455 } 456 } 457 458 // The remote balancer sends response with duplicates to grpclb client. 459 func (s) TestGRPCLBWeighted(t *testing.T) { 460 r := manual.NewBuilderWithScheme("whatever") 461 462 tss, cleanup, err := startBackendsAndRemoteLoadBalancer(2, "", nil) 463 if err != nil { 464 t.Fatalf("failed to create new load balancer: %v", err) 465 } 466 defer cleanup() 467 468 beServers := []*lbpb.Server{{ 469 IpAddress: tss.beIPs[0], 470 Port: int32(tss.bePorts[0]), 471 LoadBalanceToken: lbToken, 472 }, { 473 IpAddress: tss.beIPs[1], 474 Port: int32(tss.bePorts[1]), 475 LoadBalanceToken: lbToken, 476 }} 477 portsToIndex := make(map[int]int) 478 for i := range beServers { 479 portsToIndex[tss.bePorts[i]] = i 480 } 481 482 cc, err := grpc.Dial(r.Scheme()+":///"+beServerName, 483 grpc.WithResolvers(r), 484 grpc.WithTransportCredentials(&serverNameCheckCreds{}), 485 grpc.WithContextDialer(fakeNameDialer)) 486 if err != nil { 487 t.Fatalf("Failed to dial to the backend %v", err) 488 } 489 defer cc.Close() 490 testC := testpb.NewTestServiceClient(cc) 491 492 rs := grpclbstate.Set(resolver.State{ServiceConfig: r.CC.ParseServiceConfig(grpclbConfig)}, 493 &grpclbstate.State{BalancerAddresses: []resolver.Address{{ 494 Addr: tss.lbAddr, 495 ServerName: lbServerName, 496 }}}) 497 r.UpdateState(rs) 498 499 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 500 defer cancel() 501 sequences := []string{"00101", "00011"} 502 for _, seq := range sequences { 503 var ( 504 bes []*lbpb.Server 505 p peer.Peer 506 result string 507 ) 508 for _, s := range seq { 509 bes = append(bes, beServers[s-'0']) 510 } 511 tss.ls.sls <- &lbpb.ServerList{Servers: bes} 512 513 for i := 0; i < 1000; i++ { 514 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 515 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 516 } 517 result += strconv.Itoa(portsToIndex[p.Addr.(*net.TCPAddr).Port]) 518 } 519 // The generated result will be in format of "0010100101". 520 if !strings.Contains(result, strings.Repeat(seq, 2)) { 521 t.Errorf("got result sequence %q, want patten %q", result, seq) 522 } 523 } 524 } 525 526 func (s) TestDropRequest(t *testing.T) { 527 r := manual.NewBuilderWithScheme("whatever") 528 529 tss, cleanup, err := startBackendsAndRemoteLoadBalancer(2, "", nil) 530 if err != nil { 531 t.Fatalf("failed to create new load balancer: %v", err) 532 } 533 defer cleanup() 534 tss.ls.sls <- &lbpb.ServerList{ 535 Servers: []*lbpb.Server{{ 536 IpAddress: tss.beIPs[0], 537 Port: int32(tss.bePorts[0]), 538 LoadBalanceToken: lbToken, 539 Drop: false, 540 }, { 541 IpAddress: tss.beIPs[1], 542 Port: int32(tss.bePorts[1]), 543 LoadBalanceToken: lbToken, 544 Drop: false, 545 }, { 546 Drop: true, 547 }}, 548 } 549 550 cc, err := grpc.Dial(r.Scheme()+":///"+beServerName, 551 grpc.WithResolvers(r), 552 grpc.WithTransportCredentials(&serverNameCheckCreds{}), 553 grpc.WithContextDialer(fakeNameDialer)) 554 if err != nil { 555 t.Fatalf("Failed to dial to the backend %v", err) 556 } 557 defer cc.Close() 558 testC := testpb.NewTestServiceClient(cc) 559 560 rs := grpclbstate.Set(resolver.State{ServiceConfig: r.CC.ParseServiceConfig(grpclbConfig)}, 561 &grpclbstate.State{BalancerAddresses: []resolver.Address{{ 562 Addr: tss.lbAddr, 563 ServerName: lbServerName, 564 }}}) 565 r.UpdateState(rs) 566 567 var ( 568 i int 569 p peer.Peer 570 ) 571 const ( 572 // Poll to wait for something to happen. Total timeout 1 second. Sleep 1 573 // ms each loop, and do at most 1000 loops. 574 sleepEachLoop = time.Millisecond 575 loopCount = int(time.Second / sleepEachLoop) 576 ) 577 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 578 defer cancel() 579 // Make a non-fail-fast RPC and wait for it to succeed. 580 for i = 0; i < loopCount; i++ { 581 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err == nil { 582 break 583 } 584 time.Sleep(sleepEachLoop) 585 } 586 if i >= loopCount { 587 t.Fatalf("timeout waiting for the first connection to become ready. EmptyCall(_, _) = _, %v, want _, <nil>", err) 588 } 589 590 // Make RPCs until the peer is different. So we know both connections are 591 // READY. 592 for i = 0; i < loopCount; i++ { 593 var temp peer.Peer 594 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&temp)); err == nil { 595 if temp.Addr.(*net.TCPAddr).Port != p.Addr.(*net.TCPAddr).Port { 596 break 597 } 598 } 599 time.Sleep(sleepEachLoop) 600 } 601 if i >= loopCount { 602 t.Fatalf("timeout waiting for the second connection to become ready") 603 } 604 605 // More RPCs until drop happens. So we know the picker index, and the 606 // expected behavior of following RPCs. 607 for i = 0; i < loopCount; i++ { 608 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); status.Code(err) == codes.Unavailable { 609 break 610 } 611 time.Sleep(sleepEachLoop) 612 } 613 if i >= loopCount { 614 t.Fatalf("timeout waiting for drop. EmptyCall(_, _) = _, %v, want _, <Unavailable>", err) 615 } 616 617 select { 618 case <-ctx.Done(): 619 t.Fatal("timed out", ctx.Err()) 620 default: 621 } 622 for _, failfast := range []bool{true, false} { 623 for i := 0; i < 3; i++ { 624 // 1st RPCs pick the first item in server list. They should succeed 625 // since they choose the non-drop-request backend according to the 626 // round robin policy. 627 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(!failfast)); err != nil { 628 t.Errorf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 629 } 630 // 2nd RPCs pick the second item in server list. They should succeed 631 // since they choose the non-drop-request backend according to the 632 // round robin policy. 633 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(!failfast)); err != nil { 634 t.Errorf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 635 } 636 // 3rd RPCs should fail, because they pick last item in server list, 637 // with Drop set to true. 638 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(!failfast)); status.Code(err) != codes.Unavailable { 639 t.Errorf("%v.EmptyCall(_, _) = _, %v, want _, %s", testC, err, codes.Unavailable) 640 } 641 } 642 } 643 644 // Make one more RPC to move the picker index one step further, so it's not 645 // 0. The following RPCs will test that drop index is not reset. If picker 646 // index is at 0, we cannot tell whether it's reset or not. 647 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil { 648 t.Errorf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 649 } 650 651 tss.backends[0].Stop() 652 // This last pick was backend 0. Closing backend 0 doesn't reset drop index 653 // (for level 1 picking), so the following picks will be (backend1, drop, 654 // backend1), instead of (backend, backend, drop) if drop index was reset. 655 time.Sleep(time.Second) 656 for i := 0; i < 3; i++ { 657 var p peer.Peer 658 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 659 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 660 } 661 if want := tss.bePorts[1]; p.Addr.(*net.TCPAddr).Port != want { 662 t.Errorf("got peer: %v, want peer port: %v", p.Addr, want) 663 } 664 665 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); status.Code(err) != codes.Unavailable { 666 t.Errorf("%v.EmptyCall(_, _) = _, %v, want _, %s", testC, err, codes.Unavailable) 667 } 668 669 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 670 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 671 } 672 if want := tss.bePorts[1]; p.Addr.(*net.TCPAddr).Port != want { 673 t.Errorf("got peer: %v, want peer port: %v", p.Addr, want) 674 } 675 } 676 } 677 678 // When the balancer in use disconnects, grpclb should connect to the next address from resolved balancer address list. 679 func (s) TestBalancerDisconnects(t *testing.T) { 680 r := manual.NewBuilderWithScheme("whatever") 681 682 var ( 683 tests []*testServers 684 lbs []*grpc.Server 685 ) 686 for i := 0; i < 2; i++ { 687 tss, cleanup, err := startBackendsAndRemoteLoadBalancer(1, "", nil) 688 if err != nil { 689 t.Fatalf("failed to create new load balancer: %v", err) 690 } 691 defer cleanup() 692 693 tss.ls.sls <- &lbpb.ServerList{ 694 Servers: []*lbpb.Server{ 695 { 696 IpAddress: tss.beIPs[0], 697 Port: int32(tss.bePorts[0]), 698 LoadBalanceToken: lbToken, 699 }, 700 }, 701 } 702 703 tests = append(tests, tss) 704 lbs = append(lbs, tss.lb) 705 } 706 707 cc, err := grpc.Dial(r.Scheme()+":///"+beServerName, 708 grpc.WithResolvers(r), 709 grpc.WithTransportCredentials(&serverNameCheckCreds{}), 710 grpc.WithContextDialer(fakeNameDialer)) 711 if err != nil { 712 t.Fatalf("Failed to dial to the backend %v", err) 713 } 714 defer cc.Close() 715 testC := testpb.NewTestServiceClient(cc) 716 717 rs := grpclbstate.Set(resolver.State{ServiceConfig: r.CC.ParseServiceConfig(grpclbConfig)}, 718 &grpclbstate.State{BalancerAddresses: []resolver.Address{ 719 { 720 Addr: tests[0].lbAddr, 721 ServerName: lbServerName, 722 }, 723 { 724 Addr: tests[1].lbAddr, 725 ServerName: lbServerName, 726 }, 727 }}) 728 r.UpdateState(rs) 729 730 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 731 defer cancel() 732 var p peer.Peer 733 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 734 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 735 } 736 if p.Addr.(*net.TCPAddr).Port != tests[0].bePorts[0] { 737 t.Fatalf("got peer: %v, want peer port: %v", p.Addr, tests[0].bePorts[0]) 738 } 739 740 lbs[0].Stop() 741 // Stop balancer[0], balancer[1] should be used by grpclb. 742 // Check peer address to see if that happened. 743 for i := 0; i < 1000; i++ { 744 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 745 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 746 } 747 if p.Addr.(*net.TCPAddr).Port == tests[1].bePorts[0] { 748 return 749 } 750 time.Sleep(time.Millisecond) 751 } 752 t.Fatalf("No RPC sent to second backend after 1 second") 753 } 754 755 func (s) TestFallback(t *testing.T) { 756 balancer.Register(newLBBuilderWithFallbackTimeout(100 * time.Millisecond)) 757 defer balancer.Register(newLBBuilder()) 758 r := manual.NewBuilderWithScheme("whatever") 759 760 // Start a remote balancer and a backend. Push the backend address to the 761 // remote balancer. 762 tss, cleanup, err := startBackendsAndRemoteLoadBalancer(1, "", nil) 763 if err != nil { 764 t.Fatalf("failed to create new load balancer: %v", err) 765 } 766 defer cleanup() 767 sl := &lbpb.ServerList{ 768 Servers: []*lbpb.Server{ 769 { 770 IpAddress: tss.beIPs[0], 771 Port: int32(tss.bePorts[0]), 772 LoadBalanceToken: lbToken, 773 }, 774 }, 775 } 776 tss.ls.sls <- sl 777 778 // Start a standalone backend for fallback. 779 beLis, err := net.Listen("tcp", "localhost:0") 780 if err != nil { 781 t.Fatalf("Failed to listen %v", err) 782 } 783 defer beLis.Close() 784 standaloneBEs := startBackends(beServerName, true, beLis) 785 defer stopBackends(standaloneBEs) 786 787 cc, err := grpc.Dial(r.Scheme()+":///"+beServerName, 788 grpc.WithResolvers(r), 789 grpc.WithTransportCredentials(&serverNameCheckCreds{}), 790 grpc.WithContextDialer(fakeNameDialer)) 791 if err != nil { 792 t.Fatalf("Failed to dial to the backend %v", err) 793 } 794 defer cc.Close() 795 testC := testpb.NewTestServiceClient(cc) 796 797 // Push an update to the resolver with fallback backend address stored in 798 // the `Addresses` field and an invalid remote balancer address stored in 799 // attributes, which will cause fallback behavior to be invoked. 800 rs := resolver.State{ 801 Addresses: []resolver.Address{{Addr: beLis.Addr().String()}}, 802 ServiceConfig: r.CC.ParseServiceConfig(grpclbConfig), 803 } 804 rs = grpclbstate.Set(rs, &grpclbstate.State{BalancerAddresses: []resolver.Address{{Addr: "invalid.address", ServerName: lbServerName}}}) 805 r.UpdateState(rs) 806 807 // Make an RPC and verify that it got routed to the fallback backend. 808 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 809 defer cancel() 810 var p peer.Peer 811 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 812 t.Fatalf("_.EmptyCall(_, _) = _, %v, want _, <nil>", err) 813 } 814 if p.Addr.String() != beLis.Addr().String() { 815 t.Fatalf("got peer: %v, want peer: %v", p.Addr, beLis.Addr()) 816 } 817 818 // Push another update to the resolver, this time with a valid balancer 819 // address in the attributes field. 820 rs = resolver.State{ 821 ServiceConfig: r.CC.ParseServiceConfig(grpclbConfig), 822 Addresses: []resolver.Address{{Addr: beLis.Addr().String()}}, 823 } 824 rs = grpclbstate.Set(rs, &grpclbstate.State{BalancerAddresses: []resolver.Address{{Addr: tss.lbAddr, ServerName: lbServerName}}}) 825 r.UpdateState(rs) 826 select { 827 case <-ctx.Done(): 828 t.Fatalf("timeout when waiting for BalanceLoad RPC to be called on the remote balancer") 829 case <-tss.ls.balanceLoadCh: 830 } 831 832 // Wait for RPCs to get routed to the backend behind the remote balancer. 833 var backendUsed bool 834 for i := 0; i < 1000; i++ { 835 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 836 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 837 } 838 if p.Addr.(*net.TCPAddr).Port == tss.bePorts[0] { 839 backendUsed = true 840 break 841 } 842 time.Sleep(time.Millisecond) 843 } 844 if !backendUsed { 845 t.Fatalf("No RPC sent to backend behind remote balancer after 1 second") 846 } 847 848 // Close backend and remote balancer connections, should use fallback. 849 tss.beListeners[0].(*testutils.RestartableListener).Stop() 850 tss.lbListener.(*testutils.RestartableListener).Stop() 851 852 var fallbackUsed bool 853 for i := 0; i < 2000; i++ { 854 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 855 // Because we are hard-closing the connection, above, it's possible 856 // for the first RPC attempt to be sent on the old connection, 857 // which will lead to an Unavailable error when it is closed. 858 // Ignore unavailable errors. 859 if status.Code(err) != codes.Unavailable { 860 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 861 } 862 } 863 if p.Addr.String() == beLis.Addr().String() { 864 fallbackUsed = true 865 break 866 } 867 time.Sleep(time.Millisecond) 868 } 869 if !fallbackUsed { 870 t.Fatalf("No RPC sent to fallback after 2 seconds") 871 } 872 873 // Restart backend and remote balancer, should not use fallback backend. 874 tss.beListeners[0].(*testutils.RestartableListener).Restart() 875 tss.lbListener.(*testutils.RestartableListener).Restart() 876 tss.ls.sls <- sl 877 878 var backendUsed2 bool 879 for i := 0; i < 2000; i++ { 880 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 881 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 882 } 883 if p.Addr.(*net.TCPAddr).Port == tss.bePorts[0] { 884 backendUsed2 = true 885 break 886 } 887 time.Sleep(time.Millisecond) 888 } 889 if !backendUsed2 { 890 t.Fatalf("No RPC sent to backend behind remote balancer after 2 seconds") 891 } 892 } 893 894 func (s) TestExplicitFallback(t *testing.T) { 895 r := manual.NewBuilderWithScheme("whatever") 896 897 // Start a remote balancer and a backend. Push the backend address to the 898 // remote balancer. 899 tss, cleanup, err := startBackendsAndRemoteLoadBalancer(1, "", nil) 900 if err != nil { 901 t.Fatalf("failed to create new load balancer: %v", err) 902 } 903 defer cleanup() 904 sl := &lbpb.ServerList{ 905 Servers: []*lbpb.Server{ 906 { 907 IpAddress: tss.beIPs[0], 908 Port: int32(tss.bePorts[0]), 909 LoadBalanceToken: lbToken, 910 }, 911 }, 912 } 913 tss.ls.sls <- sl 914 915 // Start a standalone backend for fallback. 916 beLis, err := net.Listen("tcp", "localhost:0") 917 if err != nil { 918 t.Fatalf("Failed to listen %v", err) 919 } 920 defer beLis.Close() 921 standaloneBEs := startBackends(beServerName, true, beLis) 922 defer stopBackends(standaloneBEs) 923 924 cc, err := grpc.Dial(r.Scheme()+":///"+beServerName, 925 grpc.WithResolvers(r), 926 grpc.WithTransportCredentials(&serverNameCheckCreds{}), 927 grpc.WithContextDialer(fakeNameDialer)) 928 if err != nil { 929 t.Fatalf("Failed to dial to the backend %v", err) 930 } 931 defer cc.Close() 932 testC := testpb.NewTestServiceClient(cc) 933 934 rs := resolver.State{ 935 Addresses: []resolver.Address{{Addr: beLis.Addr().String()}}, 936 ServiceConfig: r.CC.ParseServiceConfig(grpclbConfig), 937 } 938 rs = grpclbstate.Set(rs, &grpclbstate.State{BalancerAddresses: []resolver.Address{{Addr: tss.lbAddr, ServerName: lbServerName}}}) 939 r.UpdateState(rs) 940 941 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 942 defer cancel() 943 var p peer.Peer 944 var backendUsed bool 945 for i := 0; i < 2000; i++ { 946 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 947 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 948 } 949 if p.Addr.(*net.TCPAddr).Port == tss.bePorts[0] { 950 backendUsed = true 951 break 952 } 953 time.Sleep(time.Millisecond) 954 } 955 if !backendUsed { 956 t.Fatalf("No RPC sent to backend behind remote balancer after 2 seconds") 957 } 958 959 // Send fallback signal from remote balancer; should use fallback. 960 tss.ls.fallbackNow() 961 962 var fallbackUsed bool 963 for i := 0; i < 2000; i++ { 964 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 965 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 966 } 967 if p.Addr.String() == beLis.Addr().String() { 968 fallbackUsed = true 969 break 970 } 971 time.Sleep(time.Millisecond) 972 } 973 if !fallbackUsed { 974 t.Fatalf("No RPC sent to fallback after 2 seconds") 975 } 976 977 // Send another server list; should use backends again. 978 tss.ls.sls <- sl 979 980 backendUsed = false 981 for i := 0; i < 2000; i++ { 982 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 983 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 984 } 985 if p.Addr.(*net.TCPAddr).Port == tss.bePorts[0] { 986 backendUsed = true 987 break 988 } 989 time.Sleep(time.Millisecond) 990 } 991 if !backendUsed { 992 t.Fatalf("No RPC sent to backend behind remote balancer after 2 seconds") 993 } 994 } 995 996 func (s) TestFallBackWithNoServerAddress(t *testing.T) { 997 resolveNowCh := testutils.NewChannel() 998 r := manual.NewBuilderWithScheme("whatever") 999 r.ResolveNowCallback = func(resolver.ResolveNowOptions) { 1000 ctx, cancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) 1001 defer cancel() 1002 if err := resolveNowCh.SendContext(ctx, nil); err != nil { 1003 t.Error("timeout when attemping to send on resolverNowCh") 1004 } 1005 } 1006 1007 // Start a remote balancer and a backend. Push the backend address to the 1008 // remote balancer yet. 1009 tss, cleanup, err := startBackendsAndRemoteLoadBalancer(1, "", nil) 1010 if err != nil { 1011 t.Fatalf("failed to create new load balancer: %v", err) 1012 } 1013 defer cleanup() 1014 sl := &lbpb.ServerList{ 1015 Servers: []*lbpb.Server{ 1016 { 1017 IpAddress: tss.beIPs[0], 1018 Port: int32(tss.bePorts[0]), 1019 LoadBalanceToken: lbToken, 1020 }, 1021 }, 1022 } 1023 1024 // Start a standalone backend for fallback. 1025 beLis, err := net.Listen("tcp", "localhost:0") 1026 if err != nil { 1027 t.Fatalf("Failed to listen %v", err) 1028 } 1029 defer beLis.Close() 1030 standaloneBEs := startBackends(beServerName, true, beLis) 1031 defer stopBackends(standaloneBEs) 1032 1033 cc, err := grpc.Dial(r.Scheme()+":///"+beServerName, 1034 grpc.WithResolvers(r), 1035 grpc.WithTransportCredentials(&serverNameCheckCreds{}), 1036 grpc.WithContextDialer(fakeNameDialer)) 1037 if err != nil { 1038 t.Fatalf("Failed to dial to the backend %v", err) 1039 } 1040 defer cc.Close() 1041 testC := testpb.NewTestServiceClient(cc) 1042 1043 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 1044 defer cancel() 1045 for i := 0; i < 2; i++ { 1046 // Send an update with only backend address. grpclb should enter 1047 // fallback and use the fallback backend. 1048 r.UpdateState(resolver.State{ 1049 Addresses: []resolver.Address{{Addr: beLis.Addr().String()}}, 1050 ServiceConfig: r.CC.ParseServiceConfig(grpclbConfig), 1051 }) 1052 1053 sCtx, sCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) 1054 defer sCancel() 1055 if _, err := resolveNowCh.Receive(sCtx); err != context.DeadlineExceeded { 1056 t.Fatalf("unexpected resolveNow when grpclb gets no balancer address 1111, %d", i) 1057 } 1058 1059 var p peer.Peer 1060 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 1061 t.Fatalf("_.EmptyCall(_, _) = _, %v, want _, <nil>", err) 1062 } 1063 if p.Addr.String() != beLis.Addr().String() { 1064 t.Fatalf("got peer: %v, want peer: %v", p.Addr, beLis.Addr()) 1065 } 1066 1067 sCtx, sCancel = context.WithTimeout(context.Background(), defaultTestShortTimeout) 1068 defer sCancel() 1069 if _, err := resolveNowCh.Receive(sCtx); err != context.DeadlineExceeded { 1070 t.Errorf("unexpected resolveNow when grpclb gets no balancer address 2222, %d", i) 1071 } 1072 1073 tss.ls.sls <- sl 1074 // Send an update with balancer address. The backends behind grpclb should 1075 // be used. 1076 rs := resolver.State{ 1077 Addresses: []resolver.Address{{Addr: beLis.Addr().String()}}, 1078 ServiceConfig: r.CC.ParseServiceConfig(grpclbConfig), 1079 } 1080 rs = grpclbstate.Set(rs, &grpclbstate.State{BalancerAddresses: []resolver.Address{{Addr: tss.lbAddr, ServerName: lbServerName}}}) 1081 r.UpdateState(rs) 1082 1083 select { 1084 case <-ctx.Done(): 1085 t.Fatalf("timeout when waiting for BalanceLoad RPC to be called on the remote balancer") 1086 case <-tss.ls.balanceLoadCh: 1087 } 1088 1089 var backendUsed bool 1090 for i := 0; i < 1000; i++ { 1091 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 1092 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 1093 } 1094 if p.Addr.(*net.TCPAddr).Port == tss.bePorts[0] { 1095 backendUsed = true 1096 break 1097 } 1098 time.Sleep(time.Millisecond) 1099 } 1100 if !backendUsed { 1101 t.Fatalf("No RPC sent to backend behind remote balancer after 1 second") 1102 } 1103 } 1104 } 1105 1106 func (s) TestGRPCLBPickFirst(t *testing.T) { 1107 r := manual.NewBuilderWithScheme("whatever") 1108 1109 tss, cleanup, err := startBackendsAndRemoteLoadBalancer(3, "", nil) 1110 if err != nil { 1111 t.Fatalf("failed to create new load balancer: %v", err) 1112 } 1113 defer cleanup() 1114 1115 beServers := []*lbpb.Server{{ 1116 IpAddress: tss.beIPs[0], 1117 Port: int32(tss.bePorts[0]), 1118 LoadBalanceToken: lbToken, 1119 }, { 1120 IpAddress: tss.beIPs[1], 1121 Port: int32(tss.bePorts[1]), 1122 LoadBalanceToken: lbToken, 1123 }, { 1124 IpAddress: tss.beIPs[2], 1125 Port: int32(tss.bePorts[2]), 1126 LoadBalanceToken: lbToken, 1127 }} 1128 portsToIndex := make(map[int]int) 1129 for i := range beServers { 1130 portsToIndex[tss.bePorts[i]] = i 1131 } 1132 1133 cc, err := grpc.Dial(r.Scheme()+":///"+beServerName, 1134 grpc.WithResolvers(r), 1135 grpc.WithTransportCredentials(&serverNameCheckCreds{}), 1136 grpc.WithContextDialer(fakeNameDialer)) 1137 if err != nil { 1138 t.Fatalf("Failed to dial to the backend %v", err) 1139 } 1140 defer cc.Close() 1141 testC := testpb.NewTestServiceClient(cc) 1142 1143 var ( 1144 p peer.Peer 1145 result string 1146 ) 1147 tss.ls.sls <- &lbpb.ServerList{Servers: beServers[0:3]} 1148 1149 // Start with sub policy pick_first. 1150 rs := resolver.State{ServiceConfig: r.CC.ParseServiceConfig(`{"loadBalancingConfig":[{"grpclb":{"childPolicy":[{"pick_first":{}}]}}]}`)} 1151 r.UpdateState(grpclbstate.Set(rs, &grpclbstate.State{BalancerAddresses: []resolver.Address{{Addr: tss.lbAddr, ServerName: lbServerName}}})) 1152 1153 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 1154 defer cancel() 1155 result = "" 1156 for i := 0; i < 1000; i++ { 1157 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 1158 t.Fatalf("_.EmptyCall(_, _) = _, %v, want _, <nil>", err) 1159 } 1160 result += strconv.Itoa(portsToIndex[p.Addr.(*net.TCPAddr).Port]) 1161 } 1162 if seq := "00000"; !strings.Contains(result, strings.Repeat(seq, 100)) { 1163 t.Errorf("got result sequence %q, want patten %q", result, seq) 1164 } 1165 1166 tss.ls.sls <- &lbpb.ServerList{Servers: beServers[2:]} 1167 result = "" 1168 for i := 0; i < 1000; i++ { 1169 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 1170 t.Fatalf("_.EmptyCall(_, _) = _, %v, want _, <nil>", err) 1171 } 1172 result += strconv.Itoa(portsToIndex[p.Addr.(*net.TCPAddr).Port]) 1173 } 1174 if seq := "22222"; !strings.Contains(result, strings.Repeat(seq, 100)) { 1175 t.Errorf("got result sequence %q, want patten %q", result, seq) 1176 } 1177 1178 tss.ls.sls <- &lbpb.ServerList{Servers: beServers[1:]} 1179 result = "" 1180 for i := 0; i < 1000; i++ { 1181 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 1182 t.Fatalf("_.EmptyCall(_, _) = _, %v, want _, <nil>", err) 1183 } 1184 result += strconv.Itoa(portsToIndex[p.Addr.(*net.TCPAddr).Port]) 1185 } 1186 if seq := "22222"; !strings.Contains(result, strings.Repeat(seq, 100)) { 1187 t.Errorf("got result sequence %q, want patten %q", result, seq) 1188 } 1189 1190 // Switch sub policy to roundrobin. 1191 rs = grpclbstate.Set(resolver.State{ServiceConfig: r.CC.ParseServiceConfig(grpclbConfig)}, 1192 &grpclbstate.State{BalancerAddresses: []resolver.Address{{ 1193 Addr: tss.lbAddr, 1194 ServerName: lbServerName, 1195 }}}) 1196 r.UpdateState(rs) 1197 1198 result = "" 1199 for i := 0; i < 1000; i++ { 1200 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 1201 t.Fatalf("_.EmptyCall(_, _) = _, %v, want _, <nil>", err) 1202 } 1203 result += strconv.Itoa(portsToIndex[p.Addr.(*net.TCPAddr).Port]) 1204 } 1205 if seq := "121212"; !strings.Contains(result, strings.Repeat(seq, 100)) { 1206 t.Errorf("got result sequence %q, want patten %q", result, seq) 1207 } 1208 1209 tss.ls.sls <- &lbpb.ServerList{Servers: beServers[0:3]} 1210 result = "" 1211 for i := 0; i < 1000; i++ { 1212 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true), grpc.Peer(&p)); err != nil { 1213 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 1214 } 1215 result += strconv.Itoa(portsToIndex[p.Addr.(*net.TCPAddr).Port]) 1216 } 1217 if seq := "012012012"; !strings.Contains(result, strings.Repeat(seq, 2)) { 1218 t.Errorf("got result sequence %q, want patten %q", result, seq) 1219 } 1220 } 1221 1222 func (s) TestGRPCLBBackendConnectionErrorPropagation(t *testing.T) { 1223 r := manual.NewBuilderWithScheme("whatever") 1224 1225 // Start up an LB which will tells the client to fall back right away. 1226 tss, cleanup, err := startBackendsAndRemoteLoadBalancer(0, "", nil) 1227 if err != nil { 1228 t.Fatalf("failed to create new load balancer: %v", err) 1229 } 1230 defer cleanup() 1231 1232 // Start a standalone backend, to be used during fallback. The creds 1233 // are intentionally misconfigured in order to simulate failure of a 1234 // security handshake. 1235 beLis, err := net.Listen("tcp", "localhost:0") 1236 if err != nil { 1237 t.Fatalf("Failed to listen %v", err) 1238 } 1239 defer beLis.Close() 1240 standaloneBEs := startBackends("arbitrary.invalid.name", true, beLis) 1241 defer stopBackends(standaloneBEs) 1242 1243 cc, err := grpc.Dial(r.Scheme()+":///"+beServerName, 1244 grpc.WithResolvers(r), 1245 grpc.WithTransportCredentials(&serverNameCheckCreds{}), 1246 grpc.WithContextDialer(fakeNameDialer)) 1247 if err != nil { 1248 t.Fatalf("Failed to dial to the backend %v", err) 1249 } 1250 defer cc.Close() 1251 testC := testpb.NewTestServiceClient(cc) 1252 1253 rs := resolver.State{ 1254 Addresses: []resolver.Address{{Addr: beLis.Addr().String()}}, 1255 ServiceConfig: r.CC.ParseServiceConfig(grpclbConfig), 1256 } 1257 rs = grpclbstate.Set(rs, &grpclbstate.State{BalancerAddresses: []resolver.Address{{Addr: tss.lbAddr, ServerName: lbServerName}}}) 1258 r.UpdateState(rs) 1259 1260 // If https://github.com/grpc/grpc-go/blob/65cabd74d8e18d7347fecd414fa8d83a00035f5f/balancer/grpclb/grpclb_test.go#L103 1261 // changes, then expectedErrMsg may need to be updated. 1262 const expectedErrMsg = "received unexpected server name" 1263 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 1264 defer cancel() 1265 var wg sync.WaitGroup 1266 wg.Add(1) 1267 go func() { 1268 tss.ls.fallbackNow() 1269 wg.Done() 1270 }() 1271 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}); err == nil || !strings.Contains(err.Error(), expectedErrMsg) { 1272 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, rpc error containing substring: %q", testC, err, expectedErrMsg) 1273 } 1274 wg.Wait() 1275 } 1276 1277 func testGRPCLBEmptyServerList(t *testing.T, svcfg string) { 1278 r := manual.NewBuilderWithScheme("whatever") 1279 1280 tss, cleanup, err := startBackendsAndRemoteLoadBalancer(1, "", nil) 1281 if err != nil { 1282 t.Fatalf("failed to create new load balancer: %v", err) 1283 } 1284 defer cleanup() 1285 1286 beServers := []*lbpb.Server{{ 1287 IpAddress: tss.beIPs[0], 1288 Port: int32(tss.bePorts[0]), 1289 LoadBalanceToken: lbToken, 1290 }} 1291 1292 creds := serverNameCheckCreds{} 1293 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 1294 defer cancel() 1295 cc, err := grpc.DialContext(ctx, r.Scheme()+":///"+beServerName, 1296 grpc.WithResolvers(r), 1297 grpc.WithTransportCredentials(&creds), 1298 grpc.WithContextDialer(fakeNameDialer)) 1299 if err != nil { 1300 t.Fatalf("Failed to dial to the backend %v", err) 1301 } 1302 defer cc.Close() 1303 testC := testpb.NewTestServiceClient(cc) 1304 1305 tss.ls.sls <- &lbpb.ServerList{Servers: beServers} 1306 1307 rs := grpclbstate.Set(resolver.State{ServiceConfig: r.CC.ParseServiceConfig(svcfg)}, 1308 &grpclbstate.State{BalancerAddresses: []resolver.Address{{ 1309 Addr: tss.lbAddr, 1310 ServerName: lbServerName, 1311 }}}) 1312 r.UpdateState(rs) 1313 t.Log("Perform an initial RPC and expect it to succeed...") 1314 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil { 1315 t.Fatalf("Initial _.EmptyCall(_, _) = _, %v, want _, <nil>", err) 1316 } 1317 t.Log("Now send an empty server list. Wait until we see an RPC failure to make sure the client got it...") 1318 tss.ls.sls <- &lbpb.ServerList{} 1319 gotError := false 1320 for i := 0; i < 100; i++ { 1321 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}); err != nil { 1322 gotError = true 1323 break 1324 } 1325 } 1326 if !gotError { 1327 t.Fatalf("Expected to eventually see an RPC fail after the grpclb sends an empty server list, but none did.") 1328 } 1329 t.Log("Now send a non-empty server list. A wait-for-ready RPC should now succeed...") 1330 tss.ls.sls <- &lbpb.ServerList{Servers: beServers} 1331 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil { 1332 t.Fatalf("Final _.EmptyCall(_, _) = _, %v, want _, <nil>", err) 1333 } 1334 } 1335 1336 func (s) TestGRPCLBEmptyServerListRoundRobin(t *testing.T) { 1337 testGRPCLBEmptyServerList(t, `{"loadBalancingConfig":[{"grpclb":{"childPolicy":[{"round_robin":{}}]}}]}`) 1338 } 1339 1340 func (s) TestGRPCLBEmptyServerListPickFirst(t *testing.T) { 1341 testGRPCLBEmptyServerList(t, `{"loadBalancingConfig":[{"grpclb":{"childPolicy":[{"pick_first":{}}]}}]}`) 1342 } 1343 1344 func (s) TestGRPCLBWithTargetNameFieldInConfig(t *testing.T) { 1345 r := manual.NewBuilderWithScheme("whatever") 1346 1347 // Start a remote balancer and a backend. Push the backend address to the 1348 // remote balancer. 1349 tss, cleanup, err := startBackendsAndRemoteLoadBalancer(1, "", nil) 1350 if err != nil { 1351 t.Fatalf("failed to create new load balancer: %v", err) 1352 } 1353 defer cleanup() 1354 sl := &lbpb.ServerList{ 1355 Servers: []*lbpb.Server{ 1356 { 1357 IpAddress: tss.beIPs[0], 1358 Port: int32(tss.bePorts[0]), 1359 LoadBalanceToken: lbToken, 1360 }, 1361 }, 1362 } 1363 tss.ls.sls <- sl 1364 1365 cc, err := grpc.Dial(r.Scheme()+":///"+beServerName, 1366 grpc.WithResolvers(r), 1367 grpc.WithTransportCredentials(&serverNameCheckCreds{}), 1368 grpc.WithContextDialer(fakeNameDialer), 1369 grpc.WithUserAgent(testUserAgent)) 1370 if err != nil { 1371 t.Fatalf("Failed to dial to the backend %v", err) 1372 } 1373 defer cc.Close() 1374 testC := testpb.NewTestServiceClient(cc) 1375 1376 // Push a resolver update with grpclb configuration which does not contain the 1377 // target_name field. Our fake remote balancer is configured to always 1378 // expect `beServerName` as the server name in the initial request. 1379 rs := grpclbstate.Set(resolver.State{ServiceConfig: r.CC.ParseServiceConfig(grpclbConfig)}, 1380 &grpclbstate.State{BalancerAddresses: []resolver.Address{{ 1381 Addr: tss.lbAddr, 1382 ServerName: lbServerName, 1383 }}}) 1384 r.UpdateState(rs) 1385 1386 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 1387 defer cancel() 1388 select { 1389 case <-ctx.Done(): 1390 t.Fatalf("timeout when waiting for BalanceLoad RPC to be called on the remote balancer") 1391 case <-tss.ls.balanceLoadCh: 1392 } 1393 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}); err != nil { 1394 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 1395 } 1396 1397 // When the value of target_field changes, grpclb will recreate the stream 1398 // to the remote balancer. So, we need to update the fake remote balancer to 1399 // expect a new server name in the initial request. 1400 const newServerName = "new-server-name" 1401 tss.ls.updateServerName(newServerName) 1402 tss.ls.sls <- sl 1403 1404 // Push the resolver update with target_field changed. 1405 // Push a resolver update with grpclb configuration containing the 1406 // target_name field. Our fake remote balancer has been updated above to expect the newServerName in the initial request. 1407 lbCfg := fmt.Sprintf(`{"loadBalancingConfig": [{"grpclb": {"targetName": "%s"}}]}`, newServerName) 1408 rs = grpclbstate.Set(resolver.State{ServiceConfig: r.CC.ParseServiceConfig(lbCfg)}, 1409 &grpclbstate.State{BalancerAddresses: []resolver.Address{{ 1410 Addr: tss.lbAddr, 1411 ServerName: lbServerName, 1412 }}}) 1413 r.UpdateState(rs) 1414 select { 1415 case <-ctx.Done(): 1416 t.Fatalf("timeout when waiting for BalanceLoad RPC to be called on the remote balancer") 1417 case <-tss.ls.balanceLoadCh: 1418 } 1419 1420 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}); err != nil { 1421 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 1422 } 1423 } 1424 1425 type failPreRPCCred struct{} 1426 1427 func (failPreRPCCred) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { 1428 if strings.Contains(uri[0], failtosendURI) { 1429 return nil, fmt.Errorf("rpc should fail to send") 1430 } 1431 return nil, nil 1432 } 1433 1434 func (failPreRPCCred) RequireTransportSecurity() bool { 1435 return false 1436 } 1437 1438 func checkStats(stats, expected *rpcStats) error { 1439 if !stats.equal(expected) { 1440 return fmt.Errorf("stats not equal: got %+v, want %+v", stats, expected) 1441 } 1442 return nil 1443 } 1444 1445 func runAndCheckStats(t *testing.T, drop bool, statsChan chan *lbpb.ClientStats, runRPCs func(*grpc.ClientConn), statsWant *rpcStats) error { 1446 r := manual.NewBuilderWithScheme("whatever") 1447 1448 tss, cleanup, err := startBackendsAndRemoteLoadBalancer(1, "", statsChan) 1449 if err != nil { 1450 t.Fatalf("failed to create new load balancer: %v", err) 1451 } 1452 defer cleanup() 1453 servers := []*lbpb.Server{{ 1454 IpAddress: tss.beIPs[0], 1455 Port: int32(tss.bePorts[0]), 1456 LoadBalanceToken: lbToken, 1457 }} 1458 if drop { 1459 servers = append(servers, &lbpb.Server{ 1460 LoadBalanceToken: lbToken, 1461 Drop: drop, 1462 }) 1463 } 1464 tss.ls.sls <- &lbpb.ServerList{Servers: servers} 1465 tss.ls.statsDura = 100 * time.Millisecond 1466 creds := serverNameCheckCreds{} 1467 1468 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 1469 defer cancel() 1470 cc, err := grpc.DialContext(ctx, r.Scheme()+":///"+beServerName, grpc.WithResolvers(r), 1471 grpc.WithTransportCredentials(&creds), 1472 grpc.WithPerRPCCredentials(failPreRPCCred{}), 1473 grpc.WithContextDialer(fakeNameDialer)) 1474 if err != nil { 1475 t.Fatalf("Failed to dial to the backend %v", err) 1476 } 1477 defer cc.Close() 1478 1479 r.UpdateState(resolver.State{Addresses: []resolver.Address{{ 1480 Addr: tss.lbAddr, 1481 Type: resolver.GRPCLB, 1482 ServerName: lbServerName, 1483 }}}) 1484 1485 runRPCs(cc) 1486 end := time.Now().Add(time.Second) 1487 for time.Now().Before(end) { 1488 if err := checkStats(tss.ls.stats, statsWant); err == nil { 1489 time.Sleep(200 * time.Millisecond) // sleep for two intervals to make sure no new stats are reported. 1490 break 1491 } 1492 } 1493 return checkStats(tss.ls.stats, statsWant) 1494 } 1495 1496 const ( 1497 countRPC = 40 1498 failtosendURI = "failtosend" 1499 ) 1500 1501 func (s) TestGRPCLBStatsUnarySuccess(t *testing.T) { 1502 if err := runAndCheckStats(t, false, nil, func(cc *grpc.ClientConn) { 1503 testC := testpb.NewTestServiceClient(cc) 1504 ctx, cancel := context.WithTimeout(context.Background(), defaultFallbackTimeout) 1505 defer cancel() 1506 // The first non-failfast RPC succeeds, all connections are up. 1507 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil { 1508 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 1509 } 1510 for i := 0; i < countRPC-1; i++ { 1511 testC.EmptyCall(ctx, &testpb.Empty{}) 1512 } 1513 }, &rpcStats{ 1514 numCallsStarted: int64(countRPC), 1515 numCallsFinished: int64(countRPC), 1516 numCallsFinishedKnownReceived: int64(countRPC), 1517 }); err != nil { 1518 t.Fatal(err) 1519 } 1520 } 1521 1522 func (s) TestGRPCLBStatsUnaryDrop(t *testing.T) { 1523 if err := runAndCheckStats(t, true, nil, func(cc *grpc.ClientConn) { 1524 testC := testpb.NewTestServiceClient(cc) 1525 ctx, cancel := context.WithTimeout(context.Background(), defaultFallbackTimeout) 1526 defer cancel() 1527 // The first non-failfast RPC succeeds, all connections are up. 1528 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil { 1529 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 1530 } 1531 for i := 0; i < countRPC-1; i++ { 1532 testC.EmptyCall(ctx, &testpb.Empty{}) 1533 } 1534 }, &rpcStats{ 1535 numCallsStarted: int64(countRPC), 1536 numCallsFinished: int64(countRPC), 1537 numCallsFinishedKnownReceived: int64(countRPC) / 2, 1538 numCallsDropped: map[string]int64{lbToken: int64(countRPC) / 2}, 1539 }); err != nil { 1540 t.Fatal(err) 1541 } 1542 } 1543 1544 func (s) TestGRPCLBStatsUnaryFailedToSend(t *testing.T) { 1545 if err := runAndCheckStats(t, false, nil, func(cc *grpc.ClientConn) { 1546 testC := testpb.NewTestServiceClient(cc) 1547 ctx, cancel := context.WithTimeout(context.Background(), defaultFallbackTimeout) 1548 defer cancel() 1549 // The first non-failfast RPC succeeds, all connections are up. 1550 if _, err := testC.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil { 1551 t.Fatalf("%v.EmptyCall(_, _) = _, %v, want _, <nil>", testC, err) 1552 } 1553 for i := 0; i < countRPC-1; i++ { 1554 cc.Invoke(ctx, failtosendURI, &testpb.Empty{}, nil) 1555 } 1556 }, &rpcStats{ 1557 numCallsStarted: int64(countRPC), 1558 numCallsFinished: int64(countRPC), 1559 numCallsFinishedWithClientFailedToSend: int64(countRPC) - 1, 1560 numCallsFinishedKnownReceived: 1, 1561 }); err != nil { 1562 t.Fatal(err) 1563 } 1564 } 1565 1566 func (s) TestGRPCLBStatsStreamingSuccess(t *testing.T) { 1567 if err := runAndCheckStats(t, false, nil, func(cc *grpc.ClientConn) { 1568 testC := testpb.NewTestServiceClient(cc) 1569 ctx, cancel := context.WithTimeout(context.Background(), defaultFallbackTimeout) 1570 defer cancel() 1571 // The first non-failfast RPC succeeds, all connections are up. 1572 stream, err := testC.FullDuplexCall(ctx, grpc.WaitForReady(true)) 1573 if err != nil { 1574 t.Fatalf("%v.FullDuplexCall(_, _) = _, %v, want _, <nil>", testC, err) 1575 } 1576 for { 1577 if _, err = stream.Recv(); err == io.EOF { 1578 break 1579 } 1580 } 1581 for i := 0; i < countRPC-1; i++ { 1582 stream, err = testC.FullDuplexCall(ctx) 1583 if err == nil { 1584 // Wait for stream to end if err is nil. 1585 for { 1586 if _, err = stream.Recv(); err == io.EOF { 1587 break 1588 } 1589 } 1590 } 1591 } 1592 }, &rpcStats{ 1593 numCallsStarted: int64(countRPC), 1594 numCallsFinished: int64(countRPC), 1595 numCallsFinishedKnownReceived: int64(countRPC), 1596 }); err != nil { 1597 t.Fatal(err) 1598 } 1599 } 1600 1601 func (s) TestGRPCLBStatsStreamingDrop(t *testing.T) { 1602 if err := runAndCheckStats(t, true, nil, func(cc *grpc.ClientConn) { 1603 testC := testpb.NewTestServiceClient(cc) 1604 ctx, cancel := context.WithTimeout(context.Background(), defaultFallbackTimeout) 1605 defer cancel() 1606 // The first non-failfast RPC succeeds, all connections are up. 1607 stream, err := testC.FullDuplexCall(ctx, grpc.WaitForReady(true)) 1608 if err != nil { 1609 t.Fatalf("%v.FullDuplexCall(_, _) = _, %v, want _, <nil>", testC, err) 1610 } 1611 for { 1612 if _, err = stream.Recv(); err == io.EOF { 1613 break 1614 } 1615 } 1616 for i := 0; i < countRPC-1; i++ { 1617 stream, err = testC.FullDuplexCall(ctx) 1618 if err == nil { 1619 // Wait for stream to end if err is nil. 1620 for { 1621 if _, err = stream.Recv(); err == io.EOF { 1622 break 1623 } 1624 } 1625 } 1626 } 1627 }, &rpcStats{ 1628 numCallsStarted: int64(countRPC), 1629 numCallsFinished: int64(countRPC), 1630 numCallsFinishedKnownReceived: int64(countRPC) / 2, 1631 numCallsDropped: map[string]int64{lbToken: int64(countRPC) / 2}, 1632 }); err != nil { 1633 t.Fatal(err) 1634 } 1635 } 1636 1637 func (s) TestGRPCLBStatsStreamingFailedToSend(t *testing.T) { 1638 if err := runAndCheckStats(t, false, nil, func(cc *grpc.ClientConn) { 1639 testC := testpb.NewTestServiceClient(cc) 1640 ctx, cancel := context.WithTimeout(context.Background(), defaultFallbackTimeout) 1641 defer cancel() 1642 // The first non-failfast RPC succeeds, all connections are up. 1643 stream, err := testC.FullDuplexCall(ctx, grpc.WaitForReady(true)) 1644 if err != nil { 1645 t.Fatalf("%v.FullDuplexCall(_, _) = _, %v, want _, <nil>", testC, err) 1646 } 1647 for { 1648 if _, err = stream.Recv(); err == io.EOF { 1649 break 1650 } 1651 } 1652 for i := 0; i < countRPC-1; i++ { 1653 cc.NewStream(ctx, &grpc.StreamDesc{}, failtosendURI) 1654 } 1655 }, &rpcStats{ 1656 numCallsStarted: int64(countRPC), 1657 numCallsFinished: int64(countRPC), 1658 numCallsFinishedWithClientFailedToSend: int64(countRPC) - 1, 1659 numCallsFinishedKnownReceived: 1, 1660 }); err != nil { 1661 t.Fatal(err) 1662 } 1663 } 1664 1665 func (s) TestGRPCLBStatsQuashEmpty(t *testing.T) { 1666 ch := make(chan *lbpb.ClientStats) 1667 defer close(ch) 1668 if err := runAndCheckStats(t, false, ch, func(cc *grpc.ClientConn) { 1669 // Perform no RPCs; wait for load reports to start, which should be 1670 // zero, then expect no other load report within 5x the update 1671 // interval. 1672 select { 1673 case st := <-ch: 1674 if !isZeroStats(st) { 1675 t.Errorf("got stats %v; want all zero", st) 1676 } 1677 case <-time.After(5 * time.Second): 1678 t.Errorf("did not get initial stats report after 5 seconds") 1679 return 1680 } 1681 1682 select { 1683 case st := <-ch: 1684 t.Errorf("got unexpected stats report: %v", st) 1685 case <-time.After(500 * time.Millisecond): 1686 // Success. 1687 } 1688 go func() { 1689 for range ch { // Drain statsChan until it is closed. 1690 } 1691 }() 1692 }, &rpcStats{ 1693 numCallsStarted: 0, 1694 numCallsFinished: 0, 1695 numCallsFinishedKnownReceived: 0, 1696 }); err != nil { 1697 t.Fatal(err) 1698 } 1699 }