mirror of
https://gitee.com/mirrors/Spring-Cloud-Alibaba.git
synced 2021-06-26 13:25:11 +08:00
Add SentinelHealthIndicator to do some health check for Sentinel #265
This commit is contained in:
parent
5fd04277cb
commit
9c638b8d3f
@ -1,6 +1,8 @@
|
|||||||
spring.application.name=sentinel-example
|
spring.application.name=sentinel-example
|
||||||
server.port=18083
|
server.port=18083
|
||||||
management.endpoints.web.exposure.include=*
|
management.endpoints.web.exposure.include=*
|
||||||
|
management.endpoint.health.show-details=always
|
||||||
|
|
||||||
spring.cloud.sentinel.transport.dashboard=localhost:8080
|
spring.cloud.sentinel.transport.dashboard=localhost:8080
|
||||||
spring.cloud.sentinel.eager=true
|
spring.cloud.sentinel.eager=true
|
||||||
|
|
||||||
@ -19,4 +21,4 @@ spring.cloud.sentinel.datasource.ds4.file.file=classpath: system.json
|
|||||||
spring.cloud.sentinel.datasource.ds4.file.rule-type=system
|
spring.cloud.sentinel.datasource.ds4.file.rule-type=system
|
||||||
|
|
||||||
spring.cloud.sentinel.datasource.ds5.file.file=classpath: param-flow.json
|
spring.cloud.sentinel.datasource.ds5.file.file=classpath: param-flow.json
|
||||||
spring.cloud.sentinel.datasource.ds5.file.rule-type=param-flow
|
spring.cloud.sentinel.datasource.ds5.file.rule-type=param_flow
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package org.springframework.cloud.alibaba.sentinel.endpoint;
|
package org.springframework.cloud.alibaba.sentinel.endpoint;
|
||||||
|
|
||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
|
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
|
||||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
@ -38,4 +39,10 @@ public class SentinelEndpointAutoConfiguration {
|
|||||||
return new SentinelEndpoint(sentinelProperties);
|
return new SentinelEndpoint(sentinelProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
@ConditionalOnEnabledHealthIndicator("sentinel")
|
||||||
|
public SentinelHealthIndicator sentinelHealthIndicator(SentinelProperties sentinelProperties) {
|
||||||
|
return new SentinelHealthIndicator(sentinelProperties);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
package org.springframework.cloud.alibaba.sentinel.endpoint;
|
||||||
|
|
||||||
|
import com.alibaba.csp.sentinel.heartbeat.HeartbeatSenderProvider;
|
||||||
|
import com.alibaba.csp.sentinel.transport.HeartbeatSender;
|
||||||
|
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
|
||||||
|
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
|
||||||
|
import org.springframework.boot.actuate.health.Health;
|
||||||
|
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||||
|
import org.springframework.boot.actuate.health.Status;
|
||||||
|
import org.springframework.cloud.alibaba.sentinel.SentinelProperties;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link HealthIndicator} for Sentinel.
|
||||||
|
* <p>
|
||||||
|
* Check the status of Sentinel Dashboard by sending a heartbeat message to it.
|
||||||
|
*
|
||||||
|
* Note: if sentinel isn't enabled or sentinel-dashboard isn't configured,
|
||||||
|
* the health status is up and more infos are provided in detail.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author cdfive
|
||||||
|
*/
|
||||||
|
public class SentinelHealthIndicator extends AbstractHealthIndicator {
|
||||||
|
|
||||||
|
private SentinelProperties sentinelProperties;
|
||||||
|
|
||||||
|
public SentinelHealthIndicator(SentinelProperties sentinelProperties) {
|
||||||
|
this.sentinelProperties = sentinelProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doHealthCheck(Health.Builder builder) throws Exception {
|
||||||
|
Map<String, Object> detailMap = new HashMap<>();
|
||||||
|
|
||||||
|
// If sentinel isn't enabled, set the status up and set the enabled to false in detail
|
||||||
|
if (!sentinelProperties.isEnabled()) {
|
||||||
|
detailMap.put("enabled", false);
|
||||||
|
builder.up().withDetails(detailMap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
detailMap.put("enabled", true);
|
||||||
|
|
||||||
|
String consoleServer = TransportConfig.getConsoleServer();
|
||||||
|
// If dashboard isn't configured, set the status to UNKNOWN
|
||||||
|
if (StringUtils.isEmpty(consoleServer)) {
|
||||||
|
detailMap.put("dashboard", new Status(Status.UNKNOWN.getCode(), "dashboard isn't configured"));
|
||||||
|
builder.up().withDetails(detailMap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If dashboard is configured, send a heartbeat message to it and check the result
|
||||||
|
HeartbeatSender heartbeatSender = HeartbeatSenderProvider.getHeartbeatSender();
|
||||||
|
boolean result = heartbeatSender.sendHeartbeat();
|
||||||
|
if (result) {
|
||||||
|
detailMap.put("dashboard", Status.UP);
|
||||||
|
builder.up().withDetails(detailMap);
|
||||||
|
} else {
|
||||||
|
detailMap.put("dashboard", new Status(Status.DOWN.getCode(), consoleServer + " can't be connected"));
|
||||||
|
builder.down().withDetails(detailMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
package org.springframework.cloud.alibaba.sentinel.endpoint;
|
||||||
|
|
||||||
|
import com.alibaba.csp.sentinel.config.SentinelConfig;
|
||||||
|
import com.alibaba.csp.sentinel.heartbeat.HeartbeatSenderProvider;
|
||||||
|
import com.alibaba.csp.sentinel.transport.HeartbeatSender;
|
||||||
|
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.boot.actuate.health.Health;
|
||||||
|
import org.springframework.boot.actuate.health.Status;
|
||||||
|
import org.springframework.cloud.alibaba.sentinel.SentinelProperties;
|
||||||
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test cases for {@link SentinelHealthIndicator}.
|
||||||
|
*
|
||||||
|
* @author cdfive
|
||||||
|
*/
|
||||||
|
public class SentinelHealthIndicatorTests {
|
||||||
|
|
||||||
|
private SentinelHealthIndicator sentinelHealthIndicator;
|
||||||
|
|
||||||
|
private SentinelProperties sentinelProperties;
|
||||||
|
|
||||||
|
private HeartbeatSender heartbeatSender;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
sentinelProperties = mock(SentinelProperties.class);
|
||||||
|
sentinelHealthIndicator = new SentinelHealthIndicator(sentinelProperties);
|
||||||
|
|
||||||
|
SentinelConfig.setConfig(TransportConfig.CONSOLE_SERVER, "");
|
||||||
|
|
||||||
|
heartbeatSender = mock(HeartbeatSender.class);
|
||||||
|
Field heartbeatSenderField = ReflectionUtils.findField(HeartbeatSenderProvider.class, "heartbeatSender");
|
||||||
|
heartbeatSenderField.setAccessible(true);
|
||||||
|
ReflectionUtils.setField(heartbeatSenderField, null, heartbeatSender);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSentinelNotEnabled() {
|
||||||
|
when(sentinelProperties.isEnabled()).thenReturn(false);
|
||||||
|
|
||||||
|
Health health = sentinelHealthIndicator.health();
|
||||||
|
|
||||||
|
assertThat(health.getStatus()).isEqualTo(Status.UP);
|
||||||
|
assertThat(health.getDetails().get("enabled")).isEqualTo(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSentinelDashboardNotConfigured() {
|
||||||
|
when(sentinelProperties.isEnabled()).thenReturn(true);
|
||||||
|
|
||||||
|
Health health = sentinelHealthIndicator.health();
|
||||||
|
|
||||||
|
assertThat(health.getStatus()).isEqualTo(Status.UP);
|
||||||
|
assertThat(health.getDetails().get("dashboard")).isEqualTo(Status.UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSentinelDashboardConfiguredCheckSuccess() throws Exception {
|
||||||
|
when(sentinelProperties.isEnabled()).thenReturn(true);
|
||||||
|
SentinelConfig.setConfig(TransportConfig.CONSOLE_SERVER, "localhost:8080");
|
||||||
|
when(heartbeatSender.sendHeartbeat()).thenReturn(true);
|
||||||
|
|
||||||
|
|
||||||
|
Health health = sentinelHealthIndicator.health();
|
||||||
|
|
||||||
|
assertThat(health.getStatus()).isEqualTo(Status.UP);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSentinelDashboardConfiguredCheckFailed() throws Exception {
|
||||||
|
when(sentinelProperties.isEnabled()).thenReturn(true);
|
||||||
|
SentinelConfig.setConfig(TransportConfig.CONSOLE_SERVER, "localhost:8080");
|
||||||
|
when(heartbeatSender.sendHeartbeat()).thenReturn(false);
|
||||||
|
|
||||||
|
|
||||||
|
Health health = sentinelHealthIndicator.health();
|
||||||
|
|
||||||
|
assertThat(health.getStatus()).isEqualTo(Status.DOWN);
|
||||||
|
assertThat(health.getDetails().get("dashboard")).isEqualTo(new Status(Status.DOWN.getCode(), "localhost:8080 can't be connected"));
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user