com.linecorp.armeria.client.endpoint.EndpointGroup Java Examples

The following examples show how to use com.linecorp.armeria.client.endpoint.EndpointGroup. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: DefaultWebClientTest.java    From armeria with Apache License 2.0 6 votes vote down vote up
@Test
void endpointRemapper() {
    final EndpointGroup group = EndpointGroup.of(Endpoint.of("127.0.0.1", 1),
                                                 Endpoint.of("127.0.0.1", 1));
    final WebClient client = WebClient.builder("http://group")
                                      .endpointRemapper(endpoint -> {
                                          if ("group".equals(endpoint.host())) {
                                              return group;
                                          } else {
                                              return endpoint;
                                          }
                                      })
                                      .build();

    try (ClientRequestContextCaptor ctxCaptor = Clients.newContextCaptor()) {
        client.get("/").aggregate();
        final ClientRequestContext cctx = ctxCaptor.get();
        await().untilAsserted(() -> {
            assertThat(cctx.endpointGroup()).isSameAs(group);
            assertThat(cctx.endpoint()).isEqualTo(Endpoint.of("127.0.0.1", 1));
            assertThat(cctx.request().authority()).isEqualTo("127.0.0.1:1");
        });
    }
}
 
Example #2
Source File: RetryingClientWithMetricsTest.java    From armeria with Apache License 2.0 6 votes vote down vote up
@Test
void retryingThenMetricCollectingWithConnectionRefused() throws Exception {
    // The first request will fail with an UnprocessedException and
    // the second request will succeed with 200.
    final EndpointGroup group = EndpointGroup.of(Endpoint.of("127.0.0.1", 1),
                                                 server.httpEndpoint());
    final WebClient client =
            WebClient.builder(SessionProtocol.HTTP, group)
                     .factory(clientFactory)
                     .decorator(MetricCollectingClient.newDecorator(meterIdPrefixFunction))
                     .decorator(RetryingClient.newDecorator(RetryRule.onUnprocessed()))
                     .build();
    assertThat(client.get("/ok").aggregate().join().status()).isEqualTo(HttpStatus.OK);

    // wait until 2 calls are recorded.
    await().untilAsserted(() -> {
        assertThat(MoreMeters.measureAll(meterRegistry))
                .containsEntry("foo.requests#count{http.status=200,method=GET,result=success}", 1.0)
                .containsEntry("foo.requests#count{http.status=200,method=GET,result=failure}", 0.0)
                .containsEntry("foo.requests#count{http.status=0,method=GET,result=success}", 0.0)
                .containsEntry("foo.requests#count{http.status=0,method=GET,result=failure}", 1.0);
    });
}
 
Example #3
Source File: GrpcClientTest.java    From armeria with Apache License 2.0 6 votes vote down vote up
@Test
void endpointRemapper() {
    final EndpointGroup group = Endpoint.of("127.0.0.1", server.httpPort());
    final TestServiceBlockingStub stub =
            Clients.builder("gproto+http://my-group")
                   .endpointRemapper(endpoint -> {
                       if ("my-group".equals(endpoint.host())) {
                           return group;
                       } else {
                           return endpoint;
                       }
                   })
                   .build(TestServiceBlockingStub.class);

    assertThat(stub.emptyCall(Empty.newBuilder().build())).isNotNull();
}
 
Example #4
Source File: DefaultWebClientTest.java    From armeria with Apache License 2.0 6 votes vote down vote up
@Test
void endpointRemapperForUnspecifiedUri() {
    final EndpointGroup group = EndpointGroup.of(Endpoint.of("127.0.0.1", 1),
                                                 Endpoint.of("127.0.0.1", 1));
    final WebClient client = WebClient.builder()
                                      .endpointRemapper(endpoint -> {
                                          if ("group".equals(endpoint.host())) {
                                              return group;
                                          } else {
                                              return endpoint;
                                          }
                                      })
                                      .build();

    try (ClientRequestContextCaptor ctxCaptor = Clients.newContextCaptor()) {
        client.get("http://group").aggregate();
        final ClientRequestContext cctx = ctxCaptor.get();
        await().untilAsserted(() -> {
            assertThat(cctx.endpointGroup()).isSameAs(group);
            assertThat(cctx.endpoint()).isEqualTo(Endpoint.of("127.0.0.1", 1));
            assertThat(cctx.request().authority()).isEqualTo("127.0.0.1:1");
        });
    }
}
 
