use of io.envoyproxy.envoy.api.v2.endpoint.ClusterStats in project grpc-java by grpc.
the class LoadReportClientTest method periodicLoadReporting.
@Test
public void periodicLoadReporting() {
verify(mockLoadReportingService).streamLoadStats(lrsResponseObserverCaptor.capture());
StreamObserver<LoadStatsResponse> responseObserver = lrsResponseObserverCaptor.getValue();
StreamObserver<LoadStatsRequest> requestObserver = Iterables.getOnlyElement(lrsRequestObservers);
verify(requestObserver).onNext(eq(buildInitialRequest()));
// Management server asks to report loads for cluster1.
responseObserver.onNext(LoadStatsResponse.newBuilder().addClusters(CLUSTER1).setLoadReportingInterval(Durations.fromSeconds(10L)).build());
fakeClock.forwardTime(10L, TimeUnit.SECONDS);
verify(requestObserver, times(2)).onNext(requestCaptor.capture());
LoadStatsRequest request = requestCaptor.getValue();
ClusterStats clusterStats = Iterables.getOnlyElement(request.getClusterStatsList());
assertThat(clusterStats.getClusterName()).isEqualTo(CLUSTER1);
assertThat(clusterStats.getClusterServiceName()).isEqualTo(EDS_SERVICE_NAME1);
assertThat(Durations.toSeconds(clusterStats.getLoadReportInterval())).isEqualTo(10L);
assertThat(Iterables.getOnlyElement(clusterStats.getDroppedRequestsList()).getCategory()).isEqualTo("lb");
assertThat(Iterables.getOnlyElement(clusterStats.getDroppedRequestsList()).getDroppedCount()).isEqualTo(52L);
assertThat(clusterStats.getTotalDroppedRequests()).isEqualTo(52L);
UpstreamLocalityStats localityStats = Iterables.getOnlyElement(clusterStats.getUpstreamLocalityStatsList());
assertThat(localityStats.getLocality().getRegion()).isEqualTo("region1");
assertThat(localityStats.getLocality().getZone()).isEqualTo("zone1");
assertThat(localityStats.getLocality().getSubZone()).isEqualTo("subZone1");
assertThat(localityStats.getTotalIssuedRequests()).isEqualTo(31L);
assertThat(localityStats.getTotalSuccessfulRequests()).isEqualTo(0L);
assertThat(localityStats.getTotalErrorRequests()).isEqualTo(0L);
assertThat(localityStats.getTotalRequestsInProgress()).isEqualTo(31L);
fakeClock.forwardTime(10L, TimeUnit.SECONDS);
verify(requestObserver, times(3)).onNext(requestCaptor.capture());
request = requestCaptor.getValue();
clusterStats = Iterables.getOnlyElement(request.getClusterStatsList());
assertThat(clusterStats.getClusterName()).isEqualTo(CLUSTER1);
assertThat(clusterStats.getClusterServiceName()).isEqualTo(EDS_SERVICE_NAME1);
assertThat(Durations.toSeconds(clusterStats.getLoadReportInterval())).isEqualTo(10L);
assertThat(clusterStats.getDroppedRequestsCount()).isEqualTo(0L);
assertThat(clusterStats.getTotalDroppedRequests()).isEqualTo(0L);
localityStats = Iterables.getOnlyElement(clusterStats.getUpstreamLocalityStatsList());
assertThat(localityStats.getLocality().getRegion()).isEqualTo("region1");
assertThat(localityStats.getLocality().getZone()).isEqualTo("zone1");
assertThat(localityStats.getLocality().getSubZone()).isEqualTo("subZone1");
assertThat(localityStats.getTotalIssuedRequests()).isEqualTo(0L);
assertThat(localityStats.getTotalSuccessfulRequests()).isEqualTo(0L);
assertThat(localityStats.getTotalErrorRequests()).isEqualTo(0L);
assertThat(localityStats.getTotalRequestsInProgress()).isEqualTo(31L);
// Management server updates the interval of sending load reports, while still asking for
// loads to cluster1 only.
responseObserver.onNext(LoadStatsResponse.newBuilder().addClusters(CLUSTER1).setLoadReportingInterval(Durations.fromSeconds(20L)).build());
fakeClock.forwardTime(10L, TimeUnit.SECONDS);
verifyNoMoreInteractions(requestObserver);
fakeClock.forwardTime(10L, TimeUnit.SECONDS);
verify(requestObserver, times(4)).onNext(requestCaptor.capture());
request = requestCaptor.getValue();
clusterStats = Iterables.getOnlyElement(request.getClusterStatsList());
assertThat(clusterStats.getClusterName()).isEqualTo(CLUSTER1);
assertThat(clusterStats.getClusterServiceName()).isEqualTo(EDS_SERVICE_NAME1);
assertThat(Durations.toSeconds(clusterStats.getLoadReportInterval())).isEqualTo(20L);
assertThat(clusterStats.getDroppedRequestsCount()).isEqualTo(0);
localityStats = Iterables.getOnlyElement(clusterStats.getUpstreamLocalityStatsList());
assertThat(localityStats.getLocality().getRegion()).isEqualTo("region1");
assertThat(localityStats.getLocality().getZone()).isEqualTo("zone1");
assertThat(localityStats.getLocality().getSubZone()).isEqualTo("subZone1");
assertThat(localityStats.getTotalIssuedRequests()).isEqualTo(0L);
assertThat(localityStats.getTotalSuccessfulRequests()).isEqualTo(0L);
assertThat(localityStats.getTotalErrorRequests()).isEqualTo(0L);
assertThat(localityStats.getTotalRequestsInProgress()).isEqualTo(31L);
// Management server asks to report loads for all clusters.
responseObserver.onNext(LoadStatsResponse.newBuilder().setSendAllClusters(true).setLoadReportingInterval(Durations.fromSeconds(20L)).build());
fakeClock.forwardTime(20L, TimeUnit.SECONDS);
verify(requestObserver, times(5)).onNext(requestCaptor.capture());
request = requestCaptor.getValue();
assertThat(request.getClusterStatsCount()).isEqualTo(2);
ClusterStats clusterStats1 = findClusterStats(request.getClusterStatsList(), CLUSTER1);
assertThat(Durations.toSeconds(clusterStats1.getLoadReportInterval())).isEqualTo(20L);
assertThat(clusterStats1.getDroppedRequestsCount()).isEqualTo(0L);
assertThat(clusterStats1.getTotalDroppedRequests()).isEqualTo(0L);
UpstreamLocalityStats localityStats1 = Iterables.getOnlyElement(clusterStats1.getUpstreamLocalityStatsList());
assertThat(localityStats1.getLocality().getRegion()).isEqualTo("region1");
assertThat(localityStats1.getLocality().getZone()).isEqualTo("zone1");
assertThat(localityStats1.getLocality().getSubZone()).isEqualTo("subZone1");
assertThat(localityStats1.getTotalIssuedRequests()).isEqualTo(0L);
assertThat(localityStats1.getTotalSuccessfulRequests()).isEqualTo(0L);
assertThat(localityStats1.getTotalErrorRequests()).isEqualTo(0L);
assertThat(localityStats1.getTotalRequestsInProgress()).isEqualTo(31L);
ClusterStats clusterStats2 = findClusterStats(request.getClusterStatsList(), CLUSTER2);
assertThat(Durations.toSeconds(clusterStats2.getLoadReportInterval())).isEqualTo(10L + 10L + 20L + 20L);
assertThat(Iterables.getOnlyElement(clusterStats2.getDroppedRequestsList()).getCategory()).isEqualTo("throttle");
assertThat(Iterables.getOnlyElement(clusterStats2.getDroppedRequestsList()).getDroppedCount()).isEqualTo(23L);
assertThat(clusterStats2.getTotalDroppedRequests()).isEqualTo(23L);
UpstreamLocalityStats localityStats2 = Iterables.getOnlyElement(clusterStats2.getUpstreamLocalityStatsList());
assertThat(localityStats2.getLocality().getRegion()).isEqualTo("region2");
assertThat(localityStats2.getLocality().getZone()).isEqualTo("zone2");
assertThat(localityStats2.getLocality().getSubZone()).isEqualTo("subZone2");
assertThat(localityStats2.getTotalIssuedRequests()).isEqualTo(45L);
assertThat(localityStats2.getTotalSuccessfulRequests()).isEqualTo(1L);
assertThat(localityStats2.getTotalErrorRequests()).isEqualTo(0L);
assertThat(localityStats2.getTotalRequestsInProgress()).isEqualTo(45L - 1L);
// Load reports for cluster1 is no longer wanted.
responseObserver.onNext(LoadStatsResponse.newBuilder().addClusters(CLUSTER2).setLoadReportingInterval(Durations.fromSeconds(10L)).build());
fakeClock.forwardTime(10L, TimeUnit.SECONDS);
verify(requestObserver, times(6)).onNext(requestCaptor.capture());
request = requestCaptor.getValue();
clusterStats = Iterables.getOnlyElement(request.getClusterStatsList());
assertThat(clusterStats.getClusterName()).isEqualTo(CLUSTER2);
assertThat(clusterStats.getClusterServiceName()).isEqualTo(EDS_SERVICE_NAME2);
assertThat(Durations.toSeconds(clusterStats.getLoadReportInterval())).isEqualTo(10L);
assertThat(clusterStats.getDroppedRequestsCount()).isEqualTo(0L);
assertThat(clusterStats.getTotalDroppedRequests()).isEqualTo(0L);
localityStats = Iterables.getOnlyElement(clusterStats.getUpstreamLocalityStatsList());
assertThat(localityStats.getLocality().getRegion()).isEqualTo("region2");
assertThat(localityStats.getLocality().getZone()).isEqualTo("zone2");
assertThat(localityStats.getLocality().getSubZone()).isEqualTo("subZone2");
assertThat(localityStats.getTotalIssuedRequests()).isEqualTo(0L);
assertThat(localityStats.getTotalSuccessfulRequests()).isEqualTo(0L);
assertThat(localityStats.getTotalErrorRequests()).isEqualTo(0L);
assertThat(localityStats.getTotalRequestsInProgress()).isEqualTo(44L);
fakeClock.forwardTime(10L, TimeUnit.SECONDS);
verify(requestObserver, times(7)).onNext(requestCaptor.capture());
request = requestCaptor.getValue();
clusterStats = Iterables.getOnlyElement(request.getClusterStatsList());
assertThat(clusterStats.getClusterName()).isEqualTo(CLUSTER2);
assertThat(clusterStats.getClusterServiceName()).isEqualTo(EDS_SERVICE_NAME2);
assertThat(Durations.toSeconds(clusterStats.getLoadReportInterval())).isEqualTo(10L);
assertThat(clusterStats.getDroppedRequestsCount()).isEqualTo(0L);
assertThat(clusterStats.getTotalDroppedRequests()).isEqualTo(0L);
localityStats = Iterables.getOnlyElement(clusterStats.getUpstreamLocalityStatsList());
assertThat(localityStats.getLocality().getRegion()).isEqualTo("region2");
assertThat(localityStats.getLocality().getZone()).isEqualTo("zone2");
assertThat(localityStats.getLocality().getSubZone()).isEqualTo("subZone2");
assertThat(localityStats.getTotalIssuedRequests()).isEqualTo(0L);
assertThat(localityStats.getTotalSuccessfulRequests()).isEqualTo(0L);
assertThat(localityStats.getTotalErrorRequests()).isEqualTo(0L);
assertThat(localityStats.getTotalRequestsInProgress()).isEqualTo(44L);
// Management server asks loads for a cluster that client has no load data.
responseObserver.onNext(LoadStatsResponse.newBuilder().addClusters("unknown.googleapis.com").setLoadReportingInterval(Durations.fromSeconds(20L)).build());
fakeClock.forwardTime(20L, TimeUnit.SECONDS);
verify(requestObserver, times(8)).onNext(requestCaptor.capture());
assertThat(requestCaptor.getValue().getClusterStatsCount()).isEqualTo(0);
}
use of io.envoyproxy.envoy.api.v2.endpoint.ClusterStats in project grpc-java by grpc.
the class LoadReportClientTest method lrsStreamClosedAndRetried.
@Test
public void lrsStreamClosedAndRetried() {
InOrder inOrder = inOrder(mockLoadReportingService, backoffPolicyProvider, backoffPolicy1, backoffPolicy2);
inOrder.verify(mockLoadReportingService).streamLoadStats(lrsResponseObserverCaptor.capture());
StreamObserver<LoadStatsResponse> responseObserver = lrsResponseObserverCaptor.getValue();
assertThat(lrsRequestObservers).hasSize(1);
StreamObserver<LoadStatsRequest> requestObserver = lrsRequestObservers.poll();
// First balancer RPC
verify(requestObserver).onNext(eq(buildInitialRequest()));
assertEquals(0, fakeClock.numPendingTasks(LRS_RPC_RETRY_TASK_FILTER));
// Balancer closes it immediately (erroneously)
responseObserver.onCompleted();
// Will start backoff sequence 1 (1s)
inOrder.verify(backoffPolicyProvider).get();
inOrder.verify(backoffPolicy1).nextBackoffNanos();
assertEquals(1, fakeClock.numPendingTasks(LRS_RPC_RETRY_TASK_FILTER));
// Fast-forward to a moment before the retry
fakeClock.forwardNanos(TimeUnit.SECONDS.toNanos(1) - 1);
verifyNoMoreInteractions(mockLoadReportingService);
// Then time for retry
fakeClock.forwardNanos(1);
inOrder.verify(mockLoadReportingService).streamLoadStats(lrsResponseObserverCaptor.capture());
responseObserver = lrsResponseObserverCaptor.getValue();
assertThat(lrsRequestObservers).hasSize(1);
requestObserver = lrsRequestObservers.poll();
verify(requestObserver).onNext(eq(buildInitialRequest()));
assertEquals(0, fakeClock.numPendingTasks(LRS_RPC_RETRY_TASK_FILTER));
// Balancer closes it with an error.
responseObserver.onError(Status.UNAVAILABLE.asException());
// Will continue the backoff sequence 1 (10s)
verifyNoMoreInteractions(backoffPolicyProvider);
inOrder.verify(backoffPolicy1).nextBackoffNanos();
assertEquals(1, fakeClock.numPendingTasks(LRS_RPC_RETRY_TASK_FILTER));
// Fast-forward to a moment before the retry
fakeClock.forwardNanos(TimeUnit.SECONDS.toNanos(10) - 1);
verifyNoMoreInteractions(mockLoadReportingService);
// Then time for retry
fakeClock.forwardNanos(1);
inOrder.verify(mockLoadReportingService).streamLoadStats(lrsResponseObserverCaptor.capture());
responseObserver = lrsResponseObserverCaptor.getValue();
assertThat(lrsRequestObservers).hasSize(1);
requestObserver = lrsRequestObservers.poll();
verify(requestObserver).onNext(eq(buildInitialRequest()));
assertEquals(0, fakeClock.numPendingTasks(LRS_RPC_RETRY_TASK_FILTER));
// Balancer sends a response asking for loads of the cluster.
responseObserver.onNext(LoadStatsResponse.newBuilder().addClusters(CLUSTER1).setLoadReportingInterval(Durations.fromNanos(5L)).build());
// Then breaks the RPC
responseObserver.onError(Status.UNAVAILABLE.asException());
// Will reset the retry sequence and retry immediately, because balancer has responded.
inOrder.verify(backoffPolicyProvider).get();
inOrder.verify(mockLoadReportingService).streamLoadStats(lrsResponseObserverCaptor.capture());
responseObserver = lrsResponseObserverCaptor.getValue();
assertThat(lrsRequestObservers).hasSize(1);
requestObserver = lrsRequestObservers.poll();
verify(requestObserver).onNext(eq(buildInitialRequest()));
// Fail the retry after spending 4ns
fakeClock.forwardNanos(4);
responseObserver.onError(Status.UNAVAILABLE.asException());
// Will be on the first retry (2s) of backoff sequence 2.
inOrder.verify(backoffPolicy2).nextBackoffNanos();
assertEquals(1, fakeClock.numPendingTasks(LRS_RPC_RETRY_TASK_FILTER));
// Fast-forward to a moment before the retry, the time spent in the last try is deducted.
fakeClock.forwardNanos(TimeUnit.SECONDS.toNanos(2) - 4 - 1);
verifyNoMoreInteractions(mockLoadReportingService);
// Then time for retry
fakeClock.forwardNanos(1);
inOrder.verify(mockLoadReportingService).streamLoadStats(lrsResponseObserverCaptor.capture());
assertThat(lrsRequestObservers).hasSize(1);
requestObserver = lrsRequestObservers.poll();
verify(requestObserver).onNext(eq(buildInitialRequest()));
assertEquals(0, fakeClock.numPendingTasks(LRS_RPC_RETRY_TASK_FILTER));
// Load reporting back to normal.
responseObserver = lrsResponseObserverCaptor.getValue();
responseObserver.onNext(LoadStatsResponse.newBuilder().addClusters(CLUSTER1).setLoadReportingInterval(Durations.fromNanos(10L)).build());
fakeClock.forwardNanos(10);
verify(requestObserver, times(2)).onNext(requestCaptor.capture());
LoadStatsRequest request = requestCaptor.getValue();
ClusterStats clusterStats = Iterables.getOnlyElement(request.getClusterStatsList());
assertThat(clusterStats.getClusterName()).isEqualTo(CLUSTER1);
assertThat(clusterStats.getClusterServiceName()).isEqualTo(EDS_SERVICE_NAME1);
assertThat(Durations.toSeconds(clusterStats.getLoadReportInterval())).isEqualTo(1L + 10L + 2L);
assertThat(Iterables.getOnlyElement(clusterStats.getDroppedRequestsList()).getCategory()).isEqualTo("lb");
assertThat(Iterables.getOnlyElement(clusterStats.getDroppedRequestsList()).getDroppedCount()).isEqualTo(52L);
assertThat(clusterStats.getTotalDroppedRequests()).isEqualTo(52L);
UpstreamLocalityStats localityStats = Iterables.getOnlyElement(clusterStats.getUpstreamLocalityStatsList());
assertThat(localityStats.getLocality().getRegion()).isEqualTo("region1");
assertThat(localityStats.getLocality().getZone()).isEqualTo("zone1");
assertThat(localityStats.getLocality().getSubZone()).isEqualTo("subZone1");
assertThat(localityStats.getTotalIssuedRequests()).isEqualTo(31L);
assertThat(localityStats.getTotalSuccessfulRequests()).isEqualTo(0L);
assertThat(localityStats.getTotalErrorRequests()).isEqualTo(0L);
assertThat(localityStats.getTotalRequestsInProgress()).isEqualTo(31L);
// Wrapping up
verify(backoffPolicyProvider, times(2)).get();
verify(backoffPolicy1, times(2)).nextBackoffNanos();
verify(backoffPolicy2, times(1)).nextBackoffNanos();
}
Aggregations