ソースを参照

Add Sentinel annotation and JAX-RS plugins for Quarkus (#1542)

* Add sentinel-quarkus-adapter module, which provides sentinel-annotation-quarkus-adapter and sentinel-jax-rs-quarkus-adapter to adapt sentinel-annotation-cdi-interceptor and sentinel-jax-rs-adapter for Quarkus. It also provides sentinel-native-image-quarkus-adapter to support running Sentinel with Quarkus in native image mode.
master
seasidesky GitHub 4年前
コミット
fda21de748
この署名に対応する既知のキーがデータベースに存在しません GPGキーID: 4AEE18F83AFDEB23
22個のファイルの変更1446行の追加0行の削除
  1. +1
    -0
      sentinel-adapter/pom.xml
  2. +86
    -0
      sentinel-adapter/sentinel-quarkus-adapter/README.md
  3. +55
    -0
      sentinel-adapter/sentinel-quarkus-adapter/pom.xml
  4. +72
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-deployment/pom.xml
  5. +46
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-deployment/src/main/java/com/alibaba/csp/sentinel/annotation/quarkus/adapter/deployment/SentinelAnnotationQuarkusAdapterProcessor.java
  6. +84
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-deployment/src/test/java/com/alibaba/csp/sentinel/annotation/quarkus/adapter/deployment/FooService.java
  7. +37
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-deployment/src/test/java/com/alibaba/csp/sentinel/annotation/quarkus/adapter/deployment/FooUtil.java
  8. +197
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-deployment/src/test/java/com/alibaba/csp/sentinel/annotation/quarkus/adapter/deployment/SentinelAnnotationQuarkusAdapterTest.java
  9. +63
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-runtime/pom.xml
  10. +11
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-runtime/src/main/resources/META-INF/quarkus-extension.yaml
  11. +77
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-deployment/pom.xml
  12. +37
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-deployment/src/main/java/com/alibaba/csp/sentinel/jaxrs/quarkus/adapter/deployment/SentinelJaxRsQuarkusAdapterProcessor.java
  13. +242
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-deployment/src/test/java/com/alibaba/csp/sentinel/jaxrs/quarkus/adapter/deployment/SentinelJaxRsQuarkusAdapterTest.java
  14. +90
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-deployment/src/test/java/com/alibaba/csp/sentinel/jaxrs/quarkus/adapter/deployment/TestResource.java
  15. +63
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-runtime/pom.xml
  16. +11
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-runtime/src/main/resources/META-INF/quarkus-extension.yaml
  17. +2
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-runtime/src/main/resources/META-INF/services/javax.ws.rs.ext.Providers
  18. +60
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-deployment/pom.xml
  19. +73
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-deployment/src/main/java/com/alibaba/csp/sentinel/nativeimage/SentinelNativeImageProcessor.java
  20. +75
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-runtime/pom.xml
  21. +52
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-runtime/src/main/java/com/alibaba/csp/sentinel/nativeimage/SentinelRecorder.java
  22. +12
    -0
      sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-runtime/src/main/resources/META-INF/quarkus-extension.yaml

+ 1
- 0
sentinel-adapter/pom.xml ファイルの表示

@@ -29,6 +29,7 @@
<module>sentinel-zuul2-adapter</module>
<module>sentinel-okhttp-adapter</module>
<module>sentinel-jax-rs-adapter</module>
<module>sentinel-quarkus-adapter</module>
</modules>

<dependencyManagement>


+ 86
- 0
sentinel-adapter/sentinel-quarkus-adapter/README.md ファイルの表示

@@ -0,0 +1,86 @@
# sentinel quarkus adapter

sentinel quarkus adapter provides `sentinel-annotation-quarkus-adapter` and `sentinel-jax-rs-quarkus-adapter` to adapt `sentinel-annotation-cdi-interceptor` and `sentinel-jax-rs-adapter` for quarkus

sentinel quarkus adapter also provides `sentinel-native-image-quarkus-adapter` to support running sentinel with quarkus in native image mode.

To use sentinel-jax-rs-quarkus-adapter, you can simply add the following dependency to your `pom.xml`:

```xml
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-jax-rs-quarkus-adapter</artifactId>
<version>x.y.z</version>
</dependency>
```

To use sentinel-annotation-quarkus-adapter, you can simply add the following dependency to your `pom.xml`:

```xml
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-quarkus-adapter</artifactId>
<version>x.y.z</version>
</dependency>
```

if your quarkus application want to use both `sentinel-annotation-quarkus-adapter` and `sentinel-jax-rs-quarkus-adapter` , then add these two dependency together to your `pom.xml`:

```xml
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-jax-rs-quarkus-adapter</artifactId>
<version>x.y.z</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-quarkus-adapter</artifactId>
<version>x.y.z</version>
</dependency>
```

when quarkus application started, you can see the enabled feature like:

```
INFO [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, resteasy, sentinel-annotation, sentinel-jax-rs]
```

## for quarkus native image

if you want to make sentinel with quarkus running in native image mode, you should add the following dependency to your `pom.xml`:

```xml
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-native-image-quarkus-adapter</artifactId>
<version>x.y.z</version>
</dependency>
```

and then add `--allow-incomplete-classpath` to `quarkus.native.additional-build-args`.

if you use `sentinel-jax-rs-quarkus-adapter` you should set `quarkus.native.auto-service-loader-registration` to true.

you can refer to `sentinel-demo-quarkus`'s `pom.xml` for more details.

when quarkus application started, you can see the enabled feature like:

```
INFO [io.quarkus] (main) Installed features: [cdi, resteasy, sentinel-annotation, sentinel-jax-rs, sentinel-native-image]
```

### notes for limitations

`sentinel-native-image-quarkus-adapter` currently rely on `sentinel-logging-slf4j` to make sentinel run in native image mode easily, because `quarkus-core` provides `Target_org_slf4j_LoggerFactory` to substitue `getLogger` method.

currently `sentinel-transport-simple-http` can work in native image mode, while `sentinel-transport-netty-http` cannot work in native image mode without extra config or substitutions.

## references for build native image or AOT

- [Quarkus - Tips for writing native applications](https://quarkus.io/guides/writing-native-applications-tips)

- [Quarkus - Class Loading Reference](https://quarkus.io/guides/class-loading-reference)

- [substratevm LIMITATIONS](https://github.com/oracle/graal/blob/master/substratevm/LIMITATIONS.md)

- [Accessing resources in Substrate VM images](https://github.com/oracle/graal/blob/master/substratevm/RESOURCES.md)

+ 55
- 0
sentinel-adapter/sentinel-quarkus-adapter/pom.xml ファイルの表示

@@ -0,0 +1,55 @@
<?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">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-adapter</artifactId>
<version>1.8.0-SNAPSHOT</version>
</parent>

<artifactId>sentinel-quarkus-adapter-parent</artifactId>
<packaging>pom</packaging>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.parameters>true</maven.compiler.parameters>
<quarkus.version>1.4.1.Final</quarkus.version>
<compiler-plugin.version>3.8.1</compiler-plugin.version>
</properties>

<modules>
<module>sentinel-annotation-quarkus-adapter-deployment</module>
<module>sentinel-annotation-quarkus-adapter-runtime</module>
<module>sentinel-jax-rs-quarkus-adapter-deployment</module>
<module>sentinel-jax-rs-quarkus-adapter-runtime</module>
<module>sentinel-native-image-quarkus-adapter-deployment</module>
<module>sentinel-native-image-quarkus-adapter-runtime</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bom-deployment</artifactId>
<version>${quarkus.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler-plugin.version}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

+ 72
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-deployment/pom.xml ファイルの表示

@@ -0,0 +1,72 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-quarkus-adapter-parent</artifactId>
<version>1.8.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>sentinel-annotation-quarkus-adapter-deployment</artifactId>
<name>sentinel-annotation-quarkus-adapter-deployment</name>

<properties>
<java.source.version>1.8</java.source.version>
<java.target.version>1.8</java.target.version>
</properties>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc-deployment</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-quarkus-adapter</artifactId>
<version>${project.version}</version>
</dependency>

<!-- Test dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc-deployment</artifactId>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>

</project>

+ 46
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-deployment/src/main/java/com/alibaba/csp/sentinel/annotation/quarkus/adapter/deployment/SentinelAnnotationQuarkusAdapterProcessor.java ファイルの表示

@@ -0,0 +1,46 @@
/*
* Copyright 1999-2020 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
*
* 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.csp.sentinel.annotation.quarkus.adapter.deployment;

import com.alibaba.csp.sentinel.annotation.cdi.interceptor.SentinelResourceInterceptor;
import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.FeatureBuildItem;

import java.util.Arrays;
import java.util.List;

/**
* @author sea
*/
class SentinelAnnotationQuarkusAdapterProcessor {

private static final String FEATURE_ANNOTATION = "sentinel-annotation";

@BuildStep
void feature(BuildProducer<FeatureBuildItem> featureProducer) {
featureProducer.produce(new FeatureBuildItem(FEATURE_ANNOTATION));
}

@BuildStep
List<AdditionalBeanBuildItem> additionalBeans() {
return Arrays.asList(
new AdditionalBeanBuildItem(SentinelResourceInterceptor.class)
);
}

}

+ 84
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-deployment/src/test/java/com/alibaba/csp/sentinel/annotation/quarkus/adapter/deployment/FooService.java ファイルの表示

@@ -0,0 +1,84 @@
/*
* Copyright 1999-2020 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.quarkus.adapter.deployment;
import com.alibaba.csp.sentinel.annotation.cdi.interceptor.SentinelResourceBinding;
import com.alibaba.csp.sentinel.slots.block.BlockException;

import javax.enterprise.context.ApplicationScoped;
import java.util.concurrent.ThreadLocalRandom;

/**
* @author Eric Zhao
* @author sea
*/
@ApplicationScoped
public class FooService {

@SentinelResourceBinding(value = "apiFoo", blockHandler = "fooBlockHandler",
exceptionsToTrace = {IllegalArgumentException.class})
public String foo(int i) throws Exception {
if (i == 5758) {
throw new IllegalAccessException();
}
if (i == 5763) {
throw new IllegalArgumentException();
}
return "Hello for " + i;
}

@SentinelResourceBinding(value = "apiFooWithFallback", blockHandler = "fooBlockHandler", fallback = "fooFallbackFunc",
exceptionsToTrace = {IllegalArgumentException.class})
public String fooWithFallback(int i) throws Exception {
if (i == 5758) {
throw new IllegalAccessException();
}
if (i == 5763) {
throw new IllegalArgumentException();
}
return "Hello for " + i;
}

@SentinelResourceBinding(value = "apiAnotherFooWithDefaultFallback", defaultFallback = "globalDefaultFallback",
fallbackClass = {FooUtil.class})
public String anotherFoo(int i) {
if (i == 5758) {
throw new IllegalArgumentException("oops");
}
return "Hello for " + i;
}

@SentinelResourceBinding(blockHandler = "globalBlockHandler", blockHandlerClass = FooUtil.class)
public int random() {
return ThreadLocalRandom.current().nextInt(0, 30000);
}

@SentinelResourceBinding(value = "apiBaz", blockHandler = "bazBlockHandler",
exceptionsToIgnore = {IllegalMonitorStateException.class})
public String baz(String name) {
if (name.equals("fail")) {
throw new IllegalMonitorStateException("boom!");
}
return "cheers, " + name;
}

public String fooBlockHandler(int i, BlockException ex) {
return "Oops, " + i;
}

public String fooFallbackFunc(int i) {
return "eee...";
}
}

+ 37
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-deployment/src/test/java/com/alibaba/csp/sentinel/annotation/quarkus/adapter/deployment/FooUtil.java ファイルの表示

@@ -0,0 +1,37 @@
/*
* Copyright 1999-2020 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.quarkus.adapter.deployment;

import com.alibaba.csp.sentinel.slots.block.BlockException;

/**
* @author Eric Zhao
*/
public class FooUtil {

public static final int BLOCK_FLAG = 88888;
public static final String FALLBACK_DEFAULT_RESULT = "fallback";

public static int globalBlockHandler(BlockException ex) {
System.out.println("Oops: " + ex.getClass().getSimpleName());
return BLOCK_FLAG;
}

public static String globalDefaultFallback(Throwable t) {
System.out.println("Fallback caught: " + t.getClass().getSimpleName());
return FALLBACK_DEFAULT_RESULT;
}
}

+ 197
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-deployment/src/test/java/com/alibaba/csp/sentinel/annotation/quarkus/adapter/deployment/SentinelAnnotationQuarkusAdapterTest.java ファイルの表示

@@ -0,0 +1,197 @@
/*
* Copyright 1999-2020 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
*
* 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.csp.sentinel.annotation.quarkus.adapter.deployment;

import com.alibaba.csp.sentinel.node.ClusterNode;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
import com.alibaba.csp.sentinel.util.MethodUtil;
import io.quarkus.arc.ArcUndeclaredThrowableException;
import io.quarkus.test.QuarkusUnitTest;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collections;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;

/**
* @author sea
*/
public class SentinelAnnotationQuarkusAdapterTest {

@RegisterExtension
static final QuarkusUnitTest TEST = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap
.create(JavaArchive.class)
.addClasses(FooService.class, FooUtil.class)
.addPackage("com.alibaba.csp.sentinel.annotation.cdi.interceptor")
);

@Inject
FooService fooService;

@BeforeEach
public void setUp() throws Exception {
FlowRuleManager.loadRules(new ArrayList<FlowRule>());
ClusterBuilderSlot.resetClusterNodes();
}

@AfterEach
public void tearDown() throws Exception {
FlowRuleManager.loadRules(new ArrayList<FlowRule>());
ClusterBuilderSlot.resetClusterNodes();
}

@Test
public void testForeignBlockHandlerClass() throws Exception {
assertThat(fooService.random()).isNotEqualTo(FooUtil.BLOCK_FLAG);
String resourceName = MethodUtil.resolveMethodName(FooService.class.getDeclaredMethod("random"));
ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertThat(cn).isNotNull();
assertThat(cn.passQps()).isPositive();

FlowRuleManager.loadRules(Collections.singletonList(
new FlowRule(resourceName).setCount(0)
));
assertThat(fooService.random()).isEqualTo(FooUtil.BLOCK_FLAG);
assertThat(cn.blockQps()).isPositive();
}

@Test
public void testBlockHandlerNotFound() {
assertThat(fooService.baz("Sentinel")).isEqualTo("cheers, Sentinel");
String resourceName = "apiBaz";
ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertThat(cn).isNotNull();
assertThat(cn.passQps()).isPositive();

FlowRuleManager.loadRules(Collections.singletonList(
new FlowRule(resourceName).setCount(0)
));

Assertions.assertThrows(ArcUndeclaredThrowableException.class, () -> {
fooService.baz("Sentinel");
});
}

@Test
public void testAnnotationExceptionsToIgnore() {
assertThat(fooService.baz("Sentinel")).isEqualTo("cheers, Sentinel");
String resourceName = "apiBaz";
ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertThat(cn).isNotNull();
assertThat(cn.passQps()).isPositive();

try {
fooService.baz("fail");
fail("should not reach here");
} catch (IllegalMonitorStateException ex) {
assertThat(cn.exceptionQps()).isZero();
}
}

@Test
public void testFallbackWithNoParams() throws Exception {
assertThat(fooService.fooWithFallback(1)).isEqualTo("Hello for 1");
String resourceName = "apiFooWithFallback";
ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertThat(cn).isNotNull();
assertThat(cn.passQps()).isPositive();

// Fallback should be ignored for this.
try {
fooService.fooWithFallback(5758);
fail("should not reach here");
} catch (IllegalAccessException e) {
assertThat(cn.exceptionQps()).isZero();
}

// Fallback should take effect.
assertThat(fooService.fooWithFallback(5763)).isEqualTo("eee...");
assertThat(cn.exceptionQps()).isPositive();
assertThat(cn.blockQps()).isZero();

FlowRuleManager.loadRules(Collections.singletonList(
new FlowRule(resourceName).setCount(0)
));
// Fallback should not take effect for BlockException, as blockHandler is configured.
assertThat(fooService.fooWithFallback(2221)).isEqualTo("Oops, 2221");
assertThat(cn.blockQps()).isPositive();
}

@Test
public void testDefaultFallbackWithSingleParam() {
assertThat(fooService.anotherFoo(1)).isEqualTo("Hello for 1");
String resourceName = "apiAnotherFooWithDefaultFallback";
ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertThat(cn).isNotNull();
assertThat(cn.passQps()).isPositive();

// Default fallback should take effect.
assertThat(fooService.anotherFoo(5758)).isEqualTo(FooUtil.FALLBACK_DEFAULT_RESULT);
assertThat(cn.exceptionQps()).isPositive();
assertThat(cn.blockQps()).isZero();

FlowRuleManager.loadRules(Collections.singletonList(
new FlowRule(resourceName).setCount(0)
));
// Default fallback should also take effect for BlockException.
assertThat(fooService.anotherFoo(5758)).isEqualTo(FooUtil.FALLBACK_DEFAULT_RESULT);
assertThat(cn.blockQps()).isPositive();
}

@Test
public void testNormalBlockHandlerAndFallback() throws Exception {
assertThat(fooService.foo(1)).isEqualTo("Hello for 1");
String resourceName = "apiFoo";
ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertThat(cn).isNotNull();
assertThat(cn.passQps()).isPositive();

// Test for biz exception.
try {
fooService.foo(5758);
fail("should not reach here");
} catch (Exception ex) {
// Should not be traced.
assertThat(cn.exceptionQps()).isZero();
}

try {
fooService.foo(5763);
fail("should not reach here");
} catch (Exception ex) {
assertThat(cn.exceptionQps()).isPositive();
}

// Test for blockHandler
FlowRuleManager.loadRules(Collections.singletonList(
new FlowRule(resourceName).setCount(0)
));
assertThat(fooService.foo(1121)).isEqualTo("Oops, 1121");
assertThat(cn.blockQps()).isPositive();
}
}

+ 63
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-runtime/pom.xml ファイルの表示

@@ -0,0 +1,63 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-quarkus-adapter-parent</artifactId>
<version>1.8.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>sentinel-annotation-quarkus-adapter</artifactId>
<name>sentinel-annotation-quarkus-adapter</name>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core</artifactId>
<version>${quarkus.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-cdi-interceptor</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bootstrap-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<goals>
<goal>extension-descriptor</goal>
</goals>
<phase>compile</phase>
<configuration>
<deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}
</deployment>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>

+ 11
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-runtime/src/main/resources/META-INF/quarkus-extension.yaml ファイルの表示

@@ -0,0 +1,11 @@
---
name: "sentinel annotation extension"
metadata:
keywords:
- "sentinel"
- "rate limit"
- "circuit breaker"
categories:
- "rate limit"
- "circuit breaker"
status: "preview"

+ 77
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-deployment/pom.xml ファイルの表示

@@ -0,0 +1,77 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-quarkus-adapter-parent</artifactId>
<version>1.8.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>sentinel-jax-rs-quarkus-adapter-deployment</artifactId>
<name>sentinel-jax-rs-quarkus-adapter-deployment</name>

<properties>
<java.source.version>1.8</java.source.version>
<java.target.version>1.8</java.target.version>
</properties>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-server-common-deployment</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-jax-rs-quarkus-adapter</artifactId>
<version>${project.version}</version>
</dependency>

<!-- Test dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-deployment</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>

</project>

+ 37
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-deployment/src/main/java/com/alibaba/csp/sentinel/jaxrs/quarkus/adapter/deployment/SentinelJaxRsQuarkusAdapterProcessor.java ファイルの表示

@@ -0,0 +1,37 @@
/*
* Copyright 1999-2020 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
*
* 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.csp.sentinel.jaxrs.quarkus.adapter.deployment;

import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import org.jboss.logging.Logger;

/**
* @author sea
*/
class SentinelJaxRsQuarkusAdapterProcessor {

private static final Logger logger = Logger.getLogger(SentinelJaxRsQuarkusAdapterProcessor.class);

private static final String FEATURE_JAX_RS = "sentinel-jax-rs";

@BuildStep
void feature(BuildProducer<FeatureBuildItem> featureProducer) {
featureProducer.produce(new FeatureBuildItem(FEATURE_JAX_RS));
}

}

+ 242
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-deployment/src/test/java/com/alibaba/csp/sentinel/jaxrs/quarkus/adapter/deployment/SentinelJaxRsQuarkusAdapterTest.java ファイルの表示

@@ -0,0 +1,242 @@
/*
* Copyright 1999-2020 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
*
* 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.csp.sentinel.jaxrs.quarkus.adapter.deployment;

import com.alibaba.csp.sentinel.Constants;
import com.alibaba.csp.sentinel.adapter.jaxrs.config.SentinelJaxRsConfig;
import com.alibaba.csp.sentinel.adapter.jaxrs.fallback.SentinelJaxRsFallback;
import com.alibaba.csp.sentinel.adapter.jaxrs.request.RequestOriginParser;
import com.alibaba.csp.sentinel.node.ClusterNode;
import com.alibaba.csp.sentinel.node.EntranceNode;
import com.alibaba.csp.sentinel.node.Node;
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 com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
import com.alibaba.csp.sentinel.util.StringUtil;
import io.quarkus.test.QuarkusUnitTest;
import io.restassured.response.Response;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.MediaType;
import java.util.Collections;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.jupiter.api.Assertions.*;

/**
* @author sea
*/
public class SentinelJaxRsQuarkusAdapterTest {

private static final String HELLO_STR = "Hello!";

@RegisterExtension
static final QuarkusUnitTest TEST = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap
.create(JavaArchive.class)
.addClasses(TestResource.class));

@AfterEach
public void cleanUp() {
FlowRuleManager.loadRules(null);
ClusterBuilderSlot.resetClusterNodes();
}

@Test
public void testGetHello() {
String url = "/test/hello";
String resourceName = "GET:" + url;
Response response = given().get(url);
response.then().statusCode(200).body(equalTo(HELLO_STR));

ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertNotNull(cn);
assertEquals(1, cn.passQps(), 0.01);

String context = "";
for (Node n : Constants.ROOT.getChildList()) {
if (n instanceof EntranceNode) {
String id = ((EntranceNode) n).getId().getName();
if (url.equals(id)) {
context = ((EntranceNode) n).getId().getName();
}
}
}
assertEquals("", context);
}

@Test
public void testAsyncGetHello() {
String url = "/test/async-hello";
String resourceName = "GET:" + url;
Response response = given().get(url);
response.then().statusCode(200).body(equalTo(HELLO_STR));

ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertNotNull(cn);
assertEquals(1, cn.passQps(), 0.01);

String context = "";
for (Node n : Constants.ROOT.getChildList()) {
if (n instanceof EntranceNode) {
String id = ((EntranceNode) n).getId().getName();
if (url.equals(id)) {
context = ((EntranceNode) n).getId().getName();
}
}
}
assertEquals("", context);
}

@Test
public void testUrlPathParam() {
String url = "/test/hello/{name}";
String resourceName = "GET:" + url;

String url1 = "/test/hello/abc";
Response response1 = given().get(url1);
response1.then().statusCode(200).body(equalTo("Hello abc !"));

String url2 = "/test/hello/def";
Response response2 = given().get(url2);
response2.then().statusCode(200).body(equalTo("Hello def !"));

ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertNotNull(cn);
assertEquals(2, cn.passQps(), 0.01);

assertNull(ClusterBuilderSlot.getClusterNode("GET:" + url1));
assertNull(ClusterBuilderSlot.getClusterNode("GET:" + url2));
}

@Test
public void testDefaultFallback() {
String url = "/test/hello";
String resourceName = "GET:" + url;
configureRulesFor(resourceName, 0);
Response response = given().get(url);
response.then().statusCode(javax.ws.rs.core.Response.Status.TOO_MANY_REQUESTS.getStatusCode())
.body(equalTo("Blocked by Sentinel (flow limiting)"));

ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertNotNull(cn);
assertEquals(0, cn.passQps(), 0.01);
}

@Test
public void testCustomFallback() {
String url = "/test/hello";
String resourceName = "GET:" + url;
SentinelJaxRsConfig.setJaxRsFallback(new SentinelJaxRsFallback() {
@Override
public javax.ws.rs.core.Response fallbackResponse(String route, Throwable cause) {
return javax.ws.rs.core.Response.status(javax.ws.rs.core.Response.Status.OK)
.entity("Blocked by Sentinel (flow limiting)")
.type(MediaType.APPLICATION_JSON_TYPE)
.build();
}

@Override
public Future<javax.ws.rs.core.Response> fallbackFutureResponse(final String route, final Throwable cause) {
return new FutureTask<>(new Callable<javax.ws.rs.core.Response>() {
@Override
public javax.ws.rs.core.Response call() throws Exception {
return fallbackResponse(route, cause);
}
});
}
});


configureRulesFor(resourceName, 0);
Response response = given().get(url);
response.then().statusCode(javax.ws.rs.core.Response.Status.OK.getStatusCode())
.body(equalTo("Blocked by Sentinel (flow limiting)"));

ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertNotNull(cn);
assertEquals(0, cn.passQps(), 0.01);
}

@Test
public void testCustomRequestOriginParser() {
String url = "/test/hello";
String resourceName = "GET:" + url;

String limitOrigin = "appB";
final String headerName = "X-APP";
configureRulesFor(resourceName, 0, limitOrigin);

SentinelJaxRsConfig.setRequestOriginParser(new RequestOriginParser() {
@Override
public String parseOrigin(ContainerRequestContext request) {
String origin = request.getHeaderString(headerName);
return origin != null ? origin : "";
}
});

Response response = given()
.header(headerName, "appA").get(url);
response.then().statusCode(200).body(equalTo(HELLO_STR));

Response blockedResp = given()
.header(headerName, "appB")
.get(url);
blockedResp.then().statusCode(javax.ws.rs.core.Response.Status.TOO_MANY_REQUESTS.getStatusCode())
.body(equalTo("Blocked by Sentinel (flow limiting)"));

ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertNotNull(cn);
assertEquals(1, cn.passQps(), 0.01);
assertEquals(1, cn.blockQps(), 0.01);
}

@Test
public void testExceptionMapper() {
String url = "/test/ex";
String resourceName = "GET:" + url;
Response response = given().get(url);
response.then().statusCode(javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).body(equalTo("test exception mapper"));

ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName);
assertNotNull(cn);
}

private void configureRulesFor(String resource, int count) {
configureRulesFor(resource, count, "default");
}

private void configureRulesFor(String resource, int count, String limitApp) {
FlowRule rule = new FlowRule()
.setCount(count)
.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setResource(resource);
if (StringUtil.isNotBlank(limitApp)) {
rule.setLimitApp(limitApp);
}
FlowRuleManager.loadRules(Collections.singletonList(rule));
}
}

+ 90
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-deployment/src/test/java/com/alibaba/csp/sentinel/jaxrs/quarkus/adapter/deployment/TestResource.java ファイルの表示

@@ -0,0 +1,90 @@
/*
* Copyright 1999-2020 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
*
* 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.csp.sentinel.jaxrs.quarkus.adapter.deployment;


import javax.ws.rs.*;
import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.container.Suspended;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
* @author sea
*/
@Path("/test")
public class TestResource {

ExecutorService executor = Executors.newFixedThreadPool(5);

@Path("/hello")
@GET
@Produces({ MediaType.APPLICATION_JSON })
public String sayHello() {
return "Hello!";
}

@Path("/async-hello")
@GET
@Produces({ MediaType.APPLICATION_JSON })
public void asyncSayHello(@Suspended final AsyncResponse asyncResponse) {
executor.submit(new Runnable() {
@Override
public void run() {
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
asyncResponse.resume("Hello!");
}
});
}

@Path("/hello/{name}")
@GET
@Produces({ MediaType.APPLICATION_JSON })
public String sayHelloWithName(@PathParam(value = "name") String name) {
return "Hello " + name + " !";
}

@Path("/ex")
@GET
@Produces({ MediaType.APPLICATION_JSON })
public String exception() {
throw new RuntimeException("test exception mapper");
}

@Path("/400")
@GET
@Produces({ MediaType.APPLICATION_JSON })
public String badRequest() {
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity("test return 400")
.build());
}

@Path("/delay/{seconds}")
@GET
@Produces({ MediaType.APPLICATION_JSON })
public String delay(@PathParam(value = "seconds") long seconds) throws InterruptedException {
TimeUnit.SECONDS.sleep(seconds);
return "finish";
}
}

+ 63
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-runtime/pom.xml ファイルの表示

@@ -0,0 +1,63 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-quarkus-adapter-parent</artifactId>
<version>1.8.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>sentinel-jax-rs-quarkus-adapter</artifactId>
<name>sentinel-jax-rs-quarkus-adapter</name>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core</artifactId>
<version>${quarkus.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-jax-rs-adapter</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bootstrap-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<goals>
<goal>extension-descriptor</goal>
</goals>
<phase>compile</phase>
<configuration>
<deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}
</deployment>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>

+ 11
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-runtime/src/main/resources/META-INF/quarkus-extension.yaml ファイルの表示

@@ -0,0 +1,11 @@
---
name: "sentinel jax rs extension"
metadata:
keywords:
- "resteasy"
- "jaxrs"
- "sentinel"
categories:
- "web"
- "circuit breaker"
status: "preview"

+ 2
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-runtime/src/main/resources/META-INF/services/javax.ws.rs.ext.Providers ファイルの表示

@@ -0,0 +1,2 @@
com.alibaba.csp.sentinel.adapter.jaxrs.SentinelJaxRsProviderFilter
com.alibaba.csp.sentinel.adapter.jaxrs.exception.DefaultExceptionMapper

+ 60
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-deployment/pom.xml ファイルの表示

@@ -0,0 +1,60 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-quarkus-adapter-parent</artifactId>
<version>1.8.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>sentinel-native-image-quarkus-adapter-deployment</artifactId>
<name>sentinel-native-image-quarkus-adapter-deployment</name>

<properties>
<java.source.version>1.8</java.source.version>
<java.target.version>1.8</java.target.version>
</properties>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc-deployment</artifactId>
</dependency>
<dependency>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>svm</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-native-image-quarkus-adapter</artifactId>
<version>${project.version}</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>

</project>

+ 73
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-deployment/src/main/java/com/alibaba/csp/sentinel/nativeimage/SentinelNativeImageProcessor.java ファイルの表示

@@ -0,0 +1,73 @@
/*
* Copyright 1999-2020 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
*
* 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.csp.sentinel.nativeimage;

import com.alibaba.csp.sentinel.slots.DefaultSlotChainBuilder;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem;
import io.quarkus.deployment.pkg.steps.NativeBuild;

import java.util.Arrays;
import java.util.List;

/**
* @author sea
*/
class SentinelNativeImageProcessor {

private static final String FEATURE_NATIVE_IMAGE = "sentinel-native-image";

@BuildStep
void feature(BuildProducer<FeatureBuildItem> featureProducer) {
featureProducer.produce(new FeatureBuildItem(FEATURE_NATIVE_IMAGE));
}

@BuildStep(onlyIf = NativeBuild.class)
List<RuntimeInitializedClassBuildItem> runtimeInitializedClasses() {
return Arrays.asList(
new RuntimeInitializedClassBuildItem("com.alibaba.fastjson.serializer.JodaCodec"),
new RuntimeInitializedClassBuildItem("com.alibaba.fastjson.serializer.GuavaCodec"),
new RuntimeInitializedClassBuildItem("com.alibaba.fastjson.support.moneta.MonetaCodec"),
new RuntimeInitializedClassBuildItem("com.alibaba.csp.sentinel.Env"),
new RuntimeInitializedClassBuildItem("com.alibaba.csp.sentinel.init.InitExecutor"),
new RuntimeInitializedClassBuildItem("com.alibaba.csp.sentinel.cluster.ClusterStateManager"),
new RuntimeInitializedClassBuildItem("com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager"),
new RuntimeInitializedClassBuildItem("com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager"),
new RuntimeInitializedClassBuildItem("com.alibaba.csp.sentinel.node.metric.MetricTimerListener"),
new RuntimeInitializedClassBuildItem("com.alibaba.csp.sentinel.node.metric.MetricWriter"),
new RuntimeInitializedClassBuildItem("com.alibaba.csp.sentinel.util.TimeUtil"),
new RuntimeInitializedClassBuildItem("com.alibaba.csp.sentinel.eagleeye.StatLogController"),
new RuntimeInitializedClassBuildItem("com.alibaba.csp.sentinel.slots.logger.EagleEyeLogUtil"),
new RuntimeInitializedClassBuildItem("com.alibaba.csp.sentinel.eagleeye.EagleEye"));
}

@BuildStep(onlyIf = NativeBuild.class)
ReflectiveClassBuildItem setupSentinelReflectiveClasses() {
return new ReflectiveClassBuildItem(true, true, true,
DefaultSlotChainBuilder.class.getName());
}

@BuildStep(onlyIf = NativeBuild.class)
@Record(ExecutionTime.STATIC_INIT)
void record(SentinelRecorder recorder) {
recorder.init();
}
}

+ 75
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-runtime/pom.xml ファイルの表示

@@ -0,0 +1,75 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-quarkus-adapter-parent</artifactId>
<version>1.8.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>sentinel-native-image-quarkus-adapter</artifactId>
<name>sentinel-native-image-quarkus-adapter</name>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core</artifactId>
<version>${quarkus.version}</version>
</dependency>
<dependency>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>svm</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-parameter-flow-control</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-logging-slf4j</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bootstrap-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<goals>
<goal>extension-descriptor</goal>
</goals>
<phase>compile</phase>
<configuration>
<deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}
</deployment>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>

