mirror of
https://gitee.com/mirrors/Spring-Cloud-Alibaba.git
synced 2021-06-26 13:25:11 +08:00
Polish alibaba/spring-cloud-alibaba/#1283 : Renaming spring-cloud-starter-alibaba to be spring-cloud-alibaba-starters
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.sentinel;
|
||||
|
||||
import com.alibaba.cloud.sentinel.feign.SentinelFeignAutoConfiguration;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Add this unit test to verify https://github.com/alibaba/spring-cloud-alibaba/pull/838.
|
||||
*
|
||||
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = { ContextIdSentinelFeignTests.TestConfig.class },
|
||||
properties = { "feign.sentinel.enabled=true" })
|
||||
public class ContextIdSentinelFeignTests {
|
||||
|
||||
@Autowired
|
||||
private EchoService echoService;
|
||||
|
||||
@Autowired
|
||||
private FooService fooService;
|
||||
|
||||
@Test
|
||||
public void testFeignClient() {
|
||||
assertThat(echoService.echo("test")).isEqualTo("echo fallback");
|
||||
assertThat(fooService.echo("test")).isEqualTo("foo fallback");
|
||||
assertThat(fooService.toString()).isNotEqualTo(echoService.toString());
|
||||
assertThat(fooService.hashCode()).isNotEqualTo(echoService.hashCode());
|
||||
assertThat(echoService.equals(fooService)).isEqualTo(Boolean.FALSE);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@ImportAutoConfiguration({ SentinelFeignAutoConfiguration.class })
|
||||
@EnableFeignClients
|
||||
public static class TestConfig {
|
||||
|
||||
}
|
||||
|
||||
@FeignClient(contextId = "echoService", name = "service-provider",
|
||||
fallback = EchoServiceFallback.class,
|
||||
configuration = FeignConfiguration.class)
|
||||
public interface EchoService {
|
||||
|
||||
@GetMapping("/echo/{str}")
|
||||
String echo(@PathVariable("str") String str);
|
||||
|
||||
}
|
||||
|
||||
@FeignClient(contextId = "fooService", value = "foo-service",
|
||||
fallbackFactory = CustomFallbackFactory.class,
|
||||
configuration = FeignConfiguration.class)
|
||||
public interface FooService {
|
||||
|
||||
@RequestMapping(path = "echo/{str}")
|
||||
String echo(@RequestParam("str") String param);
|
||||
|
||||
}
|
||||
|
||||
public static class FeignConfiguration {
|
||||
|
||||
@Bean
|
||||
public EchoServiceFallback echoServiceFallback() {
|
||||
return new EchoServiceFallback();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CustomFallbackFactory customFallbackFactory() {
|
||||
return new CustomFallbackFactory();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class EchoServiceFallback implements EchoService {
|
||||
|
||||
@Override
|
||||
public String echo(@RequestParam("str") String param) {
|
||||
return "echo fallback";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class FooServiceFallback implements FooService {
|
||||
|
||||
@Override
|
||||
public String echo(@RequestParam("str") String param) {
|
||||
return "foo fallback";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class CustomFallbackFactory
|
||||
implements feign.hystrix.FallbackFactory<FooService> {
|
||||
|
||||
private FooService fooService = new FooServiceFallback();
|
||||
|
||||
@Override
|
||||
public FooService create(Throwable throwable) {
|
||||
return fooService;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.sentinel;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;
|
||||
import com.alibaba.cloud.sentinel.custom.SentinelAutoConfiguration;
|
||||
import com.alibaba.cloud.sentinel.custom.SentinelBeanPostProcessor;
|
||||
import com.alibaba.cloud.sentinel.endpoint.SentinelEndpoint;
|
||||
import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;
|
||||
import com.alibaba.csp.sentinel.config.SentinelConfig;
|
||||
import com.alibaba.csp.sentinel.log.LogBase;
|
||||
import com.alibaba.csp.sentinel.slots.block.BlockException;
|
||||
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
|
||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
|
||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
|
||||
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static com.alibaba.cloud.sentinel.SentinelConstants.BLOCK_PAGE_URL_CONF_KEY;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
||||
* @author jiashuai.xie
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = { SentinelAutoConfigurationTests.TestConfig.class },
|
||||
properties = { "spring.cloud.sentinel.filter.order=123",
|
||||
"spring.cloud.sentinel.filter.urlPatterns=/*,/test",
|
||||
"spring.cloud.sentinel.metric.fileSingleSize=9999",
|
||||
"spring.cloud.sentinel.metric.fileTotalCount=100",
|
||||
"spring.cloud.sentinel.blockPage=/error",
|
||||
"spring.cloud.sentinel.flow.coldFactor=3",
|
||||
"spring.cloud.sentinel.eager=true",
|
||||
"spring.cloud.sentinel.log.switchPid=true",
|
||||
"spring.cloud.sentinel.transport.dashboard=http://localhost:8080",
|
||||
"spring.cloud.sentinel.transport.port=9999",
|
||||
"spring.cloud.sentinel.transport.clientIp=1.1.1.1",
|
||||
"spring.cloud.sentinel.transport.heartbeatIntervalMs=20000" },
|
||||
webEnvironment = RANDOM_PORT)
|
||||
public class SentinelAutoConfigurationTests {
|
||||
|
||||
@Autowired
|
||||
private SentinelProperties sentinelProperties;
|
||||
|
||||
@Autowired
|
||||
private SentinelBeanPostProcessor sentinelBeanPostProcessor;
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplateWithBlockClass;
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplateWithoutBlockClass;
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplateWithFallbackClass;
|
||||
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
|
||||
private String flowUrl = "http://localhost:" + port + "/flow";
|
||||
|
||||
private String degradeUrl = "http://localhost:" + port + "/degrade";
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
FlowRule rule = new FlowRule();
|
||||
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
|
||||
rule.setCount(0);
|
||||
rule.setResource("GET:" + flowUrl);
|
||||
rule.setLimitApp("default");
|
||||
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
|
||||
rule.setStrategy(RuleConstant.STRATEGY_DIRECT);
|
||||
FlowRuleManager.loadRules(Arrays.asList(rule));
|
||||
|
||||
DegradeRule degradeRule = new DegradeRule();
|
||||
degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
|
||||
degradeRule.setResource("GET:" + degradeUrl);
|
||||
degradeRule.setCount(0);
|
||||
degradeRule.setTimeWindow(60);
|
||||
DegradeRuleManager.loadRules(Arrays.asList(degradeRule));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
assertThat(sentinelBeanPostProcessor).isNotNull();
|
||||
|
||||
checkSentinelLog();
|
||||
checkSentinelEager();
|
||||
checkSentinelTransport();
|
||||
checkSentinelColdFactor();
|
||||
checkSentinelMetric();
|
||||
checkSentinelFilter();
|
||||
checkEndpoint();
|
||||
}
|
||||
|
||||
private void checkEndpoint() {
|
||||
SentinelEndpoint sentinelEndpoint = new SentinelEndpoint(sentinelProperties);
|
||||
Map<String, Object> map = sentinelEndpoint.invoke();
|
||||
|
||||
assertThat(map.get("logUsePid")).isEqualTo(Boolean.TRUE);
|
||||
assertThat(map.get("consoleServer")).isEqualTo("http://localhost:8080");
|
||||
assertThat(map.get("clientPort")).isEqualTo("9999");
|
||||
assertThat(map.get("heartbeatIntervalMs")).isEqualTo(20000L);
|
||||
assertThat(map.get("clientIp")).isEqualTo("1.1.1.1");
|
||||
assertThat(map.get("metricsFileSize")).isEqualTo(9999L);
|
||||
assertThat(map.get("totalMetricsFileCount")).isEqualTo(100);
|
||||
assertThat(map.get("metricsFileCharset")).isEqualTo("UTF-8");
|
||||
assertThat(map.get("blockPage")).isEqualTo("/error");
|
||||
}
|
||||
|
||||
private void checkSentinelFilter() {
|
||||
assertThat(sentinelProperties.getFilter().getOrder()).isEqualTo(123);
|
||||
assertThat(sentinelProperties.getFilter().getUrlPatterns().size()).isEqualTo(2);
|
||||
assertThat(sentinelProperties.getFilter().getUrlPatterns().get(0))
|
||||
.isEqualTo("/*");
|
||||
assertThat(sentinelProperties.getFilter().getUrlPatterns().get(1))
|
||||
.isEqualTo("/test");
|
||||
}
|
||||
|
||||
private void checkSentinelMetric() {
|
||||
assertThat(sentinelProperties.getMetric().getCharset()).isEqualTo("UTF-8");
|
||||
assertThat(sentinelProperties.getMetric().getFileSingleSize()).isEqualTo("9999");
|
||||
assertThat(sentinelProperties.getMetric().getFileTotalCount()).isEqualTo("100");
|
||||
}
|
||||
|
||||
private void checkSentinelColdFactor() {
|
||||
assertThat(sentinelProperties.getFlow().getColdFactor()).isEqualTo("3");
|
||||
}
|
||||
|
||||
private void checkSentinelTransport() {
|
||||
assertThat(sentinelProperties.getTransport().getPort()).isEqualTo("9999");
|
||||
assertThat(sentinelProperties.getTransport().getDashboard())
|
||||
.isEqualTo("http://localhost:8080");
|
||||
assertThat(sentinelProperties.getTransport().getClientIp()).isEqualTo("1.1.1.1");
|
||||
assertThat(sentinelProperties.getTransport().getHeartbeatIntervalMs())
|
||||
.isEqualTo("20000");
|
||||
}
|
||||
|
||||
private void checkSentinelEager() {
|
||||
assertThat(sentinelProperties.isEager()).isEqualTo(true);
|
||||
}
|
||||
|
||||
private void checkSentinelLog() {
|
||||
assertThat(sentinelProperties.getLog().isSwitchPid()).isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSentinelSystemProperties() {
|
||||
assertThat(LogBase.isLogNameUsePid()).isEqualTo(true);
|
||||
assertThat(TransportConfig.getConsoleServer()).isEqualTo("http://localhost:8080");
|
||||
assertThat(TransportConfig.getPort()).isEqualTo("9999");
|
||||
assertThat(TransportConfig.getHeartbeatIntervalMs().longValue())
|
||||
.isEqualTo(20000L);
|
||||
assertThat(TransportConfig.getHeartbeatClientIp()).isEqualTo("1.1.1.1");
|
||||
assertThat(SentinelConfig.singleMetricFileSize()).isEqualTo(9999);
|
||||
assertThat(SentinelConfig.totalMetricFileCount()).isEqualTo(100);
|
||||
assertThat(SentinelConfig.charset()).isEqualTo("UTF-8");
|
||||
assertThat(SentinelConfig.getConfig(BLOCK_PAGE_URL_CONF_KEY)).isEqualTo("/error");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFlowRestTemplate() {
|
||||
|
||||
assertThat(restTemplate.getInterceptors().size()).isEqualTo(2);
|
||||
assertThat(restTemplateWithBlockClass.getInterceptors().size()).isEqualTo(1);
|
||||
|
||||
ResponseEntity responseEntityBlock = restTemplateWithBlockClass
|
||||
.getForEntity(flowUrl, String.class);
|
||||
|
||||
assertThat(responseEntityBlock.getBody()).isEqualTo("Oops");
|
||||
assertThat(responseEntityBlock.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
ResponseEntity responseEntityRaw = restTemplate.getForEntity(flowUrl,
|
||||
String.class);
|
||||
|
||||
assertThat(responseEntityRaw.getBody())
|
||||
.isEqualTo("RestTemplate request block by sentinel");
|
||||
assertThat(responseEntityRaw.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalRestTemplate() {
|
||||
assertThat(restTemplateWithoutBlockClass.getInterceptors().size()).isEqualTo(0);
|
||||
|
||||
assertThatThrownBy(() -> {
|
||||
restTemplateWithoutBlockClass.getForEntity(flowUrl, String.class);
|
||||
}).isInstanceOf(RestClientException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFallbackRestTemplate() {
|
||||
ResponseEntity responseEntity = restTemplateWithFallbackClass
|
||||
.getForEntity(degradeUrl, String.class);
|
||||
|
||||
assertThat(responseEntity.getBody()).isEqualTo("Oops fallback");
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class SentinelTestConfiguration {
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate
|
||||
RestTemplate restTemplate() {
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
restTemplate.getInterceptors().add(mock(ClientHttpRequestInterceptor.class));
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate(blockHandlerClass = ExceptionUtil.class,
|
||||
blockHandler = "handleException")
|
||||
RestTemplate restTemplateWithBlockClass() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate(fallbackClass = ExceptionUtil.class,
|
||||
fallback = "fallbackException")
|
||||
RestTemplate restTemplateWithFallbackClass() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
@Bean
|
||||
RestTemplate restTemplateWithoutBlockClass() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ExceptionUtil {
|
||||
|
||||
public static SentinelClientHttpResponse handleException(HttpRequest request,
|
||||
byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
|
||||
System.out.println("Oops: " + ex.getClass().getCanonicalName());
|
||||
return new SentinelClientHttpResponse("Oops");
|
||||
}
|
||||
|
||||
public static SentinelClientHttpResponse fallbackException(HttpRequest request,
|
||||
byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
|
||||
System.out.println("Oops: " + ex.getClass().getCanonicalName());
|
||||
return new SentinelClientHttpResponse("Oops fallback");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@ImportAutoConfiguration({ SentinelAutoConfiguration.class,
|
||||
SentinelWebAutoConfiguration.class, SentinelTestConfiguration.class })
|
||||
public static class TestConfig {
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.sentinel;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.alibaba.cloud.sentinel.custom.SentinelAutoConfiguration;
|
||||
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
|
||||
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.DefaultBlockExceptionHandler;
|
||||
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
|
||||
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.UrlCleaner;
|
||||
import com.alibaba.csp.sentinel.adapter.spring.webmvc.config.SentinelWebMvcConfig;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = { SentinelBeanAutowiredTests.TestConfig.class },
|
||||
properties = { "spring.cloud.sentinel.filter.order=111" })
|
||||
public class SentinelBeanAutowiredTests {
|
||||
|
||||
@Autowired
|
||||
private UrlCleaner urlCleaner;
|
||||
|
||||
@Autowired
|
||||
private BlockExceptionHandler blockExceptionHandler;
|
||||
|
||||
@Autowired
|
||||
private RequestOriginParser requestOriginParser;
|
||||
|
||||
@Autowired
|
||||
private SentinelProperties sentinelProperties;
|
||||
|
||||
@Autowired
|
||||
private SentinelWebMvcConfig sentinelWebMvcConfig;
|
||||
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
assertThat(urlCleaner).isNotNull();
|
||||
assertThat(blockExceptionHandler).isNotNull();
|
||||
assertThat(requestOriginParser).isNotNull();
|
||||
assertThat(sentinelProperties).isNotNull();
|
||||
|
||||
checkUrlPattern();
|
||||
}
|
||||
|
||||
private void checkUrlPattern() {
|
||||
assertThat(sentinelProperties.getFilter().getOrder()).isEqualTo(111);
|
||||
assertThat(sentinelProperties.getFilter().getUrlPatterns().size()).isEqualTo(1);
|
||||
assertThat(sentinelProperties.getFilter().getUrlPatterns().get(0))
|
||||
.isEqualTo("/**");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBeanAutowired() {
|
||||
assertThat(sentinelWebMvcConfig.getUrlCleaner()).isEqualTo(urlCleaner);
|
||||
assertThat(sentinelWebMvcConfig.getBlockExceptionHandler())
|
||||
.isEqualTo(blockExceptionHandler);
|
||||
assertThat(sentinelWebMvcConfig.getOriginParser()).isEqualTo(requestOriginParser);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@ImportAutoConfiguration({ SentinelAutoConfiguration.class,
|
||||
SentinelWebAutoConfiguration.class })
|
||||
public static class TestConfig {
|
||||
|
||||
@Bean
|
||||
public UrlCleaner urlCleaner() {
|
||||
return new UrlCleaner() {
|
||||
@Override
|
||||
public String clean(String s) {
|
||||
return s;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RequestOriginParser requestOriginParser() {
|
||||
return new RequestOriginParser() {
|
||||
@Override
|
||||
public String parseOrigin(HttpServletRequest httpServletRequest) {
|
||||
return httpServletRequest.getRemoteAddr();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BlockExceptionHandler blockExceptionHandler() {
|
||||
return new DefaultBlockExceptionHandler();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.sentinel;
|
||||
|
||||
import com.alibaba.cloud.sentinel.custom.SentinelAutoConfiguration;
|
||||
import com.alibaba.cloud.sentinel.datasource.RuleType;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = { SentinelDataSourceTests.TestConfig.class }, properties = {
|
||||
"spring.cloud.sentinel.datasource.ds1.file.file=classpath: flowrule.json",
|
||||
"spring.cloud.sentinel.datasource.ds1.file.data-type=json",
|
||||
"spring.cloud.sentinel.datasource.ds1.file.rule-type=flow",
|
||||
|
||||
"spring.cloud.sentinel.datasource.ds2.file.file=classpath: degraderule.json",
|
||||
"spring.cloud.sentinel.datasource.ds2.file.data-type=json",
|
||||
"spring.cloud.sentinel.datasource.ds2.file.rule-type=degrade",
|
||||
|
||||
"spring.cloud.sentinel.datasource.ds3.file.file=classpath: authority.json",
|
||||
"spring.cloud.sentinel.datasource.ds3.file.rule-type=authority",
|
||||
|
||||
"spring.cloud.sentinel.datasource.ds4.file.file=classpath: system.json",
|
||||
"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.data-type=custom",
|
||||
"spring.cloud.sentinel.datasource.ds5.file.converter-class=TestConverter",
|
||||
"spring.cloud.sentinel.datasource.ds5.file.rule-type=param-flow" })
|
||||
public class SentinelDataSourceTests {
|
||||
|
||||
@Autowired
|
||||
private SentinelProperties sentinelProperties;
|
||||
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
assertThat(sentinelProperties).isNotNull();
|
||||
|
||||
checkUrlPattern();
|
||||
}
|
||||
|
||||
private void checkUrlPattern() {
|
||||
assertThat(sentinelProperties.getFilter().getOrder())
|
||||
.isEqualTo(Integer.MIN_VALUE);
|
||||
assertThat(sentinelProperties.getFilter().getUrlPatterns().size()).isEqualTo(1);
|
||||
assertThat(sentinelProperties.getFilter().getUrlPatterns().get(0))
|
||||
.isEqualTo("/**");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDataSource() {
|
||||
assertThat(sentinelProperties.getDatasource().size()).isEqualTo(5);
|
||||
assertThat(sentinelProperties.getDatasource().get("ds1").getApollo()).isNull();
|
||||
assertThat(sentinelProperties.getDatasource().get("ds1").getNacos()).isNull();
|
||||
assertThat(sentinelProperties.getDatasource().get("ds1").getZk()).isNull();
|
||||
assertThat(sentinelProperties.getDatasource().get("ds1").getFile()).isNotNull();
|
||||
|
||||
assertThat(sentinelProperties.getDatasource().get("ds1").getFile().getDataType())
|
||||
.isEqualTo("json");
|
||||
assertThat(sentinelProperties.getDatasource().get("ds1").getFile().getRuleType())
|
||||
.isEqualTo(RuleType.FLOW);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@ImportAutoConfiguration({ SentinelAutoConfiguration.class,
|
||||
SentinelWebAutoConfiguration.class })
|
||||
public static class TestConfig {
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.sentinel;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.alibaba.cloud.sentinel.feign.SentinelFeignAutoConfiguration;
|
||||
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = { SentinelFeignTests.TestConfig.class },
|
||||
properties = { "feign.sentinel.enabled=true" })
|
||||
public class SentinelFeignTests {
|
||||
|
||||
@Autowired
|
||||
private EchoService echoService;
|
||||
|
||||
@Autowired
|
||||
private FooService fooService;
|
||||
|
||||
@Autowired
|
||||
private BarService barService;
|
||||
|
||||
@Autowired
|
||||
private BazService bazService;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
FlowRule rule1 = new FlowRule();
|
||||
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
|
||||
rule1.setCount(0);
|
||||
rule1.setResource("GET:http://test-service/echo/{str}");
|
||||
rule1.setLimitApp("default");
|
||||
rule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
|
||||
rule1.setStrategy(RuleConstant.STRATEGY_DIRECT);
|
||||
FlowRule rule2 = new FlowRule();
|
||||
rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
|
||||
rule2.setCount(0);
|
||||
rule2.setResource("GET:http://foo-service/echo/{str}");
|
||||
rule2.setLimitApp("default");
|
||||
rule2.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
|
||||
rule2.setStrategy(RuleConstant.STRATEGY_DIRECT);
|
||||
FlowRule rule3 = new FlowRule();
|
||||
rule3.setGrade(RuleConstant.FLOW_GRADE_QPS);
|
||||
rule3.setCount(0);
|
||||
rule3.setResource("GET:http://bar-service/bar");
|
||||
rule3.setLimitApp("default");
|
||||
rule3.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
|
||||
rule3.setStrategy(RuleConstant.STRATEGY_DIRECT);
|
||||
FlowRule rule4 = new FlowRule();
|
||||
rule4.setGrade(RuleConstant.FLOW_GRADE_QPS);
|
||||
rule4.setCount(0);
|
||||
rule4.setResource("GET:http://baz-service/baz");
|
||||
rule4.setLimitApp("default");
|
||||
rule4.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
|
||||
rule4.setStrategy(RuleConstant.STRATEGY_DIRECT);
|
||||
FlowRuleManager.loadRules(Arrays.asList(rule1, rule2, rule3, rule4));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextLoads() throws Exception {
|
||||
assertThat(echoService).isNotNull();
|
||||
assertThat(fooService).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFeignClient() {
|
||||
assertThat(echoService.echo("test")).isEqualTo("echo fallback");
|
||||
assertThat(fooService.echo("test")).isEqualTo("foo fallback");
|
||||
|
||||
assertThatThrownBy(() -> {
|
||||
barService.bar();
|
||||
}).isInstanceOf(Exception.class);
|
||||
|
||||
assertThatThrownBy(() -> {
|
||||
bazService.baz();
|
||||
}).isInstanceOf(Exception.class);
|
||||
|
||||
assertThat(fooService.toString()).isNotEqualTo(echoService.toString());
|
||||
assertThat(fooService.hashCode()).isNotEqualTo(echoService.hashCode());
|
||||
assertThat(echoService.equals(fooService)).isEqualTo(Boolean.FALSE);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@ImportAutoConfiguration({ SentinelFeignAutoConfiguration.class })
|
||||
@EnableFeignClients
|
||||
public static class TestConfig {
|
||||
|
||||
@Bean
|
||||
public EchoServiceFallback echoServiceFallback() {
|
||||
return new EchoServiceFallback();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CustomFallbackFactory customFallbackFactory() {
|
||||
return new CustomFallbackFactory();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@FeignClient(value = "test-service", fallback = EchoServiceFallback.class)
|
||||
public interface EchoService {
|
||||
|
||||
@RequestMapping(path = "echo/{str}")
|
||||
String echo(@RequestParam("str") String param);
|
||||
|
||||
}
|
||||
|
||||
@FeignClient(value = "foo-service", fallbackFactory = CustomFallbackFactory.class)
|
||||
public interface FooService {
|
||||
|
||||
@RequestMapping(path = "echo/{str}")
|
||||
String echo(@RequestParam("str") String param);
|
||||
|
||||
}
|
||||
|
||||
@FeignClient("bar-service")
|
||||
public interface BarService {
|
||||
|
||||
@RequestMapping(path = "bar")
|
||||
String bar();
|
||||
|
||||
}
|
||||
|
||||
public interface BazService {
|
||||
|
||||
@RequestMapping(path = "baz")
|
||||
String baz();
|
||||
|
||||
}
|
||||
|
||||
@FeignClient("baz-service")
|
||||
public interface BazClient extends BazService {
|
||||
|
||||
}
|
||||
|
||||
public static class EchoServiceFallback implements EchoService {
|
||||
|
||||
@Override
|
||||
public String echo(@RequestParam("str") String param) {
|
||||
return "echo fallback";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class FooServiceFallback implements FooService {
|
||||
|
||||
@Override
|
||||
public String echo(@RequestParam("str") String param) {
|
||||
return "foo fallback";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class CustomFallbackFactory
|
||||
implements feign.hystrix.FallbackFactory<FooService> {
|
||||
|
||||
private FooService fooService = new FooServiceFallback();
|
||||
|
||||
@Override
|
||||
public FooService create(Throwable throwable) {
|
||||
return fooService;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,412 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.sentinel;
|
||||
|
||||
import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;
|
||||
import com.alibaba.cloud.sentinel.custom.SentinelBeanPostProcessor;
|
||||
import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;
|
||||
import com.alibaba.csp.sentinel.slots.block.BlockException;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
||||
*/
|
||||
public class SentinelRestTemplateTests {
|
||||
|
||||
@Test(expected = BeanCreationException.class)
|
||||
public void testFbkMethod() {
|
||||
new AnnotationConfigApplicationContext(TestConfig1.class);
|
||||
}
|
||||
|
||||
@Test(expected = BeanCreationException.class)
|
||||
public void testFbkClass() {
|
||||
new AnnotationConfigApplicationContext(TestConfig2.class);
|
||||
}
|
||||
|
||||
@Test(expected = BeanCreationException.class)
|
||||
public void testblkMethod() {
|
||||
new AnnotationConfigApplicationContext(TestConfig3.class);
|
||||
}
|
||||
|
||||
@Test(expected = BeanCreationException.class)
|
||||
public void testblkClass() {
|
||||
new AnnotationConfigApplicationContext(TestConfig4.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormal() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
TestConfig5.class);
|
||||
assertThat(context.getBeansOfType(RestTemplate.class).size()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test(expected = BeanCreationException.class)
|
||||
public void testBlkMethodExists() {
|
||||
new AnnotationConfigApplicationContext(TestConfig6.class);
|
||||
}
|
||||
|
||||
@Test(expected = BeanCreationException.class)
|
||||
public void testFbkMethodExists() {
|
||||
new AnnotationConfigApplicationContext(TestConfig7.class);
|
||||
}
|
||||
|
||||
@Test(expected = BeanCreationException.class)
|
||||
public void testBlkReturnValue() {
|
||||
new AnnotationConfigApplicationContext(TestConfig8.class);
|
||||
}
|
||||
|
||||
@Test(expected = BeanCreationException.class)
|
||||
public void testFbkReturnValue() {
|
||||
new AnnotationConfigApplicationContext(TestConfig9.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalWithoutParam() {
|
||||
new AnnotationConfigApplicationContext(TestConfig10.class);
|
||||
}
|
||||
|
||||
@Test(expected = BeanCreationException.class)
|
||||
public void testUrlClnMethod() {
|
||||
new AnnotationConfigApplicationContext(TestConfig11.class);
|
||||
}
|
||||
|
||||
@Test(expected = BeanCreationException.class)
|
||||
public void testUrlClnClass() {
|
||||
new AnnotationConfigApplicationContext(TestConfig12.class);
|
||||
}
|
||||
|
||||
@Test(expected = BeanCreationException.class)
|
||||
public void testUrlClnMethodExists() {
|
||||
new AnnotationConfigApplicationContext(TestConfig13.class);
|
||||
}
|
||||
|
||||
@Test(expected = BeanCreationException.class)
|
||||
public void testUrlClnReturnValue() {
|
||||
new AnnotationConfigApplicationContext(TestConfig14.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class TestConfig1 {
|
||||
|
||||
@Bean
|
||||
SentinelBeanPostProcessor sentinelBeanPostProcessor(
|
||||
ApplicationContext applicationContext) {
|
||||
return new SentinelBeanPostProcessor(applicationContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate(fallback = "fbk")
|
||||
RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class TestConfig2 {
|
||||
|
||||
@Bean
|
||||
SentinelBeanPostProcessor sentinelBeanPostProcessor(
|
||||
ApplicationContext applicationContext) {
|
||||
return new SentinelBeanPostProcessor(applicationContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate(fallbackClass = ExceptionUtil.class)
|
||||
RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class TestConfig3 {
|
||||
|
||||
@Bean
|
||||
SentinelBeanPostProcessor sentinelBeanPostProcessor(
|
||||
ApplicationContext applicationContext) {
|
||||
return new SentinelBeanPostProcessor(applicationContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate(blockHandler = "blk")
|
||||
RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class TestConfig4 {
|
||||
|
||||
@Bean
|
||||
SentinelBeanPostProcessor sentinelBeanPostProcessor(
|
||||
ApplicationContext applicationContext) {
|
||||
return new SentinelBeanPostProcessor(applicationContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate(blockHandlerClass = ExceptionUtil.class)
|
||||
RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class TestConfig5 {
|
||||
|
||||
@Bean
|
||||
SentinelBeanPostProcessor sentinelBeanPostProcessor(
|
||||
ApplicationContext applicationContext) {
|
||||
return new SentinelBeanPostProcessor(applicationContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate(
|
||||
blockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class,
|
||||
blockHandler = "handleException",
|
||||
fallbackClass = SentinelRestTemplateTests.ExceptionUtil.class,
|
||||
fallback = "fallbackException",
|
||||
urlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class,
|
||||
urlCleaner = "clean")
|
||||
RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class TestConfig6 {
|
||||
|
||||
@Bean
|
||||
SentinelBeanPostProcessor sentinelBeanPostProcessor(
|
||||
ApplicationContext applicationContext) {
|
||||
return new SentinelBeanPostProcessor(applicationContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate(
|
||||
blockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class,
|
||||
blockHandler = "handleException1")
|
||||
RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class TestConfig7 {
|
||||
|
||||
@Bean
|
||||
SentinelBeanPostProcessor sentinelBeanPostProcessor(
|
||||
ApplicationContext applicationContext) {
|
||||
return new SentinelBeanPostProcessor(applicationContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate(
|
||||
fallbackClass = SentinelRestTemplateTests.ExceptionUtil.class,
|
||||
fallback = "fallbackException1")
|
||||
RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class TestConfig8 {
|
||||
|
||||
@Bean
|
||||
SentinelBeanPostProcessor sentinelBeanPostProcessor(
|
||||
ApplicationContext applicationContext) {
|
||||
return new SentinelBeanPostProcessor(applicationContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate(
|
||||
blockHandlerClass = SentinelRestTemplateTests.ExceptionUtil.class,
|
||||
blockHandler = "handleException2")
|
||||
RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class TestConfig9 {
|
||||
|
||||
@Bean
|
||||
SentinelBeanPostProcessor sentinelBeanPostProcessor(
|
||||
ApplicationContext applicationContext) {
|
||||
return new SentinelBeanPostProcessor(applicationContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate(
|
||||
fallbackClass = SentinelRestTemplateTests.ExceptionUtil.class,
|
||||
fallback = "fallbackException2")
|
||||
RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class TestConfig10 {
|
||||
|
||||
@Bean
|
||||
SentinelBeanPostProcessor sentinelBeanPostProcessor(
|
||||
ApplicationContext applicationContext) {
|
||||
return new SentinelBeanPostProcessor(applicationContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate
|
||||
RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate
|
||||
RestTemplate restTemplate2() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class TestConfig11 {
|
||||
|
||||
@Bean
|
||||
SentinelBeanPostProcessor sentinelBeanPostProcessor(
|
||||
ApplicationContext applicationContext) {
|
||||
return new SentinelBeanPostProcessor(applicationContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate(urlCleaner = "cln")
|
||||
RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class TestConfig12 {
|
||||
|
||||
@Bean
|
||||
SentinelBeanPostProcessor sentinelBeanPostProcessor(
|
||||
ApplicationContext applicationContext) {
|
||||
return new SentinelBeanPostProcessor(applicationContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate(urlCleanerClass = UrlCleanUtil.class)
|
||||
RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class TestConfig13 {
|
||||
|
||||
@Bean
|
||||
SentinelBeanPostProcessor sentinelBeanPostProcessor(
|
||||
ApplicationContext applicationContext) {
|
||||
return new SentinelBeanPostProcessor(applicationContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate(
|
||||
urlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class,
|
||||
urlCleaner = "clean1")
|
||||
RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class TestConfig14 {
|
||||
|
||||
@Bean
|
||||
SentinelBeanPostProcessor sentinelBeanPostProcessor(
|
||||
ApplicationContext applicationContext) {
|
||||
return new SentinelBeanPostProcessor(applicationContext);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SentinelRestTemplate(
|
||||
urlCleanerClass = SentinelRestTemplateTests.UrlCleanUtil.class,
|
||||
urlCleaner = "clean2")
|
||||
RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ExceptionUtil {
|
||||
|
||||
public static SentinelClientHttpResponse handleException(HttpRequest request,
|
||||
byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
|
||||
System.out.println("Oops: " + ex.getClass().getCanonicalName());
|
||||
return new SentinelClientHttpResponse("Oops");
|
||||
}
|
||||
|
||||
public static void handleException2(HttpRequest request, byte[] body,
|
||||
ClientHttpRequestExecution execution, BlockException ex) {
|
||||
System.out.println("Oops: " + ex.getClass().getCanonicalName());
|
||||
}
|
||||
|
||||
public static SentinelClientHttpResponse fallbackException(HttpRequest request,
|
||||
byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
|
||||
System.out.println("Oops: " + ex.getClass().getCanonicalName());
|
||||
return new SentinelClientHttpResponse("Oops fallback");
|
||||
}
|
||||
|
||||
public static void fallbackException2(HttpRequest request, byte[] body,
|
||||
ClientHttpRequestExecution execution, BlockException ex) {
|
||||
System.out.println("Oops: " + ex.getClass().getCanonicalName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class UrlCleanUtil {
|
||||
|
||||
public static String clean(String url) {
|
||||
return url;
|
||||
}
|
||||
|
||||
public static void clean2(String url) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.sentinel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.csp.sentinel.datasource.Converter;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:fangjian0423@gmail.com">Jim</a>
|
||||
*/
|
||||
public class TestConverter implements Converter<String, List<ParamFlowRule>> {
|
||||
|
||||
private ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Override
|
||||
public List<ParamFlowRule> convert(String s) {
|
||||
try {
|
||||
return objectMapper.readValue(s, new TypeReference<List<ParamFlowRule>>() {
|
||||
});
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.sentinel.endpoint;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.cloud.sentinel.SentinelProperties;
|
||||
import com.alibaba.csp.sentinel.config.SentinelConfig;
|
||||
import com.alibaba.csp.sentinel.datasource.AbstractDataSource;
|
||||
import com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource;
|
||||
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.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.boot.actuate.health.Health;
|
||||
import org.springframework.boot.actuate.health.Status;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
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 DefaultListableBeanFactory beanFactory;
|
||||
|
||||
private SentinelProperties sentinelProperties;
|
||||
|
||||
private HeartbeatSender heartbeatSender;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
beanFactory = mock(DefaultListableBeanFactory.class);
|
||||
sentinelProperties = mock(SentinelProperties.class);
|
||||
sentinelHealthIndicator = new SentinelHealthIndicator(beanFactory,
|
||||
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 testSentinelDashboardConfiguredSuccess() 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 testSentinelDashboardConfiguredFailed() 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"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSentinelDataSourceSuccess() throws Exception {
|
||||
when(sentinelProperties.isEnabled()).thenReturn(true);
|
||||
SentinelConfig.setConfig(TransportConfig.CONSOLE_SERVER, "localhost:8080");
|
||||
when(heartbeatSender.sendHeartbeat()).thenReturn(true);
|
||||
|
||||
Map<String, AbstractDataSource> dataSourceMap = new HashMap<>();
|
||||
|
||||
FileRefreshableDataSource fileDataSource1 = mock(FileRefreshableDataSource.class);
|
||||
dataSourceMap.put("ds1-sentinel-file-datasource", fileDataSource1);
|
||||
|
||||
FileRefreshableDataSource fileDataSource2 = mock(FileRefreshableDataSource.class);
|
||||
dataSourceMap.put("ds2-sentinel-file-datasource", fileDataSource2);
|
||||
|
||||
when(beanFactory.getBeansOfType(AbstractDataSource.class))
|
||||
.thenReturn(dataSourceMap);
|
||||
|
||||
Health health = sentinelHealthIndicator.health();
|
||||
|
||||
assertThat(health.getStatus()).isEqualTo(Status.UP);
|
||||
Map<String, Status> dataSourceDetailMap = (Map<String, Status>) health
|
||||
.getDetails().get("dataSource");
|
||||
assertThat(dataSourceDetailMap.get("ds1-sentinel-file-datasource"))
|
||||
.isEqualTo(Status.UP);
|
||||
assertThat(dataSourceDetailMap.get("ds2-sentinel-file-datasource"))
|
||||
.isEqualTo(Status.UP);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSentinelDataSourceFailed() throws Exception {
|
||||
when(sentinelProperties.isEnabled()).thenReturn(true);
|
||||
SentinelConfig.setConfig(TransportConfig.CONSOLE_SERVER, "localhost:8080");
|
||||
when(heartbeatSender.sendHeartbeat()).thenReturn(true);
|
||||
|
||||
Map<String, AbstractDataSource> dataSourceMap = new HashMap<>();
|
||||
|
||||
FileRefreshableDataSource fileDataSource1 = mock(FileRefreshableDataSource.class);
|
||||
dataSourceMap.put("ds1-sentinel-file-datasource", fileDataSource1);
|
||||
|
||||
FileRefreshableDataSource fileDataSource2 = mock(FileRefreshableDataSource.class);
|
||||
when(fileDataSource2.loadConfig())
|
||||
.thenThrow(new RuntimeException("fileDataSource2 error"));
|
||||
dataSourceMap.put("ds2-sentinel-file-datasource", fileDataSource2);
|
||||
|
||||
when(beanFactory.getBeansOfType(AbstractDataSource.class))
|
||||
.thenReturn(dataSourceMap);
|
||||
|
||||
Health health = sentinelHealthIndicator.health();
|
||||
|
||||
assertThat(health.getStatus()).isEqualTo(Status.DOWN);
|
||||
Map<String, Status> dataSourceDetailMap = (Map<String, Status>) health
|
||||
.getDetails().get("dataSource");
|
||||
assertThat(dataSourceDetailMap.get("ds1-sentinel-file-datasource"))
|
||||
.isEqualTo(Status.UP);
|
||||
assertThat(dataSourceDetailMap.get("ds2-sentinel-file-datasource"))
|
||||
.isEqualTo(new Status(Status.DOWN.getCode(), "fileDataSource2 error"));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
[
|
||||
{
|
||||
"resource": "good",
|
||||
"limitApp": "abc",
|
||||
"strategy": 0
|
||||
},
|
||||
{
|
||||
"resource": "bad",
|
||||
"limitApp": "bcd",
|
||||
"strategy": 1
|
||||
},
|
||||
{
|
||||
"resource": "terrible",
|
||||
"limitApp": "aaa",
|
||||
"strategy": 1
|
||||
}
|
||||
]
|
@@ -0,0 +1,16 @@
|
||||
[
|
||||
{
|
||||
"resource": "abc0",
|
||||
"count": 20.0,
|
||||
"grade": 0,
|
||||
"passCount": 0,
|
||||
"timeWindow": 10
|
||||
},
|
||||
{
|
||||
"resource": "abc1",
|
||||
"count": 15.0,
|
||||
"grade": 0,
|
||||
"passCount": 0,
|
||||
"timeWindow": 10
|
||||
}
|
||||
]
|
@@ -0,0 +1,26 @@
|
||||
[
|
||||
{
|
||||
"resource": "resource",
|
||||
"controlBehavior": 0,
|
||||
"count": 1,
|
||||
"grade": 1,
|
||||
"limitApp": "default",
|
||||
"strategy": 0
|
||||
},
|
||||
{
|
||||
"resource": "p",
|
||||
"controlBehavior": 0,
|
||||
"count": 1,
|
||||
"grade": 1,
|
||||
"limitApp": "default",
|
||||
"strategy": 0
|
||||
},
|
||||
{
|
||||
"resource": "http://www.taobao.com",
|
||||
"controlBehavior": 0,
|
||||
"count": 0,
|
||||
"grade": 1,
|
||||
"limitApp": "default",
|
||||
"strategy": 0
|
||||
}
|
||||
]
|
@@ -0,0 +1,16 @@
|
||||
[
|
||||
{
|
||||
"resource": "hotResource",
|
||||
"count": 0,
|
||||
"grade": 1,
|
||||
"limitApp": "default",
|
||||
"paramIdx": 0,
|
||||
"paramFlowItemList": [
|
||||
{
|
||||
"object": "2",
|
||||
"classType": "int",
|
||||
"count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@@ -0,0 +1,8 @@
|
||||
[
|
||||
{
|
||||
"highestSystemLoad": -1,
|
||||
"qps": 100,
|
||||
"avgRt": -1,
|
||||
"maxThread": 10
|
||||
}
|
||||
]
|
Reference in New Issue
Block a user