Example #5
Source File: ArmeriaCentralDogmaBuilderTest.java    From centraldogma with Apache License 2.0 6 votes vote down vote up
@Test
void buildingWithProfile() throws Exception {
    final ArmeriaCentralDogmaBuilder b = new ArmeriaCentralDogmaBuilder();
    b.healthCheckIntervalMillis(0);
    b.profile("xip");
    final EndpointGroup group = b.endpointGroup();

    assertThat(group).isNotNull();
    assertThat(group).isInstanceOf(CompositeEndpointGroup.class);
    final CompositeEndpointGroup compositeGroup = (CompositeEndpointGroup) group;
    final List<EndpointGroup> childGroups = compositeGroup.groups();
    assertThat(childGroups).hasSize(2);
    assertThat(childGroups.get(0)).isInstanceOf(DnsAddressEndpointGroup.class);
    assertThat(childGroups.get(1)).isInstanceOf(DnsAddressEndpointGroup.class);

    await().untilAsserted(() -> {
        final List<Endpoint> endpoints = group.endpoints();
        assertThat(endpoints).isNotNull();
        assertThat(endpoints).containsExactlyInAnyOrder(
                Endpoint.of("1.2.3.4.xip.io", 36462).withIpAddr("1.2.3.4"),
                Endpoint.of("5.6.7.8.xip.io", 8080).withIpAddr("5.6.7.8"));
    });
}
 
Example #6
Source File: RetryingClientWithMetricsTest.java    From armeria with Apache License 2.0 6 votes vote down vote up
@Test
public void metricCollectingThenRetryingWithConnectionRefused() throws Exception {
    // The first request will fail with an UnprocessedException and
    // the second request will succeed with 200.
    final EndpointGroup group = EndpointGroup.of(Endpoint.of("127.0.0.1", 1),
                                                 server.httpEndpoint());
    final WebClient client =
            WebClient.builder(SessionProtocol.HTTP, group)
                     .factory(clientFactory)
                     .decorator(RetryingClient.newDecorator(RetryRule.onUnprocessed()))
                     .decorator(MetricCollectingClient.newDecorator(MeterIdPrefixFunction.ofDefault("foo")))
                     .build();

    assertThat(client.get("/ok").aggregate().join().status()).isEqualTo(HttpStatus.OK);

    // wait until 1 call is recorded.
    await().untilAsserted(() -> {
        assertThat(MoreMeters.measureAll(meterRegistry))
                .containsEntry("foo.requests#count{http.status=200,method=GET,result=success}", 1.0)
                .containsEntry("foo.requests#count{http.status=200,method=GET,result=failure}", 0.0);
    });
}
 
Example #7
Source File: ArmeriaCentralDogmaBuilder.java    From centraldogma with Apache License 2.0 6 votes vote down vote up
/**
 * Returns a newly-created {@link CentralDogma} instance.
 *
 * @throws UnknownHostException if failed to resolve the host names from the DNS servers
 */
public CentralDogma build() throws UnknownHostException {
    final EndpointGroup endpointGroup = endpointGroup();
    final String scheme = "none+" + (isUseTls() ? "https" : "http");
    final ClientBuilder builder =
            newClientBuilder(scheme, endpointGroup, cb -> cb.decorator(DecodingClient.newDecorator()), "/");
    final EventLoopGroup executor = clientFactory().eventLoopGroup();
    final int maxRetriesOnReplicationLag = maxNumRetriesOnReplicationLag();
    final CentralDogma dogma = new ArmeriaCentralDogma(executor,
                                                       builder.build(WebClient.class),
                                                       accessToken());
    if (maxRetriesOnReplicationLag <= 0) {
        return dogma;
    } else {
        return new ReplicationLagTolerantCentralDogma(
                executor, dogma, maxRetriesOnReplicationLag, retryIntervalOnReplicationLagMillis(),
                () -> {
                    // FIXME(trustin): Note that this will always return `null` due to a known limitation
                    //                 in Armeria: https://github.com/line/armeria/issues/760
                    final ClientRequestContext ctx = ClientRequestContext.currentOrNull();
                    return ctx != null ? ctx.remoteAddress() : null;
                });
    }
}
 
