@Inject public CallsAnotherServiceHandler(RpcClientFactory factory) { rpcClient = factory.newClient("com.sixt.service.another-service", "AnotherService.ImpersonatorTest", CallAnotherServiceResponse.class).build(); }
@Inject public RpcClientBuilder(Injector injector) { this.injector = injector; initialize(); }
private void initialize() { ServiceProperties properties = injector.getInstance(ServiceProperties.class); retries = parseSetting(properties, "rpcClientRetries", DEFAULT_RETRIES); timeout = parseSetting(properties, "rpcClientTimeout", DEFAULT_RESPONSE_TIMEOUT); }
/** * Build an RpcClientBuilder. Use the withXXX methods to customize the behavior * of the client, then finish with builder.build(). */ public <RESPONSE extends Message> RpcClientBuilder<RESPONSE> newClient(String serviceName, String methodName, Class<RESPONSE> responseClass) { @SuppressWarnings("unchecked") RpcClientBuilder<RESPONSE> retval = (RpcClientBuilder<RESPONSE>) injector.getInstance(RpcClientBuilder.class); retval.setServiceName(serviceName); retval.setMethodName(methodName); retval.setResponseClass(responseClass); return retval; }
@Test public void singleServiceZeroRetries() throws Exception { //Verify retry behavior. Create 1 server and have it always fail. //Set retries to 0. Send a request, and verify server got issued one request. loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20001", "dc1", dependencyHealthCheck)); rpcClient = clientFactory.newClient(serviceName, "testing", FrameworkTest.Foobar.class). withRetries(0).build(); rpcClient.callSynchronous(FrameworkTest.Foobar.newBuilder().build(), new OrangeContext()); assertThat(httpClient.verifyRequestsProcessed(1, "localhost:20001")).isTrue(); }
clientFactory.newClient("com.sixt.service.configuration", "Configuration.GetValues", ConfigurationOuterClass.ValuesResponse.class). withRetries(0).withTimeout(LONG_POLL_TIMEOUT).build(); logger.debug("Calling configuration service, lastChangeIndex = {}", lastChangeIndex.get()); response = client.callSynchronous(configRequest, new OrangeContext());
@Test public void allInstancesTimeOut() { //Create 2 servers and have both timeout. Set retries to 1. Send request. //The response from the 2nd should be returned. loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20001", "dc1", dependencyHealthCheck)); loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20002", "dc1", dependencyHealthCheck)); rpcClient = clientFactory.newClient(serviceName, "testing", FrameworkTest.Foobar.class). withRetries(1).build(); httpClient.makeRequestsTimeout(); int failureCount = 0; try { rpcClient.callSynchronous(FrameworkTest.Foobar.newBuilder().build(), new OrangeContext()); } catch (RpcCallException ex) { failureCount++; assertThat(ex.getCategory()).isEqualTo(RpcCallException.Category.RequestTimedOut); } assertThat(failureCount).isEqualTo(1); assertThat(httpClient.verifyRequestsProcessed(1, "localhost:20001")).isTrue(); assertThat(httpClient.verifyRequestsProcessed(1, "localhost:20002")).isTrue(); }
@Test public void singleInstanceTimesOut() { //Create 2 servers and have one timeout. Set retries to 1. Send request. //The response from the 2nd should be returned. loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20001", "dc1", dependencyHealthCheck)); loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20002", "dc1", dependencyHealthCheck)); rpcClient = clientFactory.newClient(serviceName, "testing", FrameworkTest.Foobar.class). withRetries(1).build(); httpClient.makeFirstRequestTimeout(); try { rpcClient.callSynchronous(FrameworkTest.Foobar.newBuilder().build(), new OrangeContext()); } catch (java.lang.Exception e) { e.printStackTrace(); } assertThat(httpClient.verifyRequestsProcessed(1, "localhost:20001")).isTrue(); assertThat(httpClient.verifyRequestsProcessed(1, "localhost:20002")).isTrue(); }
@SuppressWarnings("unchecked") public Map<String, ServiceMethod<Message>> getMethodHandlers(String serviceName) { String serviceNameUnderscores = serviceName.replace("-", "_"); List<RpcMethodDefinition> rpcMethodDefinitions = getRpcMethodDefinitions(serviceNameUnderscores); // get the generated proto classes List<String> protoClasses = getGeneratedProtoClasses(serviceNameUnderscores); Map<String, ServiceMethod<Message>> serviceMethods = new HashMap<>(); for (RpcMethodDefinition def : rpcMethodDefinitions) { try { if (serviceMethods.containsKey(def.getMethodName())) { continue; } logger.info("Adding endpoint {} for {}", def.getMethodName(), serviceName); Class<? extends Message> protobufClass = findProtobufClass(protoClasses, def, def.getResponseType()); RpcClient rpcClient = rpcClientFactory.newClient(serviceName, def.getMethodName(), protobufClass).build(); serviceMethods.put(def.getMethodName(), new ServiceMethod(rpcClient, protobufClass)); } catch (ClassNotFoundException ex) { logger.error("Error while adding RPC endpoint for service " + serviceName, ex); } } return serviceMethods; }
@Test public void allFailingNoInstanceAvailable() { //Create 3 servers and have them always fail. Set retries to 4. Send request. //Each server should be tried once, then the request should fail. loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20001", "dc1", dependencyHealthCheck)); loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20002", "dc1", dependencyHealthCheck)); loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20003", "dc1", dependencyHealthCheck)); rpcClient = clientFactory.newClient(serviceName, "testing", FrameworkTest.Foobar.class). withRetries(4).build(); httpClient.makeFailing(); int failureCount = 0; try { rpcClient.callSynchronous(FrameworkTest.Foobar.newBuilder().build(), new OrangeContext()); } catch (java.lang.Exception e) { e.printStackTrace(); failureCount++; } assertThat(failureCount).isEqualTo(1); assertThat(httpClient.verifyRequestsProcessed(1, "localhost:20001")).isTrue(); assertThat(httpClient.verifyRequestsProcessed(1, "localhost:20002")).isTrue(); assertThat(httpClient.verifyRequestsProcessed(1, "localhost:20003")).isTrue(); }
public RpcClientIntegrationTest(String featureFlag) { this.featureFlag = featureFlag; TestInjectionModule module = new TestInjectionModule(featureFlag); ServiceProperties props = new ServiceProperties(); props.addProperty(FeatureFlags.FLAG_EXPOSE_ERRORS_HTTP, featureFlag); props.addProperty(FeatureFlags.DISABLE_RPC_INSTANCE_RETRY, "true"); props.addProperty(ServiceProperties.REGISTRY_SERVER_KEY, "localhost:65432"); props.addProperty("registry", "consul"); module.setServiceProperties(props); Injector injector = Guice.createInjector(module, new ServiceRegistryModule(props), new TracingModule(props)); httpClient = (MockHttpClient)injector.getInstance(HttpClient.class); clientFactory = injector.getInstance(RpcClientFactory.class); loadBalancerFactory = injector.getInstance(LoadBalancerFactory.class); rpcClient = clientFactory.newClient(serviceName, "testing", FrameworkTest.Foobar.class).build(); loadBalancer = (LoadBalancerImpl) loadBalancerFactory.getLoadBalancer(serviceName); dependencyHealthCheck = mock(ServiceDependencyHealthCheck.class); }
@Test public void retriableError() { //Create 2 servers and have both throw an exception that is retriable. //The exception should be thrown locally loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20001", "dc1", dependencyHealthCheck)); loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20002", "dc1", dependencyHealthCheck)); rpcClient = clientFactory.newClient(serviceName, "testing", FrameworkTest.Foobar.class). withRetries(1).build(); httpClient.setResponseException(new RpcCallException(RpcCallException.Category. InternalServerError, "test1234").withSource("testing567")); int failureCount = 0; try { rpcClient.callSynchronous(FrameworkTest.Foobar.newBuilder().build(), new OrangeContext()); } catch (RpcCallException ex) { failureCount++; assertThat(ex.getCategory()).isEqualTo(RpcCallException.Category.InternalServerError); assertThat(ex.getMessage()).isEqualTo("test1234"); assertThat(ex.getSource()).isEqualTo("testing567"); } assertThat(failureCount).isEqualTo(1); assertThat(httpClient.verifyRequestsProcessed(2)).isTrue(); }
@Test public void nonRetriableError() { //Create 2 servers and have the first throw an exception that is not retriable. //The exception should be thrown and not retried with the other node loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20001", "dc1", dependencyHealthCheck)); loadBalancer.addServiceEndpoint(new ServiceEndpoint(executor, "localhost:20002", "dc1", dependencyHealthCheck)); rpcClient = clientFactory.newClient(serviceName, "testing", FrameworkTest.Foobar.class). withRetries(1).build(); httpClient.setResponseException(new RpcCallException(RpcCallException.Category. InsufficientPermissions, "test").withSource("testing")); int failureCount = 0; try { rpcClient.callSynchronous(FrameworkTest.Foobar.newBuilder().build(), new OrangeContext()); } catch (RpcCallException ex) { failureCount++; assertThat(ex.getCategory()).isEqualTo(RpcCallException.Category.InsufficientPermissions); assertThat(ex.getMessage()).isEqualTo("test"); } assertThat(failureCount).isEqualTo(1); assertThat(httpClient.verifyRequestsProcessed(1)).isTrue(); }