Skip to content

Commit

Permalink
Add Sentinel annotation definition and aspectj extension
Browse files Browse the repository at this point in the history
Signed-off-by: Eric Zhao <sczyh16@gmail.com>
  • Loading branch information
sczyh30 committed Aug 8, 2018
1 parent b37c237 commit 348b1c8
Show file tree
Hide file tree
Showing 7 changed files with 440 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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
*
* http://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.csp.sentinel.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.alibaba.csp.sentinel.EntryType;

/**
* @author Eric Zhao
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface SentinelResource {

/**
* @return name of the Sentinel resource
*/
String value();

/**
* @return the entry type (inbound or outbound), outbound by default
*/
EntryType entryType() default EntryType.OUT;

/**
* @return name of the block exception function, empty by default
*/
String blockHandler() default "";

/**
* @return name of the fallback function, empty by default
*/
String fallback() default "";
}
2 changes: 2 additions & 0 deletions sentinel-extension/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
<module>sentinel-datasource-extension</module>
<module>sentinel-datasource-nacos</module>
<module>sentinel-datasource-zookeeper</module>

<module>sentinel-annotation-aspectj</module>
</modules>

</project>
63 changes: 63 additions & 0 deletions sentinel-extension/sentinel-annotation-aspectj/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Sentinel Annotation AspectJ

This extension is an AOP implementation using AspectJ for Sentinel annotations.
Currently only runtime waving is supported.

## Annotation

The `@SentinelResource` annotation indicates a resource definition, including:

- `value`: Resource name, required (cannot be empty)
- `entryType`: Resource entry type (inbound or outbound), `EntryType.OUT` by default
- `fallback`: Fallback method when degraded (optional). The fallback method should be located in the same class with original method. The signature of the fallback method should match the original method (parameter types and return type)
- `blockHandler`: Handler method that handles `BlockException` when blocked. The block handler method should be located in the same class with original method, and the signature should match original method, with the last additional parameter type `BlockException`.

For example:

```java
@SentinelResource(value = "abc", fallback = "doFallback", blockHandler = "handleException")
public String doSomething(long i) {
return "Hello " + i;
}

public String doFallback(long i) {
// Return fallback value.
return "Oops, degraded";
}

public String handleException(long i, BlockException ex) {
// Handle the block exception here.
return null;
}
```

## Configuration

### AspectJ

If you are using AspectJ directly, you can add the Sentinel annotation aspect to
your `aop.xml`:

```xml
<aspects>
<aspect name="com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect"/>
</aspects>
```

### Spring AOP

If you are using Spring AOP, you should add a configuration to register the aspect
as a Spring bean:

```java
@Configuration
public class SentinelAspectConfiguration {

@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
}
```

An example for using Sentinel Annotation AspectJ with Spring Boot can be found [here](https://github.com/alibaba/Sentinel/tree/master/sentinel-demo/sentinel-demo-annotation-spring-aop).
37 changes: 37 additions & 0 deletions sentinel-extension/sentinel-annotation-aspectj/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>sentinel-extension</artifactId>
<groupId>com.alibaba.csp</groupId>
<version>0.1.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>sentinel-annotation-aspectj</artifactId>
<packaging>jar</packaging>

<properties>
<aspectj.version>1.9.1</aspectj.version>
</properties>

<dependencies>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
</dependency>

<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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
*
* http://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.csp.sentinel.annotation.aspectj;

import java.lang.reflect.Method;

/**
* @author Eric Zhao
*/
class MethodWrapper {

private final Method method;
private final boolean present;

private MethodWrapper(Method method, boolean present) {
this.method = method;
this.present = present;
}

static MethodWrapper wrap(Method method) {
if (method == null) {
return none();
}
return new MethodWrapper(method, true);
}

static MethodWrapper none() {
return new MethodWrapper(null, false);
}

Method getMethod() {
return method;
}

boolean isPresent() {
return present;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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
*
* http://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.csp.sentinel.annotation.aspectj;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.alibaba.csp.sentinel.util.StringUtil;

/**
* @author Eric Zhao
*/
public final class ResourceMetadataRegistry {

private static final Map<String, MethodWrapper> FALLBACK_MAP = new ConcurrentHashMap<String, MethodWrapper>();
private static final Map<String, MethodWrapper> BLOCK_HANDLER_MAP = new ConcurrentHashMap<String, MethodWrapper>();

public static MethodWrapper lookupFallback(Class<?> clazz, String name) {
return FALLBACK_MAP.get(getKey(clazz, name));
}

public static MethodWrapper lookupBlockHandler(Class<?> clazz, String name) {
return BLOCK_HANDLER_MAP.get(getKey(clazz, name));
}

public static void updateFallbackFor(Class<?> clazz, String name, Method method) {
if (clazz == null || StringUtil.isBlank(name)) {
throw new IllegalArgumentException("Bad argument");
}
FALLBACK_MAP.put(getKey(clazz, name), MethodWrapper.wrap(method));
}

public static void updateBlockHandlerFor(Class<?> clazz, String name, Method method) {
if (clazz == null || StringUtil.isBlank(name)) {
throw new IllegalArgumentException("Bad argument");
}
BLOCK_HANDLER_MAP.put(getKey(clazz, name), MethodWrapper.wrap(method));
}

public static String getKey(Class<?> clazz, String name) {
return String.format("%s:%s", clazz.getCanonicalName(), name);
}
}
Loading

0 comments on commit 348b1c8

Please sign in to comment.