Example #8
Source File: ArmeriaCallFactoryTest.java    From armeria with Apache License 2.0 6 votes vote down vote up
@Test
void urlAnnotation() throws Exception {
    final EndpointGroup groupFoo = EndpointGroup.of(Endpoint.of("127.0.0.1", 1),
                                                    Endpoint.of("127.0.0.1", 1));
    final EndpointGroup groupBar = EndpointGroup.of(Endpoint.of("127.0.0.1", server.httpPort()),
                                                    Endpoint.of("127.0.0.1", server.httpPort()));

    final WebClient baseWebClient = WebClient.builder(SessionProtocol.HTTP, groupFoo)
                                             .endpointRemapper(endpoint -> {
                                                 if ("group_bar".equals(endpoint.host())) {
                                                     return groupBar;
                                                 } else {
                                                     return endpoint;
                                                 }
                                             })
                                             .build();

    final Service service = ArmeriaRetrofit.builder(baseWebClient)
                                           .addConverterFactory(converterFactory)
                                           .build()
                                           .create(Service.class);

    // The request should never go to 'groupFoo'.
    final Pojo pojo = service.fullUrl("http://group_bar/pojo").get();
    assertThat(pojo).isEqualTo(new Pojo("Cony", 26));
}
 
Example #9
Source File: ElasticsearchDomainEndpoint.java    From zipkin-aws with Apache License 2.0 5 votes vote down vote up
ElasticsearchDomainEndpoint(Function<EndpointGroup, WebClient> clientFactory, Endpoint endpoint,
    String region, String domain) {
  this.clientFactory = clientFactory;
  this.endpoint = endpoint;
  this.region = region;
  this.domain = domain;
}
 
Example #10
Source File: RetryingClientAuthorityHeaderTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
private static WebClient newHttpClientWithEndpointGroup() {
    final EndpointGroup endpointGroup = EndpointGroup.of(
            Endpoint.of("www.foo.com", backend1.httpPort()).withIpAddr("127.0.0.1"),
            Endpoint.of("www.bar.com", backend2.httpPort()).withIpAddr("127.0.0.1"));

    return WebClient.builder(SessionProtocol.H2C, endpointGroup)
                    .decorator(RetryingClient.newDecorator(
                            RetryRule.builder().onServerErrorStatus().onException().thenBackoff()))
                    .build();
}
 
Example #11
Source File: ClientBuilderParams.java    From armeria with Apache License 2.0 5 votes vote down vote up
/**
 * Returns a newly created {@link ClientBuilderParams} from the specified properties.
 */
static ClientBuilderParams of(Scheme scheme, EndpointGroup endpointGroup,
                              @Nullable String path, Class<?> type, ClientOptions options) {
    requireNonNull(scheme, "scheme");
    requireNonNull(endpointGroup, "endpointGroup");
    requireNonNull(type, "type");
    requireNonNull(options, "options");
    return new DefaultClientBuilderParams(scheme, endpointGroup, path, type, options);
}
 
Example #12
Source File: HealthCheckedEndpointGroupLongPollingTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
/**
 * Makes sure the notification occurs as soon as possible thanks to long polling.
 */
private static void waitForGroup(EndpointGroup group, @Nullable Endpoint expectedEndpoint) {
    final Stopwatch stopwatch = Stopwatch.createStarted();
    if (expectedEndpoint != null) {
        await().untilAsserted(() -> assertThat(group.endpoints()).containsExactly(expectedEndpoint));
    } else {
        await().untilAsserted(() -> assertThat(group.endpoints()).isEmpty());
    }
    assertThat(stopwatch.elapsed(TimeUnit.MILLISECONDS)).isLessThan(RETRY_INTERVAL.toMillis() / 3);
}
 
Example #13
Source File: AbstractWebClientBuilder.java    From armeria with Apache License 2.0 5 votes vote down vote up
/**
 * Creates a new instance.
 *
 * @throws IllegalArgumentException if the {@code sessionProtocol} is not one of the fields
 *                                  in {@link SessionProtocol}
 */
protected AbstractWebClientBuilder(SessionProtocol sessionProtocol, EndpointGroup endpointGroup,
                                   @Nullable String path) {
    validateScheme(requireNonNull(sessionProtocol, "sessionProtocol").uriText());
    if (path != null) {
        checkArgument(path.startsWith("/"),
                      "path: %s (expected: an absolute path starting with '/')", path);
    }

    uri = null;
    scheme = Scheme.of(SerializationFormat.NONE, sessionProtocol);
    this.endpointGroup = requireNonNull(endpointGroup, "endpointGroup");
    this.path = path;
}
 
