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

Merge pull request #2 from spring-cloud-incubator/master

同步一次master代码
This commit is contained in:
pbting 2018-12-19 15:55:06 +08:00 committed by GitHub
commit 2d842b6c98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 81 additions and 46 deletions

View File

@ -13,6 +13,7 @@ Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。
* **分布式配置管理**:支持分布式系统中的外部化配置,配置更改时自动刷新。
* **消息驱动能力**:基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。
* **阿里云对象存储**:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。
* **分布式任务调度**:提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Workerschedulerx-client上执行。
更多功能请参考 [Roadmap](https://github.com/spring-cloud-incubator/spring-cloud-alibaba/blob/master/Roadmap-zh.md)。
@ -29,6 +30,8 @@ Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。
**[Alibaba Cloud OSS](https://www.aliyun.com/product/oss)**: 阿里云对象存储服务Object Storage Service简称 OSS是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
**[Alibaba Cloud SchedulerX](https://help.aliyun.com/document_detail/43136.html?spm=a2c4g.11186623.6.709.baef7da9QVICiD)**: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。
更多组件请参考 [Roadmap](https://github.com/spring-cloud-incubator/spring-cloud-alibaba/blob/master/Roadmap-zh.md)。
## 如何构建
@ -96,6 +99,8 @@ Example 列表:
[Alibaba Cloud ACM Example](https://github.com/spring-cloud-incubator/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/acm-example/acm-local-example/readme-zh.md)
[Alibaba Cloud SchedulerX Example](https://github.com/xiaolongzuo/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/schedulerx-example/schedulerx-simple-task-example/readme-zh.md)
## 版本管理规范
项目的版本号格式为 x.x.x 的形式,其中 x 的数值类型为数字从0开始取值且不限于 0~9 这个范围。项目处于孵化器阶段时第一位版本号固定使用0即版本号为 0.x.x 的格式。

View File

@ -185,7 +185,7 @@ Sentinel RestTemplate 限流的资源规则提供两种粒度:
* `schema://host:port`:协议、主机和端口
NOTE: 以 `https://www.taobao.com/test` 这个 url 为例。对应的资源名有两种粒度,分别是 `https://www.taobao.com:80` 以及 `https://www.taobao.com:80/test`
NOTE: 以 `https://www.taobao.com/test` 这个 url 为例。对应的资源名有两种粒度,分别是 `https://www.taobao.com` 以及 `https://www.taobao.com/test`
### 动态数据源支持

View File

@ -187,7 +187,7 @@ Sentinel RestTemplate provides two granularities for resource rate limiting:
* `schema://host:port` Protocol, host and port
NOTE: Take `https://www.taobao.com/test` as an example. The corresponding resource names have two levels of granularities, `https://www.taobao.com:80` and `https://www.taobao.com:80/test`.
NOTE: Take `https://www.taobao.com/test` as an example. The corresponding resource names have two levels of granularities, `https://www.taobao.com` and `https://www.taobao.com/test`.
### Dynamic Data Source Support

View File

@ -1,6 +1,6 @@
[[spring-cloud-alibaba-reference]]
= Spring Cloud Alibaba Reference Documentation
xiaojing; xiaolongzuo; jim fang; bingting peng
xiaojing; xiaolongzuo; jim fang; bingting peng; wangyuxin
:doctype: book
:toc:
:toclevels: 4

View File

@ -122,28 +122,30 @@
## 自定义限流处理逻辑
1. URL 限流触发后默认处理逻辑是,直接返回 "Blocked by Sentinel (flow limiting)"。
* 默认限流异常处理
URL 限流触发后默认处理逻辑是,直接返回 "Blocked by Sentinel (flow limiting)"。
如果需要自定义处理逻辑,实现的方式如下:
```java
public class CustomUrlBlockHandler implements UrlBlockHandler {
@Override
public void blocked(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException {
// todo add your logic
}
}
```java
public class CustomUrlBlockHandler implements UrlBlockHandler {
@Override
public void blocked(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException {
// todo add your logic
}
}
WebCallbackManager.setUrlBlockHandler(new CustomUrlBlockHandler());
```
WebCallbackManager.setUrlBlockHandler(new CustomUrlBlockHandler());
```
2. 自定义限流触发后,默认的处理逻辑是抛出异常。
* 使用 `@SentinelResource` 注解下的限流异常处理
如果需要自定义处理逻辑,填写 `@SentinelResource` 注解的 `blockHandler` 属性(针对所有类型的 `BlockException`,需自行判断)或 `fallback` 属性(针对熔断降级异常),注意**对应方法的签名和位置有限制**,详情见 [Sentinel 注解支持文档](https://github.com/alibaba/Sentinel/wiki/%E6%B3%A8%E8%A7%A3%E6%94%AF%E6%8C%81#sentinelresource-%E6%B3%A8%E8%A7%A3)。示例实现如下:
```java
public class TestService {
// blockHandler 是位于 ExceptionUtil 类下的 handleException 静态方法,需符合对应的类型限制.
// blockHandler 是位于 ExceptionUtil 类下的 handleException 静态方法,需符合对应的类型限制.
@SentinelResource(value = "test", blockHandler = "handleException", blockHandlerClass = {ExceptionUtil.class})
public void test() {
System.out.println("Test");
@ -172,7 +174,7 @@ public final class ExceptionUtil {
}
```
一个简单的示例可以见 [sentinel-demo-annotation-spring-aop](https://github.com/alibaba/Sentinel/tree/master/sentinel-demo/sentinel-demo-annotation-spring-aop)。
一个简单的 `@SentinelResource` 示例可以见 [sentinel-demo-annotation-spring-aop](https://github.com/alibaba/Sentinel/tree/master/sentinel-demo/sentinel-demo-annotation-spring-aop)。
## Endpoint 信息查看

View File

@ -108,7 +108,9 @@ The screenshot belows shows invoke success:
## Customize Flow Control Logic
1. When a URL resource is blocked by Sentinel, the default logic is return HTTP response "Blocked by Sentinel (flow limiting)".
* Flow control exception handle by default
When a URL resource is blocked by Sentinel, the default logic is return HTTP response "Blocked by Sentinel (flow limiting)".
If you want to customize your flow control logic, see the code below:
@ -123,7 +125,9 @@ The screenshot belows shows invoke success:
WebCallbackManager.setUrlBlockHandler(new CustomUrlBlockHandler());
2. When a custom resource is blocked by Sentinel, the default logic is throw BlockException.
* Flow control exception handle by using `@SentinelResource`
When a custom resource is blocked by Sentinel, the default logic is throw BlockException.
If you want to customize your flow control logic, implement interface `SentinelExceptionHandler`, set @SentinelResource's blockHandler() and blockHandlerClass(). See the code below:

View File

@ -1,5 +1,9 @@
package org.springframework.cloud.alibaba.cloud.examples;
import org.springframework.cloud.alibaba.sentinel.rest.SentinelClientHttpResponse;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import com.alibaba.csp.sentinel.slots.block.BlockException;
/**
@ -7,8 +11,10 @@ import com.alibaba.csp.sentinel.slots.block.BlockException;
*/
public class ExceptionUtil {
public static void handleException(BlockException ex) {
public static SentinelClientHttpResponse handleException(HttpRequest request,
byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
System.out.println("Oops: " + ex.getClass().getCanonicalName());
return new SentinelClientHttpResponse("custom block info");
}
}

View File

@ -16,9 +16,9 @@
"strategy": 0
},
{
"resource": "abc",
"resource": "http://www.taobao.com",
"controlBehavior": 0,
"count": 1,
"count": 0,
"grade": 1,
"limitApp": "default",
"strategy": 0

View File

@ -33,6 +33,7 @@ import org.springframework.util.ClassUtils;
import com.alibaba.csp.sentinel.Entry;
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;
@ -58,27 +59,41 @@ public class SentinelProtectInterceptor implements ClientHttpRequestInterceptor
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
ClientHttpRequestExecution execution) throws IOException {
URI uri = request.getURI();
String hostResource = uri.getScheme() + "://" + uri.getHost() + ":"
+ (uri.getPort() == -1 ? 80 : uri.getPort());
String hostResource = uri.getScheme() + "://" + uri.getHost()
+ (uri.getPort() == -1 ? "" : ":" + uri.getPort());
String hostWithPathResource = hostResource + uri.getPath();
boolean entryWithPath = true;
if (hostResource.equals(hostWithPathResource)) {
entryWithPath = false;
}
Entry hostEntry = null, hostWithPathEntry = null;
ClientHttpResponse response;
try {
ContextUtil.enter(hostWithPathResource);
hostWithPathEntry = SphU.entry(hostWithPathResource);
if (entryWithPath) {
hostWithPathEntry = SphU.entry(hostWithPathResource);
}
hostEntry = SphU.entry(hostResource);
response = execution.execute(request, body);
}
catch (BlockException e) {
try {
return handleBlockException(request, body, execution, e);
catch (Throwable e) {
if (!BlockException.isBlockException(e)) {
Tracer.trace(e);
throw new IllegalStateException(e);
}
catch (Exception ex) {
if (ex instanceof IllegalStateException) {
throw (IllegalStateException) ex;
else {
try {
return handleBlockException(request, body, execution,
(BlockException) e);
}
catch (Exception ex) {
if (ex instanceof IllegalStateException) {
throw (IllegalStateException) ex;
}
throw new IllegalStateException(
"sentinel handle BlockException error: " + ex.getMessage(),
ex);
}
throw new IllegalStateException(
"sentinel handle BlockException error: " + ex.getMessage(), ex);
}
}
finally {

View File

@ -25,11 +25,14 @@ import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.cloud.alicloud.acm.AcmPropertySourceRepository;
import org.springframework.cloud.alicloud.acm.bootstrap.AcmPropertySource;
import org.springframework.cloud.alicloud.context.acm.AcmIntegrationProperties;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.cloud.endpoint.event.RefreshEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.util.StringUtils;
@ -43,7 +46,8 @@ import com.alibaba.edas.acm.listener.ConfigChangeListener;
*
* @author juven.xuxb, 5/13/16.
*/
public class AcmContextRefresher implements ApplicationListener<ApplicationReadyEvent> {
public class AcmContextRefresher
implements ApplicationListener<ApplicationReadyEvent>, ApplicationContextAware {
private Logger logger = LoggerFactory.getLogger(AcmContextRefresher.class);
@ -53,6 +57,8 @@ public class AcmContextRefresher implements ApplicationListener<ApplicationReady
private final AcmRefreshHistory refreshHistory;
private ApplicationContext applicationContext;
private final AcmPropertySourceRepository acmPropertySourceRepository;
private Map<String, ConfigChangeListener> listenerMap = new ConcurrentHashMap<>(16);
@ -74,19 +80,10 @@ public class AcmContextRefresher implements ApplicationListener<ApplicationReady
private void registerDiamondListenersForApplications() {
if (acmIntegrationProperties.getAcmProperties().isRefreshEnabled()) {
for (AcmPropertySource acmPropertySource : acmPropertySourceRepository
.getAll()) {
if (acmPropertySource.isGroupLevel()) {
continue;
}
String dataId = acmPropertySource.getDataId();
for (String dataId : acmIntegrationProperties
.getApplicationConfigurationDataIds()) {
registerDiamondListener(dataId);
}
if (acmPropertySourceRepository.getAll().isEmpty()) {
registerDiamondListener(acmIntegrationProperties
.getApplicationConfigurationDataIdWithoutGroup());
}
}
}
@ -110,11 +107,17 @@ public class AcmContextRefresher implements ApplicationListener<ApplicationReady
}
}
refreshHistory.add(dataId, md5);
contextRefresher.refresh();
applicationContext.publishEvent(new RefreshEvent(this, md5,
"ACM Refresh, dataId=" + dataId));
}
});
ConfigService.addListener(dataId,
acmIntegrationProperties.getAcmProperties().getGroup(), listener);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
}