1
0
mirror of https://gitee.com/mirrors/Spring-Cloud-Alibaba.git synced 2021-06-26 13:25:11 +08:00

sync sentinel in 1.x branch

This commit is contained in:
fangjian0423 2019-03-26 17:30:39 +08:00
parent 01c1136a0d
commit dd765d3344
11 changed files with 157 additions and 19 deletions

View File

@ -260,6 +260,11 @@
<artifactId>spring-cloud-stream-binder-rocketmq</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dubbo</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Own dependencies - Starters -->
<dependency>
@ -328,6 +333,13 @@
<version>${project.version}</version>
</dependency>
<!-- Dubbo -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Testing Dependencies -->

View File

@ -0,0 +1,7 @@
#!/usr/bin/env bash
n=1
while [ $n -le 10 ]
do
echo `curl -s http://localhost:18083/test`
let n++
done

View File

@ -0,0 +1,7 @@
#!/usr/bin/env bash
n=1
while [ $n -le 10 ]
do
echo `curl -s http://localhost:18083/index`
let n++
done

View File

@ -0,0 +1,7 @@
#!/usr/bin/env bash
n=1
while [ $n -le 10 ]
do
echo `curl -s http://localhost:18083/sleep`
let n++
done

View File

@ -3,6 +3,7 @@ package org.springframework.cloud.alibaba.cloud.examples;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.alibaba.cloud.examples.ConsumerApplication.EchoService;
import org.springframework.cloud.alibaba.sentinel.annotation.SentinelRestTemplate;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
@ -28,6 +29,13 @@ public class ConsumerApplication {
return new RestTemplate();
}
@LoadBalanced
@Bean
@SentinelRestTemplate
public RestTemplate restTemplate1() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}

View File