Example #14
Source File: HealthCheckedEndpointGroupIntegrationTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@ParameterizedTest
@EnumSource(value = SessionProtocol.class, names = { "HTTP", "HTTPS" })
void endpoints_containsUnhealthyServer(SessionProtocol protocol) throws Exception {
    serverOne.start();

    final int portOne = serverOne.port(protocol);
    final int portTwo = 1;
    try (HealthCheckedEndpointGroup endpointGroup = build(
            HealthCheckedEndpointGroup.builder(
                    EndpointGroup.of(Endpoint.of("127.0.0.1", portOne),
                                     Endpoint.of("127.0.0.1", portTwo)),
                    HEALTH_CHECK_PATH),
            protocol)) {

        endpointGroup.newMeterBinder("bar").bindTo(registry);

        await().untilAsserted(() -> {
            assertThat(endpointGroup.endpoints())
                    .containsOnly(Endpoint.of("127.0.0.1", portOne));

            assertThat(MoreMeters.measureAll(registry))
                    .containsEntry("armeria.client.endpoint.group.count#value{name=bar,state=healthy}", 1.0)
                    .containsEntry("armeria.client.endpoint.group.count#value{name=bar,state=unhealthy}",
                                   1.0)
                    .containsEntry("armeria.client.endpoint.group.healthy#value" +
                                   "{authority=127.0.0.1:" + portOne + ",ip=127.0.0.1,name=bar}", 1.0)
                    .containsEntry("armeria.client.endpoint.group.healthy#value" +
                                   "{authority=127.0.0.1:" + portTwo + ",ip=127.0.0.1,name=bar}", 0.0);
        });
    }
}
 
Example #15
Source File: ZipkinElasticsearchAwsStorageModule.java    From zipkin-aws with Apache License 2.0 5 votes vote down vote up
/**
 * When the domain variable is set, we lookup the elasticsearch domain url dynamically, using the
 * AWS api. Otherwise, we assume the URL specified in ES_HOSTS is correct.
 */
@Bean @Qualifier(QUALIFIER) @Conditional(AwsDomainSetCondition.class)
Supplier<EndpointGroup> esInitialEndpoints(Function<EndpointGroup, WebClient> clientFactory,
    String region, ZipkinElasticsearchAwsStorageProperties aws) {
  return new ElasticsearchDomainEndpoint(clientFactory,
      Endpoint.of("es." + region + ".amazonaws.com", 443), region, aws.getDomain());
}
 
Example #16
Source File: MaxNumEventLoopsPerEndpointTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
private static void acquireTenEntries(DefaultEventLoopScheduler s,
                                      SessionProtocol sessionProtocol,
                                      EndpointGroup endpointGroup,
                                      Endpoint endpoint) {
    for (int i = 0; i < 10; i++) {
        s.acquire(sessionProtocol, endpointGroup, endpoint);
    }
}
 
Example #17
Source File: ArmeriaCentralDogmaBuilderTest.java    From centraldogma with Apache License 2.0 5 votes vote down vote up
@Test
void buildingWithMultipleHosts() throws Exception {
    final ArmeriaCentralDogmaBuilder b = new ArmeriaCentralDogmaBuilder();
    b.healthCheckIntervalMillis(0);
    b.host("1.2.3.4.xip.io", 1); // Unresolved host
    b.host("5.6.7.8.xip.io", 2); // Another unresolved host
    b.host("4.3.2.1", 3); // Resolved host
    b.host("8.7.6.5", 4); // Another resolved host

    final EndpointGroup endpointGroup = b.endpointGroup();
    assertThat(endpointGroup).isNotNull();
    assertThat(endpointGroup).isInstanceOf(CompositeEndpointGroup.class);
    final CompositeEndpointGroup compositeGroup = (CompositeEndpointGroup) endpointGroup;
    final List<EndpointGroup> childGroups = compositeGroup.groups();
    assertThat(childGroups).hasSize(3);
    assertThat(childGroups.get(0)).isInstanceOf(DnsAddressEndpointGroup.class);
    assertThat(childGroups.get(1)).isInstanceOf(DnsAddressEndpointGroup.class);
    assertThat(childGroups.get(2).toString()).contains("StaticEndpointGroup");

    await().untilAsserted(() -> {
        final List<Endpoint> endpoints = endpointGroup.endpoints();
        assertThat(endpoints).isNotNull();
        assertThat(endpoints).containsExactlyInAnyOrder(
                Endpoint.of("1.2.3.4.xip.io", 1).withIpAddr("1.2.3.4"),
                Endpoint.of("5.6.7.8.xip.io", 2).withIpAddr("5.6.7.8"),
                Endpoint.of("4.3.2.1", 3),
                Endpoint.of("8.7.6.5", 4));
    });
}
 
