@@ -20,6 +20,7 @@ import * as path from 'path';
20
20
import * as grpc from '../src' ;
21
21
import { loadProtoFile } from './common' ;
22
22
import { OutlierDetectionLoadBalancingConfig } from '../src/load-balancer-outlier-detection'
23
+ import { ServiceClient } from '../src/make-client' ;
23
24
24
25
function multiDone ( done : Mocha . Done , target : number ) {
25
26
let count = 0 ;
@@ -49,6 +50,54 @@ const defaultOutlierDetectionServiceConfig = {
49
50
50
51
const defaultOutlierDetectionServiceConfigString = JSON . stringify ( defaultOutlierDetectionServiceConfig ) ;
51
52
53
+ const successRateOutlierDetectionServiceConfig = {
54
+ methodConfig : [ ] ,
55
+ loadBalancingConfig : [
56
+ {
57
+ outlier_detection : {
58
+ interval : {
59
+ seconds : 1 ,
60
+ nanos : 0
61
+ } ,
62
+ base_ejection_time : {
63
+ seconds : 3 ,
64
+ nanos : 0
65
+ } ,
66
+ success_rate_ejection : {
67
+ request_volume : 5
68
+ } ,
69
+ child_policy : [ { round_robin : { } } ]
70
+ }
71
+ }
72
+ ]
73
+ } ;
74
+
75
+ const successRateOutlierDetectionServiceConfigString = JSON . stringify ( successRateOutlierDetectionServiceConfig ) ;
76
+
77
+ const failurePercentageOutlierDetectionServiceConfig = {
78
+ methodConfig : [ ] ,
79
+ loadBalancingConfig : [
80
+ {
81
+ outlier_detection : {
82
+ interval : {
83
+ seconds : 1 ,
84
+ nanos : 0
85
+ } ,
86
+ base_ejection_time : {
87
+ seconds : 3 ,
88
+ nanos : 0
89
+ } ,
90
+ failure_percentage_ejection : {
91
+ request_volume : 5
92
+ } ,
93
+ child_policy : [ { round_robin : { } } ]
94
+ }
95
+ }
96
+ ]
97
+ } ;
98
+
99
+ const falurePercentageOutlierDetectionServiceConfigString = JSON . stringify ( failurePercentageOutlierDetectionServiceConfig ) ;
100
+
52
101
const goodService = {
53
102
echo : ( call : grpc . ServerUnaryCall < any , any > , callback : grpc . sendUnaryData < any > ) => {
54
103
callback ( null , call . request )
@@ -353,6 +402,20 @@ describe('Outlier detection', () => {
353
402
badServer . forceShutdown ( ) ;
354
403
} ) ;
355
404
405
+ function makeManyRequests ( makeOneRequest : ( callback : ( error ?: Error ) => void ) => void , total : number , callback : ( error ?: Error ) => void ) {
406
+ if ( total === 0 ) {
407
+ callback ( ) ;
408
+ return ;
409
+ }
410
+ makeOneRequest ( error => {
411
+ if ( error ) {
412
+ callback ( error ) ;
413
+ return ;
414
+ }
415
+ makeManyRequests ( makeOneRequest , total - 1 , callback ) ;
416
+ } ) ;
417
+ }
418
+
356
419
it ( 'Should allow normal operation with one server' , done => {
357
420
const client = new EchoService ( `localhost:${ goodPorts [ 0 ] } ` , grpc . credentials . createInsecure ( ) , { 'grpc.service_config' : defaultOutlierDetectionServiceConfigString } ) ;
358
421
client . echo (
@@ -364,4 +427,110 @@ describe('Outlier detection', () => {
364
427
}
365
428
) ;
366
429
} ) ;
430
+ describe ( 'Success rate' , ( ) => {
431
+ let makeCheckedRequest : ( callback : ( ) => void ) => void ;
432
+ let makeUncheckedRequest :( callback : ( error ?: Error ) => void ) => void ;
433
+ before ( ( ) => {
434
+ const target = 'ipv4:///' + goodPorts . map ( port => `127.0.0.1:${ port } ` ) . join ( ',' ) + `,127.0.0.1:${ badPort } ` ;
435
+ const client = new EchoService ( target , grpc . credentials . createInsecure ( ) , { 'grpc.service_config' : successRateOutlierDetectionServiceConfigString } ) ;
436
+ makeUncheckedRequest = ( callback : ( ) => void ) => {
437
+ client . echo (
438
+ { value : 'test value' , value2 : 3 } ,
439
+ ( error : grpc . ServiceError , response : any ) => {
440
+ callback ( ) ;
441
+ }
442
+ ) ;
443
+ } ;
444
+ makeCheckedRequest = ( callback : ( error ?: Error ) => void ) => {
445
+ client . echo (
446
+ { value : 'test value' , value2 : 3 } ,
447
+ ( error : grpc . ServiceError , response : any ) => {
448
+ callback ( error ) ;
449
+ }
450
+ ) ;
451
+ } ;
452
+ } ) ;
453
+ it ( 'Should eject a server if it is failing requests' , done => {
454
+ // Make a large volume of requests
455
+ makeManyRequests ( makeUncheckedRequest , 50 , ( ) => {
456
+ // Give outlier detection time to run ejection checks
457
+ setTimeout ( ( ) => {
458
+ // Make enough requests to go around all servers
459
+ makeManyRequests ( makeCheckedRequest , 10 , done ) ;
460
+ } , 1000 ) ;
461
+ } ) ;
462
+ } ) ;
463
+ it ( 'Should uneject a server after the ejection period' , function ( done ) {
464
+ this . timeout ( 5000 ) ;
465
+ makeManyRequests ( makeUncheckedRequest , 50 , ( ) => {
466
+ setTimeout ( ( ) => {
467
+ makeManyRequests ( makeCheckedRequest , 10 , error => {
468
+ if ( error ) {
469
+ done ( error ) ;
470
+ return ;
471
+ }
472
+ setTimeout ( ( ) => {
473
+ makeManyRequests ( makeCheckedRequest , 10 , error => {
474
+ assert ( error ) ;
475
+ done ( ) ;
476
+ } ) ;
477
+ } , 3000 ) ;
478
+ } ) ;
479
+ } , 1000 ) ;
480
+ } )
481
+ } ) ;
482
+ } ) ;
483
+ describe ( 'Failure percentage' , ( ) => {
484
+ let makeCheckedRequest : ( callback : ( ) => void ) => void ;
485
+ let makeUncheckedRequest :( callback : ( error ?: Error ) => void ) => void ;
486
+ before ( ( ) => {
487
+ const target = 'ipv4:///' + goodPorts . map ( port => `127.0.0.1:${ port } ` ) . join ( ',' ) + `,127.0.0.1:${ badPort } ` ;
488
+ const client = new EchoService ( target , grpc . credentials . createInsecure ( ) , { 'grpc.service_config' : falurePercentageOutlierDetectionServiceConfigString } ) ;
489
+ makeUncheckedRequest = ( callback : ( ) => void ) => {
490
+ client . echo (
491
+ { value : 'test value' , value2 : 3 } ,
492
+ ( error : grpc . ServiceError , response : any ) => {
493
+ callback ( ) ;
494
+ }
495
+ ) ;
496
+ } ;
497
+ makeCheckedRequest = ( callback : ( error ?: Error ) => void ) => {
498
+ client . echo (
499
+ { value : 'test value' , value2 : 3 } ,
500
+ ( error : grpc . ServiceError , response : any ) => {
501
+ callback ( error ) ;
502
+ }
503
+ ) ;
504
+ } ;
505
+ } ) ;
506
+ it ( 'Should eject a server if it is failing requests' , done => {
507
+ // Make a large volume of requests
508
+ makeManyRequests ( makeUncheckedRequest , 50 , ( ) => {
509
+ // Give outlier detection time to run ejection checks
510
+ setTimeout ( ( ) => {
511
+ // Make enough requests to go around all servers
512
+ makeManyRequests ( makeCheckedRequest , 10 , done ) ;
513
+ } , 1000 ) ;
514
+ } ) ;
515
+ } ) ;
516
+ it ( 'Should uneject a server after the ejection period' , function ( done ) {
517
+ this . timeout ( 5000 ) ;
518
+ makeManyRequests ( makeUncheckedRequest , 50 , ( ) => {
519
+ setTimeout ( ( ) => {
520
+ makeManyRequests ( makeCheckedRequest , 10 , error => {
521
+ if ( error ) {
522
+ done ( error ) ;
523
+ return ;
524
+ }
525
+ setTimeout ( ( ) => {
526
+ makeManyRequests ( makeCheckedRequest , 10 , error => {
527
+ assert ( error ) ;
528
+ done ( ) ;
529
+ } ) ;
530
+ } , 3000 ) ;
531
+ } ) ;
532
+ } , 1000 ) ;
533
+ } )
534
+ } ) ;
535
+ } ) ;
367
536
} ) ;
0 commit comments