diff --git a/docs/src/main/asciidoc/spring-cloud-commons.adoc b/docs/src/main/asciidoc/spring-cloud-commons.adoc
index 10e6cd68..3927cae0 100644
--- a/docs/src/main/asciidoc/spring-cloud-commons.adoc
+++ b/docs/src/main/asciidoc/spring-cloud-commons.adoc
@@ -979,7 +979,7 @@ TIP: The `HealthCheckServiceInstanceListSupplier` relies on having updated insta
`HealthCheckServiceInstanceListSupplier` uses properties prefixed with
`spring.cloud.loadbalancer.health-check`. You can set the `initialDelay` and `interval`
for the scheduler. You can set the default path for the healthcheck URL by setting
-the value of the `spring.cloud.loadbalancer.health-check.path.default` property. You can also set a specific value for any given service by setting the value of the `spring.cloud.loadbalancer.health-check.path.[SERVICE_ID]` property, substituting `[SERVICE_ID]` with the correct ID of your service. If the `[SERVICE_ID]` is not specified, `/actuator/health` is used by default. If the `[SERVICE_ID]` is set to `null` or empty as a value, then the health check will not be executed.
+the value of the `spring.cloud.loadbalancer.health-check.path.default` property. You can also set a specific value for any given service by setting the value of the `spring.cloud.loadbalancer.health-check.path.[SERVICE_ID]` property, substituting `[SERVICE_ID]` with the correct ID of your service. If the `[SERVICE_ID]` is not specified, `/actuator/health` is used by default. If the `[SERVICE_ID]` is set to `null` or empty as a value, then the health check will not be executed. You can also set a custom port for health-check requests by setting the value of `spring.cloud.loadbalancer.health-check.port`. If none is set, the port under which the requested service is available at the service instance.
TIP: If you rely on the default path (`/actuator/health`), make sure you add `spring-boot-starter-actuator` to your collaborator's dependencies, unless you are planning to add such an endpoint on your own.
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerProperties.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerProperties.java
index aa2d6bf6..388f99b1 100644
--- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerProperties.java
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerProperties.java
@@ -186,8 +186,19 @@ public class LoadBalancerProperties {
*/
private Duration refetchInstancesInterval = Duration.ofSeconds(25);
+ /**
+ * Path at which the health-check request should be made. Can be set up per
+ * serviceId. A default value can be set up as well. If
+ * none is set up, /actuator/health will be used.
+ */
private Map path = new LinkedCaseInsensitiveMap<>();
+ /**
+ * Path at which the health-check request should be made. If none is set, the port
+ * under which the requested service is available at the service instance.
+ */
+ private Integer port;
+
/**
* Indicates whether the instances should be refetched by the
* HealthCheckServiceInstanceListSupplier. This can be used if the
@@ -251,6 +262,14 @@ public class LoadBalancerProperties {
this.interval = interval;
}
+ public Integer getPort() {
+ return port;
+ }
+
+ public void setPort(Integer port) {
+ this.port = port;
+ }
+
}
public static class Retry {
diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/HealthCheckServiceInstanceListSupplier.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/HealthCheckServiceInstanceListSupplier.java
index 61182cef..18792431 100644
--- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/HealthCheckServiceInstanceListSupplier.java
+++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/HealthCheckServiceInstanceListSupplier.java
@@ -30,6 +30,7 @@ import reactor.retry.Repeat;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
+import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties;
import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
@@ -156,7 +157,7 @@ public class HealthCheckServiceInstanceListSupplier extends DelegatingServiceIns
return Mono.just(true);
}
String healthCheckPath = healthCheckPropertyValue != null ? healthCheckPropertyValue : defaultHealthCheckPath;
- return aliveFunction.apply(serviceInstance, healthCheckPath);
+ return aliveFunction.apply(updatedServiceInstance(serviceInstance), healthCheckPath);
}
@Override
@@ -167,4 +168,14 @@ public class HealthCheckServiceInstanceListSupplier extends DelegatingServiceIns
}
}
+ private ServiceInstance updatedServiceInstance(ServiceInstance serviceInstance) {
+ Integer healthCheckPort = healthCheck.getPort();
+ if (serviceInstance instanceof DefaultServiceInstance && healthCheckPort != null) {
+ return new DefaultServiceInstance(serviceInstance.getInstanceId(), serviceInstance.getServiceId(),
+ serviceInstance.getHost(), healthCheckPort, serviceInstance.isSecure(),
+ serviceInstance.getMetadata());
+ }
+ return serviceInstance;
+ }
+
}
diff --git a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/HealthCheckServiceInstanceListSupplierTests.java b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/HealthCheckServiceInstanceListSupplierTests.java
index 6814a54a..c33ece5b 100644
--- a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/HealthCheckServiceInstanceListSupplierTests.java
+++ b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/HealthCheckServiceInstanceListSupplierTests.java
@@ -41,6 +41,7 @@ import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties;
+import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.cloud.loadbalancer.support.ServiceInstanceListSuppliers;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping;
@@ -50,6 +51,7 @@ import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchThrowable;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -579,6 +581,27 @@ class HealthCheckServiceInstanceListSupplierTests {
assertThat(alive).isTrue();
}
+ @Test
+ void shouldCheckUseProvidedPortForHealthCheckRequest() {
+ Throwable exception = catchThrowable(() -> {
+ String serviceId = "ignored-service";
+ healthCheck.setPort(8888);
+ LoadBalancerProperties properties = new LoadBalancerProperties();
+ properties.setHealthCheck(healthCheck);
+ LoadBalancerClientFactory loadBalancerClientFactory = mock(LoadBalancerClientFactory.class);
+ when(loadBalancerClientFactory.getProperties(serviceId)).thenReturn(properties);
+ ServiceInstance serviceInstance = new DefaultServiceInstance("ignored-service-1", serviceId, "127.0.0.1",
+ port, false);
+ listSupplier = new HealthCheckServiceInstanceListSupplier(
+ ServiceInstanceListSuppliers.from(serviceId, serviceInstance), loadBalancerClientFactory,
+ healthCheckFunction(webClient));
+
+ listSupplier.isAlive(serviceInstance).block();
+ });
+
+ assertThat(exception).hasMessageContaining("Connection refused: /127.0.0.1:888");
+ }
+
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
@RestController