Example #18
Source File: ClientBuilder.java    From armeria with Apache License 2.0 5 votes vote down vote up
ClientBuilder(Scheme scheme, EndpointGroup endpointGroup, @Nullable String path) {
    if (path != null) {
        checkArgument(path.startsWith("/"),
                      "path: %s (expected: an absolute path starting with '/')", path);
    }
    uri = null;
    this.endpointGroup = endpointGroup;
    this.path = path;
    this.scheme = scheme;
}
 
Example #19
Source File: RetryingClientWithEmptyEndpointGroupTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Test
void shouldRetryEvenIfEndpointGroupIsEmpty() {
    final int numAttempts = 3;
    final WebClient client =
            WebClient.builder(SessionProtocol.HTTP, EndpointGroup.empty())
                     .decorator(RetryingClient.builder(RetryRule.builder()
                                                                .onUnprocessed()
                                                                .thenBackoff(Backoff.withoutDelay()))
                                              .maxTotalAttempts(numAttempts)
                                              .newDecorator())
                     .build();

    final ClientRequestContext ctx;
    try (ClientRequestContextCaptor ctxCaptor = Clients.newContextCaptor()) {
        client.get("/").aggregate();
        ctx = ctxCaptor.get();
    }

    // Make sure all attempts have failed with `EmptyEndpointGroupException`.
    final RequestLog log = ctx.log().whenComplete().join();
    assertEmptyEndpointGroupException(log);

    assertThat(log.children()).hasSize(numAttempts);
    log.children().stream()
       .map(RequestLogAccess::ensureComplete)
       .forEach(RetryingClientWithEmptyEndpointGroupTest::assertEmptyEndpointGroupException);
}
 
Example #20
Source File: ClientUtil.java    From armeria with Apache License 2.0 5 votes vote down vote up
private static EndpointGroup mapEndpoint(ClientRequestContext ctx, EndpointGroup endpointGroup) {
    if (endpointGroup instanceof Endpoint) {
        return requireNonNull(ctx.options().endpointRemapper().apply((Endpoint) endpointGroup),
                              "endpointRemapper returned null.");
    } else {
        return endpointGroup;
    }
}
 
Example #21
Source File: DefaultClientRequestContext.java    From armeria with Apache License 2.0 5 votes vote down vote up
private void acquireEventLoop(EndpointGroup endpointGroup) {
    if (eventLoop == null) {
        final ReleasableHolder<EventLoop> releasableEventLoop =
                options().factory().acquireEventLoop(sessionProtocol(), endpointGroup, endpoint);
        eventLoop = releasableEventLoop.get();
        log.whenComplete().thenAccept(unused -> releasableEventLoop.release());
    }
}
 
Example #22
Source File: DefaultClientRequestContext.java    From armeria with Apache License 2.0 5 votes vote down vote up
private CompletableFuture<Boolean> initEndpointGroup(EndpointGroup endpointGroup) {
    this.endpointGroup = endpointGroup;
    // Note: thread-local customizer must be run before EndpointSelector.select()
    //       so that the customizer can inject the attributes which may be required
    //       by the EndpointSelector.
    runThreadLocalContextCustomizers();
    final Endpoint endpoint = endpointGroup.selectNow(this);
    if (endpoint != null) {
        updateEndpoint(endpoint);
        acquireEventLoop(endpointGroup);
        return UnmodifiableFuture.completedFuture(true);
    }

    // Use an arbitrary event loop for asynchronous Endpoint selection.
    final EventLoop temporaryEventLoop = options().factory().eventLoopSupplier().get();
    return endpointGroup.select(this, temporaryEventLoop, connectTimeoutMillis()).handle((e, cause) -> {
        updateEndpoint(e);
        acquireEventLoop(endpointGroup);

        final boolean success;
        if (cause != null) {
            failEarly(cause);
            success = false;
        } else {
            success = true;
        }

        final EventLoop acquiredEventLoop = eventLoop();
        if (acquiredEventLoop == temporaryEventLoop) {
            // We were lucky. No need to hand over to other EventLoop.
            return UnmodifiableFuture.completedFuture(success);
        } else {
            // We need to hand over to the acquired EventLoop.
            return CompletableFuture.supplyAsync(() -> success, acquiredEventLoop);
        }
    }).thenCompose(Function.identity());
}
 
Example #23
Source File: HealthCheckedEndpointGroup.java    From armeria with Apache License 2.0 5 votes vote down vote up
/**
 * Creates a new instance.
 */