+ 52
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-runtime/src/main/java/com/alibaba/csp/sentinel/nativeimage/SentinelRecorder.java ファイルの表示

@@ -0,0 +1,52 @@
/*
* Copyright 1999-2020 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
*
* 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.csp.sentinel.nativeimage;

import com.alibaba.csp.sentinel.command.vo.NodeVo;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializeConfig;
import io.quarkus.runtime.annotations.Recorder;

/**
* @author sea
*/
@Recorder
public class SentinelRecorder {

/**
* register fastjson serializer deserializer class info
*/
public void init() {
SerializeConfig.getGlobalInstance().getObjectWriter(NodeVo.class);
SerializeConfig.getGlobalInstance().getObjectWriter(FlowRule.class);
SerializeConfig.getGlobalInstance().getObjectWriter(SystemRule.class);
SerializeConfig.getGlobalInstance().getObjectWriter(DegradeRule.class);
SerializeConfig.getGlobalInstance().getObjectWriter(AuthorityRule.class);
SerializeConfig.getGlobalInstance().getObjectWriter(ParamFlowRule.class);

ParserConfig.getGlobalInstance().getDeserializer(NodeVo.class);
ParserConfig.getGlobalInstance().getDeserializer(FlowRule.class);
ParserConfig.getGlobalInstance().getDeserializer(SystemRule.class);
ParserConfig.getGlobalInstance().getDeserializer(DegradeRule.class);
ParserConfig.getGlobalInstance().getDeserializer(AuthorityRule.class);
ParserConfig.getGlobalInstance().getDeserializer(ParamFlowRule.class);
}
}

+ 12
- 0
sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-runtime/src/main/resources/META-INF/quarkus-extension.yaml ファイルの表示

@@ -0,0 +1,12 @@
---
name: "sentinel native image extension"
metadata:
keywords:
- "sentinel"
- "rate limit"
- "circuit breaker"
- "native image"
categories:
- "rate limit"
- "circuit breaker"
status: "preview"

読み込み中…
キャンセル
保存