@ -3,7 +3,11 @@ package org.springframework.cloud.alibaba.cloud.examples;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.alibaba.cloud.examples.ConsumerApplication.EchoService;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
@ -14,18 +18,54 @@ public class TestController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private RestTemplate restTemplate1;
@Autowired
private EchoService echoService;
@Autowired
private DiscoveryClient discoveryClient;
// @PostConstruct
// public void init() {
// restTemplate1.setErrorHandler(new ResponseErrorHandler() {
// @Override
// public boolean hasError(ClientHttpResponse response) throws IOException {
// return false;
// }
//
// @Override
// public void handleError(ClientHttpResponse response) throws IOException {
// System.err.println("handle error");
// }
// });
// }
@RequestMapping(value = "/echo-rest/{str}", method = RequestMethod.GET)
public String rest(@PathVariable String str) {
return restTemplate.getForObject("http://service-provider-1X/echo/" + str,
String.class);
}
@RequestMapping(value = "/index", method = RequestMethod.GET)
public String index() {
return restTemplate1.getForObject("http://service-provider-1X", String.class);
}
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String test() {
return restTemplate1.getForObject("http://service-provider-1X/test",
String.class);
}
@RequestMapping(value = "/sleep", method = RequestMethod.GET)
public String sleep() {
return restTemplate1.getForObject("http://service-provider-1X/sleep",
String.class);
}
@RequestMapping(value = "/notFound-feign", method = RequestMethod.GET)
public String notFound() {
return echoService.notFound();

View File

@ -5,5 +5,11 @@ spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
feign.sentinel.enabled=true
spring.cloud.sentinel.transport.dashboard=localhost:8080
spring.cloud.sentinel.eager=true
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.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

View File

@ -0,0 +1,20 @@
[
{
"resource": "GET:http://service-provider-1X/test",
"count": 0.5,
"grade": 1,
"timeWindow": 30
},
{
"resource": "GET:http://service-provider-1X",
"count": 0.5,
"grade": 1,
"timeWindow": 10
},
{
"resource": "GET:http://service-provider-1X/sleep",
"count": 20.0,
"grade": 0,
"timeWindow": 30
}
]

View File

@ -3,6 +3,8 @@ package org.springframework.cloud.alibaba.cloud.examples;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@ -22,6 +24,27 @@ public class ProviderApplication {
@RestController
class EchoController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public ResponseEntity index() {
return new ResponseEntity("index error", HttpStatus.INTERNAL_SERVER_ERROR);
}
@RequestMapping(value = "/test", method = RequestMethod.GET)
public ResponseEntity test() {
return new ResponseEntity("error", HttpStatus.INTERNAL_SERVER_ERROR);
}
@RequestMapping(value = "/sleep", method = RequestMethod.GET)
public String sleep() {
try {
Thread.sleep(1000L);
}
catch (InterruptedException e) {
e.printStackTrace();
}
return "ok";
}
@RequestMapping(value = "/echo/{string}", method = RequestMethod.GET)
public String echo(@PathVariable String string) {
return "hello Nacos Discovery " + string;

View File

@ -180,9 +180,9 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces
throws BeansException {
if (cache.containsKey(beanName)) {
// add interceptor for each RestTemplate with @SentinelRestTemplate annotation
StringBuilder interceptorBeanName = new StringBuilder();
StringBuilder interceptorBeanNamePrefix = new StringBuilder();
SentinelRestTemplate sentinelRestTemplate = cache.get(beanName);
interceptorBeanName
interceptorBeanNamePrefix
.append(StringUtils.uncapitalize(
SentinelProtectInterceptor.class.getSimpleName()))
.append("_")
@ -191,23 +191,25 @@ public class SentinelBeanPostProcessor implements MergedBeanDefinitionPostProces
.append(sentinelRestTemplate.fallbackClass().getSimpleName())
.append(sentinelRestTemplate.fallback());
RestTemplate restTemplate = (RestTemplate) bean;
registerBean(interceptorBeanName.toString(), sentinelRestTemplate);
String interceptorBeanName = interceptorBeanNamePrefix + "@"
+ bean.toString();
registerBean(interceptorBeanName, sentinelRestTemplate, (RestTemplate) bean);
SentinelProtectInterceptor sentinelProtectInterceptor = applicationContext
.getBean(interceptorBeanName.toString(),
SentinelProtectInterceptor.class);
.getBean(interceptorBeanName, SentinelProtectInterceptor.class);
restTemplate.getInterceptors().add(0, sentinelProtectInterceptor);
}
return bean;
}
private void registerBean(String interceptorBeanName,
SentinelRestTemplate sentinelRestTemplate) {
SentinelRestTemplate sentinelRestTemplate, RestTemplate restTemplate) {
// register SentinelProtectInterceptor bean
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext
.getAutowireCapableBeanFactory();
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
.genericBeanDefinition(SentinelProtectInterceptor.class);
beanDefinitionBuilder.addConstructorArgValue(sentinelRestTemplate);
beanDefinitionBuilder.addConstructorArgValue(restTemplate);
BeanDefinition interceptorBeanDefinition = beanDefinitionBuilder
.getRawBeanDefinition();
beanFactory.registerBeanDefinition(interceptorBeanName,

View File

@ -27,11 +27,12 @@ import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RestTemplate;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
@ -44,8 +45,12 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor
private final SentinelRestTemplate sentinelRestTemplate;
public SentinelProtectInterceptor(SentinelRestTemplate sentinelRestTemplate) {
private final RestTemplate restTemplate;
public SentinelProtectInterceptor(SentinelRestTemplate sentinelRestTemplate,
RestTemplate restTemplate) {
this.sentinelRestTemplate = sentinelRestTemplate;
this.restTemplate = restTemplate;
}
@Override
@ -61,32 +66,33 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor
entryWithPath = false;
}
Entry hostEntry = null, hostWithPathEntry = null;
ClientHttpResponse response;
ClientHttpResponse response = null;
try {
ContextUtil.enter(hostWithPathResource);
hostEntry = SphU.entry(hostResource, EntryType.OUT);
if (entryWithPath) {
hostWithPathEntry = SphU.entry(hostWithPathResource);
hostWithPathEntry = SphU.entry(hostWithPathResource, EntryType.OUT);
}
hostEntry = SphU.entry(hostResource);
response = execution.execute(request, body);
if (this.restTemplate.getErrorHandler().hasError(response)) {
Tracer.trace(
new IllegalStateException("RestTemplate ErrorHandler has error"));
}
}
catch (Throwable e) {
if (!BlockException.isBlockException(e)) {
Tracer.trace(e);
throw new IllegalStateException(e);
}
else {
return handleBlockException(request, body, execution, (BlockException) e);
}
}
finally {
if (hostEntry != null) {
hostEntry.exit();
}
if (hostWithPathEntry != null) {
hostWithPathEntry.exit();
}
ContextUtil.exit();
if (hostEntry != null) {
hostEntry.exit();
}
}
return response;
}