HealthCheckedEndpointGroup(
        EndpointGroup delegate, SessionProtocol protocol, int port,
        Backoff retryBackoff, ClientOptions clientOptions,
        Function<? super HealthCheckerContext, ? extends AsyncCloseable> checkerFactory,
        HealthCheckStrategy healthCheckStrategy) {

    super(requireNonNull(delegate, "delegate").selectionStrategy());

    this.delegate = delegate;
    this.protocol = requireNonNull(protocol, "protocol");
    this.port = port;
    this.retryBackoff = requireNonNull(retryBackoff, "retryBackoff");
    this.clientOptions = requireNonNull(clientOptions, "clientOptions");
    this.checkerFactory = requireNonNull(checkerFactory, "checkerFactory");
    this.healthCheckStrategy = requireNonNull(healthCheckStrategy, "healthCheckStrategy");

    clientOptions.factory().whenClosed().thenRun(this::closeAsync);
    delegate.addListener(this::updateCandidates);
    updateCandidates(delegate.whenReady().join());

    // Wait until the initial health of all endpoints are determined.
    final List<DefaultHealthCheckerContext> snapshot;
    synchronized (contexts) {
        snapshot = ImmutableList.copyOf(contexts.values());
    }
    snapshot.forEach(ctx -> ctx.initialCheckFuture.join());

    // If all endpoints are unhealthy, we will not have called setEndpoints even once, meaning listeners
    // aren't notified that we've finished an initial health check. We make sure to refresh endpoints once
    // on initialization to ensure this happens, even if the endpoints are currently empty.
    refreshEndpoints();
}
 
Example #24
Source File: HealthCheckedEndpointGroupIntegrationTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@ParameterizedTest
@EnumSource(value = SessionProtocol.class, names = { "HTTP", "HTTPS" })
void endpoints_duplicateEntries(SessionProtocol protocol) throws Exception {
    serverOne.start();

    final int portOne = serverOne.port(protocol);
    try (HealthCheckedEndpointGroup endpointGroup = build(
            HealthCheckedEndpointGroup.builder(
                    EndpointGroup.of(Endpoint.of("127.0.0.1", portOne),
                                     Endpoint.of("127.0.0.1", portOne),
                                     Endpoint.of("127.0.0.1", portOne)),
                    HEALTH_CHECK_PATH),
            protocol)) {

        endpointGroup.newMeterBinder("baz").bindTo(registry);

        await().untilAsserted(() -> {
            assertThat(endpointGroup.endpoints())
                    .containsOnly(Endpoint.of("127.0.0.1", portOne));

            assertThat(MoreMeters.measureAll(registry))
                    .containsEntry("armeria.client.endpoint.group.count#value{name=baz,state=healthy}", 3.0)
                    .containsEntry("armeria.client.endpoint.group.count#value{name=baz,state=unhealthy}",
                                   0.0)
                    .containsEntry("armeria.client.endpoint.group.healthy#value" +
                                   "{authority=127.0.0.1:" + portOne + ",ip=127.0.0.1,name=baz}", 1.0);
        });
        serverOne.stop();
        await().untilAsserted(() -> assertThat(endpointGroup.endpoints()).isEmpty());
    }
}
 
Example #25
Source File: DefaultClientBuilderParams.java    From armeria with Apache License 2.0 5 votes vote down vote up
DefaultClientBuilderParams(Scheme scheme, EndpointGroup endpointGroup,
                           @Nullable String absolutePathRef,
                           Class<?> type, ClientOptions options) {
    final ClientFactory factory = requireNonNull(options, "options").factory();
    this.scheme = factory.validateScheme(scheme);
    this.endpointGroup = requireNonNull(endpointGroup, "endpointGroup");
    this.type = requireNonNull(type, "type");
    this.options = options;

    final String schemeStr;
    if (scheme.serializationFormat() == SerializationFormat.NONE) {
        schemeStr = scheme.sessionProtocol().uriText();
    } else {
        schemeStr = scheme.uriText();
    }

    final String normalizedAbsolutePathRef = nullOrEmptyToSlash(absolutePathRef);
    final URI uri;
    if (endpointGroup instanceof Endpoint) {
        uri = URI.create(schemeStr + "://" + ((Endpoint) endpointGroup).authority() +
                         normalizedAbsolutePathRef);
    } else {
        // Create a valid URI which will never succeed.
        uri = URI.create(schemeStr + "://armeria-group-" +
                         Integer.toHexString(System.identityHashCode(endpointGroup)) +
                         ":1" + normalizedAbsolutePathRef);
    }

    this.uri = factory.validateUri(uri);
    this.absolutePathRef = normalizedAbsolutePathRef;
}
 
