use of io.grpc.LoadBalancer.ResolvedAddresses in project grpc-java by grpc.
the class HealthCheckingLoadBalancerFactoryTest method serviceConfigHasNoHealthCheckingInitiallyButDoesLater.
@Test
public void serviceConfigHasNoHealthCheckingInitiallyButDoesLater() {
// No service config, thus no health check.
ResolvedAddresses result1 = ResolvedAddresses.newBuilder().setAddresses(resolvedAddressList).setAttributes(Attributes.EMPTY).build();
hcLbEventDelivery.handleResolvedAddresses(result1);
verify(origLb).handleResolvedAddresses(result1);
verifyNoMoreInteractions(origLb);
// First, create Subchannels 0
createSubchannel(0, Attributes.EMPTY);
// No health check activity. Underlying Subchannel states are directly propagated
deliverSubchannelState(0, ConnectivityStateInfo.forNonError(READY));
assertThat(healthImpls[0].calls).isEmpty();
verify(mockStateListeners[0]).onSubchannelState(eq(ConnectivityStateInfo.forNonError(READY)));
verifyNoMoreInteractions(mockStateListeners[0]);
// Service config enables health check
Attributes resolutionAttrs = attrsWithHealthCheckService("FooService");
ResolvedAddresses result2 = ResolvedAddresses.newBuilder().setAddresses(resolvedAddressList).setAttributes(resolutionAttrs).build();
hcLbEventDelivery.handleResolvedAddresses(result2);
verify(origLb).handleResolvedAddresses(result2);
// Health check started on existing Subchannel
assertThat(healthImpls[0].calls).hasSize(1);
// State stays in READY, instead of switching to CONNECTING.
verifyNoMoreInteractions(mockStateListeners[0]);
// Start Subchannel 1, which will have health check
createSubchannel(1, Attributes.EMPTY);
assertThat(healthImpls[1].calls).isEmpty();
deliverSubchannelState(1, ConnectivityStateInfo.forNonError(READY));
assertThat(healthImpls[1].calls).hasSize(1);
}
use of io.grpc.LoadBalancer.ResolvedAddresses in project grpc-java by grpc.
the class HealthCheckingLoadBalancerFactoryTest method serviceConfigDisablesHealthCheckWhenRpcInactive.
@Test
public void serviceConfigDisablesHealthCheckWhenRpcInactive() {
Attributes resolutionAttrs = attrsWithHealthCheckService("TeeService");
ResolvedAddresses result1 = ResolvedAddresses.newBuilder().setAddresses(resolvedAddressList).setAttributes(resolutionAttrs).build();
hcLbEventDelivery.handleResolvedAddresses(result1);
verify(origLb).handleResolvedAddresses(result1);
verifyNoMoreInteractions(origLb);
Subchannel subchannel = createSubchannel(0, Attributes.EMPTY);
assertThat(unwrap(subchannel)).isSameInstanceAs(subchannels[0]);
InOrder inOrder = inOrder(origLb, mockStateListeners[0]);
// Underlying subchannel is not READY initially
ConnectivityStateInfo underlyingErrorState = ConnectivityStateInfo.forTransientFailure(Status.UNAVAILABLE.withDescription("connection refused"));
deliverSubchannelState(0, underlyingErrorState);
inOrder.verify(mockStateListeners[0]).onSubchannelState(same(underlyingErrorState));
inOrder.verifyNoMoreInteractions();
// NameResolver gives an update without service config, thus health check will be disabled
ResolvedAddresses result2 = ResolvedAddresses.newBuilder().setAddresses(resolvedAddressList).setAttributes(Attributes.EMPTY).build();
hcLbEventDelivery.handleResolvedAddresses(result2);
inOrder.verify(origLb).handleResolvedAddresses(result2);
// Underlying subchannel is now ready
deliverSubchannelState(0, ConnectivityStateInfo.forNonError(READY));
// Since health check is disabled, READY state is propagated directly.
inOrder.verify(mockStateListeners[0]).onSubchannelState(eq(ConnectivityStateInfo.forNonError(READY)));
// and there is no health check activity.
assertThat(healthImpls[0].calls).isEmpty();
verifyNoMoreInteractions(origLb, mockStateListeners[0]);
}
use of io.grpc.LoadBalancer.ResolvedAddresses in project grpc-java by grpc.
the class HealthCheckingLoadBalancerFactoryTest method backoffRetriesWhenServerErroneouslyClosesRpcBeforeAnyResponse.
@Test
public void backoffRetriesWhenServerErroneouslyClosesRpcBeforeAnyResponse() {
Attributes resolutionAttrs = attrsWithHealthCheckService("TeeService");
ResolvedAddresses result = ResolvedAddresses.newBuilder().setAddresses(resolvedAddressList).setAttributes(resolutionAttrs).build();
hcLbEventDelivery.handleResolvedAddresses(result);
verify(origLb).handleResolvedAddresses(result);
verifyNoMoreInteractions(origLb);
FakeSubchannel subchannel = unwrap(createSubchannel(0, Attributes.EMPTY));
assertThat(subchannel).isSameInstanceAs(subchannels[0]);
SubchannelStateListener mockListener = mockStateListeners[0];
InOrder inOrder = inOrder(mockListener, backoffPolicyProvider, backoffPolicy1, backoffPolicy2);
deliverSubchannelState(0, ConnectivityStateInfo.forNonError(READY));
inOrder.verify(mockListener).onSubchannelState(eq(ConnectivityStateInfo.forNonError(CONNECTING)));
HealthImpl healthImpl = healthImpls[0];
assertThat(healthImpl.calls).hasSize(1);
assertThat(clock.getPendingTasks()).isEmpty();
subchannel.logs.clear();
// Server closes the health checking RPC without any response
healthImpl.calls.poll().responseObserver.onCompleted();
// which results in TRANSIENT_FAILURE
inOrder.verify(mockListener).onSubchannelState(unavailableStateWithMsg("Health-check stream unexpectedly closed with " + Status.OK + " for 'TeeService'"));
assertThat(subchannel.logs).containsExactly("INFO: TRANSIENT_FAILURE: health-check stream closed with " + Status.OK, "DEBUG: Will retry health-check after 11 ns").inOrder();
// Retry with backoff is scheduled
inOrder.verify(backoffPolicyProvider).get();
inOrder.verify(backoffPolicy1).nextBackoffNanos();
assertThat(clock.getPendingTasks()).hasSize(1);
verifyRetryAfterNanos(inOrder, mockListener, healthImpl, 11);
assertThat(clock.getPendingTasks()).isEmpty();
subchannel.logs.clear();
// Server closes the health checking RPC without any response
healthImpl.calls.poll().responseObserver.onError(Status.CANCELLED.asException());
// which also results in TRANSIENT_FAILURE, with a different description
inOrder.verify(mockListener).onSubchannelState(unavailableStateWithMsg("Health-check stream unexpectedly closed with " + Status.CANCELLED + " for 'TeeService'"));
assertThat(subchannel.logs).containsExactly("INFO: TRANSIENT_FAILURE: health-check stream closed with " + Status.CANCELLED, "DEBUG: Will retry health-check after 21 ns").inOrder();
// Retry with backoff
inOrder.verify(backoffPolicy1).nextBackoffNanos();
verifyRetryAfterNanos(inOrder, mockListener, healthImpl, 21);
// Server responds this time
healthImpl.calls.poll().responseObserver.onNext(makeResponse(ServingStatus.SERVING));
inOrder.verify(mockListener).onSubchannelState(eq(ConnectivityStateInfo.forNonError(READY)));
verifyNoMoreInteractions(origLb, mockListener, backoffPolicyProvider, backoffPolicy1);
}
use of io.grpc.LoadBalancer.ResolvedAddresses in project grpc-java by grpc.
the class HealthCheckingLoadBalancerFactoryTest method balancerShutdown.
@Test
public void balancerShutdown() {
Attributes resolutionAttrs = attrsWithHealthCheckService("TeeService");
ResolvedAddresses result = ResolvedAddresses.newBuilder().setAddresses(resolvedAddressList).setAttributes(resolutionAttrs).build();
hcLbEventDelivery.handleResolvedAddresses(result);
verify(origLb).handleResolvedAddresses(result);
verifyNoMoreInteractions(origLb);
ServerSideCall[] serverCalls = new ServerSideCall[NUM_SUBCHANNELS];
final Subchannel[] wrappedSubchannels = new Subchannel[NUM_SUBCHANNELS];
for (int i = 0; i < NUM_SUBCHANNELS; i++) {
Subchannel subchannel = createSubchannel(i, Attributes.EMPTY);
wrappedSubchannels[i] = subchannel;
SubchannelStateListener mockListener = mockStateListeners[i];
assertThat(unwrap(subchannel)).isSameInstanceAs(subchannels[i]);
// Trigger the health check
deliverSubchannelState(i, ConnectivityStateInfo.forNonError(READY));
HealthImpl healthImpl = healthImpls[i];
assertThat(healthImpl.calls).hasSize(1);
serverCalls[i] = healthImpl.calls.poll();
assertThat(serverCalls[i].cancelled).isFalse();
verify(mockListener).onSubchannelState(eq(ConnectivityStateInfo.forNonError(CONNECTING)));
}
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) {
for (int i = 0; i < NUM_SUBCHANNELS; i++) {
wrappedSubchannels[i].shutdown();
}
return null;
}
}).when(origLb).shutdown();
// Shut down the balancer
hcLbEventDelivery.shutdown();
verify(origLb).shutdown();
// Health check stream should be cancelled
for (int i = 0; i < NUM_SUBCHANNELS; i++) {
assertThat(serverCalls[i].cancelled).isTrue();
verifyNoMoreInteractions(origLb);
verify(mockStateListeners[i]).onSubchannelState(ConnectivityStateInfo.forNonError(SHUTDOWN));
// No more health check call is made or scheduled
assertThat(healthImpls[i].calls).isEmpty();
}
assertThat(clock.getPendingTasks()).isEmpty();
}
use of io.grpc.LoadBalancer.ResolvedAddresses in project grpc-java by grpc.
the class HealthCheckingLoadBalancerFactoryTest method setup.
@Before
@SuppressWarnings("unchecked")
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
for (int i = 0; i < NUM_SUBCHANNELS; i++) {
HealthImpl healthImpl = new HealthImpl();
healthImpls[i] = healthImpl;
Server server = InProcessServerBuilder.forName("health-check-test-" + i).addService(healthImpl).directExecutor().build().start();
servers[i] = server;
ManagedChannel channel = InProcessChannelBuilder.forName("health-check-test-" + i).directExecutor().build();
channels[i] = channel;
EquivalentAddressGroup eag = new EquivalentAddressGroup(new FakeSocketAddress("address-" + i));
eags[i] = eag;
List<EquivalentAddressGroup> eagList = Arrays.asList(eag);
eagLists[i] = eagList;
mockStateListeners[i] = mock(SubchannelStateListener.class);
}
resolvedAddressList = Arrays.asList(eags);
when(backoffPolicyProvider.get()).thenReturn(backoffPolicy1, backoffPolicy2);
when(backoffPolicy1.nextBackoffNanos()).thenReturn(11L, 21L, 31L);
when(backoffPolicy2.nextBackoffNanos()).thenReturn(12L, 22L, 32L);
hcLbFactory = new HealthCheckingLoadBalancerFactory(origLbFactory, backoffPolicyProvider, clock.getStopwatchSupplier());
hcLb = hcLbFactory.newLoadBalancer(origHelper);
// Make sure all calls into the hcLb is from the syncContext
hcLbEventDelivery = new LoadBalancer() {
// Per LoadBalancer API, no more callbacks will be called after shutdown() is called.
boolean shutdown;
@Override
public void handleResolvedAddresses(final ResolvedAddresses resolvedAddresses) {
syncContext.execute(new Runnable() {
@Override
public void run() {
if (!shutdown) {
hcLb.handleResolvedAddresses(resolvedAddresses);
}
}
});
}
@Override
public void handleNameResolutionError(Status error) {
throw new AssertionError("Not supposed to be called");
}
@Override
public void shutdown() {
syncContext.execute(new Runnable() {
@Override
public void run() {
if (!shutdown) {
shutdown = true;
hcLb.shutdown();
}
}
});
}
};
verify(origLbFactory).newLoadBalancer(any(Helper.class));
}
Aggregations