Example #26
Source File: Clients.java    From armeria with Apache License 2.0 5 votes vote down vote up
/**
 * Returns a new {@link ClientBuilder} that builds the client that connects to the specified
 * {@link EndpointGroup} with the specified {@link Scheme} and {@code path}.
 */
public static ClientBuilder builder(Scheme scheme, EndpointGroup endpointGroup, String path) {
    requireNonNull(scheme, "scheme");
    requireNonNull(endpointGroup, "endpointGroup");
    requireNonNull(path, "path");
    return new ClientBuilder(scheme, endpointGroup, path);
}
 
Example #27
Source File: ArmeriaRetrofitBuilderTest.java    From armeria with Apache License 2.0 5 votes vote down vote up
@Test
void build_armeriaGroupAuthority() {
    final Endpoint endpoint = Endpoint.of("127.0.0.1", 8080);
    final EndpointGroup group = EndpointGroup.of(endpoint, endpoint);

    assertThat(ArmeriaRetrofit.of(SessionProtocol.H2C, endpoint).baseUrl().toString())
            .isEqualTo("http://127.0.0.1:8080/");

    assertThat(ArmeriaRetrofit.of(SessionProtocol.H2, group).baseUrl().toString())
            .startsWith("https://armeria-group-");
}
 
Example #28
Source File: AbstractArmeriaCentralDogmaBuilder.java    From centraldogma with Apache License 2.0 4 votes vote down vote up
/**
 * Returns the {@link EndpointGroup} this client will connect to, derived from {@link #hosts()}.
 *
 * @throws UnknownHostException if failed to resolve the host names from the DNS servers
 */
protected final EndpointGroup endpointGroup() throws UnknownHostException {
    final Set<InetSocketAddress> hosts = hosts();
    checkState(!hosts.isEmpty(), "no hosts were added.");

    final InetSocketAddress firstHost = Iterables.getFirst(hosts, null);
    if (hosts.size() == 1 && !firstHost.isUnresolved()) {
        return toResolvedHostEndpoint(firstHost);
    }

    final List<Endpoint> staticEndpoints = new ArrayList<>();
    final List<EndpointGroup> groups = new ArrayList<>();
    for (final InetSocketAddress addr : hosts) {
        if (addr.isUnresolved()) {
            groups.add(DnsAddressEndpointGroup.builder(addr.getHostString())
                                              .eventLoop(clientFactory.eventLoopGroup().next())
                                              .port(addr.getPort())
                                              .build());
        } else {
            staticEndpoints.add(toResolvedHostEndpoint(addr));
        }
    }

    if (!staticEndpoints.isEmpty()) {
        groups.add(EndpointGroup.of(staticEndpoints));
    }

    final EndpointGroup group;
    if (groups.size() == 1) {
        group = groups.get(0);
    } else {
        group = new CompositeEndpointGroup(groups, EndpointSelectionStrategy.roundRobin());
    }

    if (group instanceof DynamicEndpointGroup) {
        // Wait until the initial endpointGroup list is ready.
        try {
            group.whenReady().get(10, TimeUnit.SECONDS);
        } catch (Exception e) {
            final UnknownHostException cause = new UnknownHostException(
                    "failed to resolve any of: " + hosts);
            cause.initCause(e);
            throw cause;
        }
    }

    if (!healthCheckInterval.isZero()) {
        return HealthCheckedEndpointGroup.builder(group, HttpApiV1Constants.HEALTH_CHECK_PATH)
                                         .clientFactory(clientFactory)
                                         .protocol(isUseTls() ? SessionProtocol.HTTPS
                                                              : SessionProtocol.HTTP)
                                         .retryInterval(healthCheckInterval)
                                         .build();
    } else {
        return group;
    }
}
 
Example #29
Source File: RetryingClientLoadBalancingTest.java    From armeria with Apache License 2.0 4 votes vote down vote up
/**
 * Makes sure that {@link RetryingClient} respects the {@link Endpoint} selection order.
 */
@ParameterizedTest
@EnumSource(TestMode.class)
void test(TestMode mode) {
    server.start();
    final List<Integer> expectedPorts = server.server().activePorts().keySet().stream()
                                              .map(InetSocketAddress::getPort)
                                              .collect(toImmutableList());

    final EndpointGroup group = EndpointGroup.of(EndpointSelectionStrategy.roundRobin(),
                                                 expectedPorts.stream()
                                                              .map(port -> Endpoint.of("127.0.0.1", port))
                                                              .collect(toImmutableList()));

    final RetryRule retryRule = (ctx, cause) -> {
        // Get the response status.
        final HttpStatus status;
        if (ctx.log().isAvailable(RequestLogProperty.RESPONSE_HEADERS)) {
            status = ctx.log().partial().responseHeaders().status();
        } else {
            status = null;
        }

        // Retry only once on failure.
        if (!HttpStatus.OK.equals(status) && AbstractRetryingClient.getTotalAttempts(ctx) <= 1) {
            return CompletableFuture.completedFuture(RetryDecision.retry(Backoff.withoutDelay()));
        } else {
            return CompletableFuture.completedFuture(RetryDecision.noRetry());
        }
    };
    final WebClient c = WebClient.builder(SessionProtocol.H2C, group)
                                 .decorator(RetryingClient.builder(retryRule)
                                                          .newDecorator())
                                 .build();

    for (int i = 0; i < NUM_PORTS; i++) {
        c.get(mode.path).aggregate().join();
    }

    switch (mode) {
        case SUCCESS:
            assertThat(accessedPorts).isEqualTo(expectedPorts);
            break;
        case FAILURE:
            final List<Integer> expectedPortsWhenRetried =
                    ImmutableList.<Integer>builder()
                            .addAll(expectedPorts)
                            .addAll(expectedPorts)
                            .build();
            assertThat(accessedPorts).isEqualTo(expectedPortsWhenRetried);
            break;
    }
}
 
Example #30
Source File: DefaultEventLoopScheduler.java    From armeria with Apache License 2.0 4 votes vote down vote up
/**
 * Returns the {@link AbstractEventLoopState} in the map whose key is {@link StateKey}. If the IP address
 * exists in the specified {@link Endpoint}, it's used in the key to find the
 * {@link AbstractEventLoopState} first. Then {@link Endpoint#host()} is used.
 * If {@link AbstractEventLoopState} does not exist in the map, the state is created with the maximum
 * number of {@link EventLoop}s. The number can be produced by the {@code maxNumEventLoopsFunction} or
 * {@code maxNumEventLoopsPerEndpoint} and {@code maxNumEventLoopsPerHttp1Endpoint} dependent on
 * the {@link SessionProtocol} when the {@code maxNumEventLoopsFunction} does not produce a value.
 */
private AbstractEventLoopState state(SessionProtocol sessionProtocol,
                                     EndpointGroup endpointGroup,
                                     @Nullable Endpoint endpoint) {
    if (endpoint == null) {
        // Use a fake endpoint if no endpoint was selected from the endpointGroup.
        endpoint = Endpoint.of(
                "armeria-group-" + Integer.toHexString(System.identityHashCode(endpointGroup)));
    }

    final String firstTryHost;
    final String secondTryHost;
    if (endpoint.hasIpAddr()) {
        final String ipAddr = endpoint.ipAddr();
        assert ipAddr != null;
        firstTryHost = ipAddr;
        if (endpoint.isIpAddrOnly()) {
            secondTryHost = null;
        } else {
            secondTryHost = endpoint.host();
        }
    } else {
        firstTryHost = endpoint.host();
        secondTryHost = null;
    }

    final int port = endpoint.hasPort() ? endpoint.port() : sessionProtocol.defaultPort();
    final Endpoint endpointWithPort = endpoint.withPort(port);
    final boolean isHttp1 = isHttp1(sessionProtocol, endpointWithPort);
    final StateKey firstKey = new StateKey(firstTryHost, port, isHttp1);
    AbstractEventLoopState state = states.get(firstKey);
    if (state != null) {
        return state;
    }

    if (secondTryHost != null) {
        final StateKey secondKey = new StateKey(secondTryHost, port, isHttp1);
        state = states.get(secondKey);
        if (state != null) {
            return state;
        }
    }

    // Try with the endpoint which has a port first.
    int maxNumEventLoopsCandidate = maxNumEventLoopsCandidate(endpointWithPort);
    if (maxNumEventLoopsCandidate <= 0 && !endpointWithPort.equals(endpoint)) {
        // Try without the port second.
        maxNumEventLoopsCandidate = maxNumEventLoopsCandidate(endpoint);
    }

    final int maxNumEventLoops =
            maxNumEventLoopsCandidate > 0 ? Math.min(maxNumEventLoopsCandidate, eventLoops.size())
                                          : maxNumEventLoops(sessionProtocol, endpointWithPort);
    return states.computeIfAbsent(firstKey,
                                  unused -> AbstractEventLoopState.of(eventLoops, maxNumEventLoops, this));
}