init
This commit is contained in:
40
sentinel/sentinel-demo/sentinel-demo-spring-webflux/pom.xml
Normal file
40
sentinel/sentinel-demo/sentinel-demo-spring-webflux/pom.xml
Normal file
@@ -0,0 +1,40 @@
|
||||
<?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-demo</artifactId>
|
||||
<groupId>com.alibaba.csp</groupId>
|
||||
<version>1.8.3</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>sentinel-demo-spring-webflux</artifactId>
|
||||
|
||||
<properties>
|
||||
<spring.boot.version>2.1.3.RELEASE</spring.boot.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.csp</groupId>
|
||||
<artifactId>sentinel-transport-simple-http</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.csp</groupId>
|
||||
<artifactId>sentinel-spring-webflux-adapter</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 1999-2019 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.demo.spring.webflux;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* <p>A demo for Spring WebFlux reactive application.</p>
|
||||
*
|
||||
* <p>To integrate with Sentinel dashboard, you can run the demo with the parameters (an example):
|
||||
* <code>-Dproject.name=WebFluxDemoApplication -Dcsp.sentinel.dashboard.server=localhost:8080
|
||||
* -Dcsp.sentinel.api.port=8720
|
||||
* </code>
|
||||
* </p>
|
||||
*
|
||||
* @author Eric Zhao
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class WebFluxDemoApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(WebFluxDemoApplication.class, args);
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.demo.spring.webflux.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.ReactiveRedisTemplate;
|
||||
import org.springframework.data.redis.serializer.RedisSerializationContext;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
* @author Eric Zhao
|
||||
*/
|
||||
@Configuration
|
||||
public class RedisConfig {
|
||||
|
||||
@Bean
|
||||
public ReactiveRedisTemplate<String, String> stringReactiveRedisTemplate(ReactiveRedisConnectionFactory connectionFactory){
|
||||
RedisSerializationContext<String, String> serializationContext = RedisSerializationContext
|
||||
.<String, String>newSerializationContext(new StringRedisSerializer())
|
||||
.hashKey(new StringRedisSerializer())
|
||||
.hashValue(new StringRedisSerializer())
|
||||
.build();
|
||||
return new ReactiveRedisTemplate<>(connectionFactory, serializationContext);
|
||||
}
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.demo.spring.webflux.config;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.csp.sentinel.adapter.spring.webflux.SentinelWebFluxFilter;
|
||||
import com.alibaba.csp.sentinel.adapter.spring.webflux.exception.SentinelBlockExceptionHandler;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.codec.ServerCodecConfigurer;
|
||||
import org.springframework.web.reactive.result.view.ViewResolver;
|
||||
|
||||
/**
|
||||
* @author Eric Zhao
|
||||
*/
|
||||
public class WebFluxConfig {
|
||||
|
||||
private final List<ViewResolver> viewResolvers;
|
||||
private final ServerCodecConfigurer serverCodecConfigurer;
|
||||
|
||||
public WebFluxConfig(ObjectProvider<List<ViewResolver>> viewResolversProvider,
|
||||
ServerCodecConfigurer serverCodecConfigurer) {
|
||||
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
|
||||
this.serverCodecConfigurer = serverCodecConfigurer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(-1)
|
||||
public SentinelBlockExceptionHandler sentinelBlockExceptionHandler() {
|
||||
// Register the block exception handler for Spring WebFlux.
|
||||
return new SentinelBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(-1)
|
||||
public SentinelWebFluxFilter sentinelWebFluxFilter() {
|
||||
// Register the Sentinel WebFlux filter.
|
||||
return new SentinelWebFluxFilter();
|
||||
}
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 1999-2019 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.demo.spring.webflux.controller;
|
||||
|
||||
import com.alibaba.csp.sentinel.adapter.reactor.SentinelReactorTransformer;
|
||||
import com.alibaba.csp.sentinel.demo.spring.webflux.service.BazService;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Eric Zhao
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/baz")
|
||||
public class BazController {
|
||||
|
||||
@Autowired
|
||||
private BazService bazService;
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public Mono<String> apiGetValue(@PathVariable("id") Long id) {
|
||||
return bazService.getById(id)
|
||||
.transform(new SentinelReactorTransformer<>("BazService:getById"));
|
||||
}
|
||||
|
||||
@PostMapping("/{id}")
|
||||
public Mono<Boolean> apiSetValue(@PathVariable("id") Long id, @RequestBody String value) {
|
||||
return bazService.setValue(id, value)
|
||||
.transform(new SentinelReactorTransformer<>("BazService:setValue"));
|
||||
}
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 1999-2019 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.demo.spring.webflux.controller;
|
||||
|
||||
import com.alibaba.csp.sentinel.adapter.reactor.SentinelReactorTransformer;
|
||||
import com.alibaba.csp.sentinel.demo.spring.webflux.service.FooService;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Eric Zhao
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/foo")
|
||||
public class FooController {
|
||||
|
||||
@Autowired
|
||||
private FooService fooService;
|
||||
|
||||
@GetMapping("/single")
|
||||
public Mono<String> apiNormalSingle() {
|
||||
return fooService.emitSingle()
|
||||
// transform the publisher here.
|
||||
.transform(new SentinelReactorTransformer<>("demo_foo_normal_single"));
|
||||
}
|
||||
|
||||
@GetMapping("/flux")
|
||||
public Flux<Integer> apiNormalFlux() {
|
||||
return fooService.emitMultiple()
|
||||
.transform(new SentinelReactorTransformer<>("demo_foo_normal_flux"));
|
||||
}
|
||||
|
||||
@GetMapping("/slow")
|
||||
public Mono<String> apiDoSomethingSlow(ServerHttpResponse response) {
|
||||
return fooService.doSomethingSlow();
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 1999-2019 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.demo.spring.webflux.service;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.ReactiveRedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* <p>A sample service for interacting with Redis via reactive Redis client.</p>
|
||||
* <p>To play this service, you need a Redis instance running in local.</p>
|
||||
*
|
||||
* @author Eric Zhao
|
||||
*/
|
||||
@Service
|
||||
public class BazService {
|
||||
|
||||
@Autowired
|
||||
private ReactiveRedisTemplate<String, String> template;
|
||||
|
||||
public Mono<String> getById(Long id) {
|
||||
if (id == null || id <= 0) {
|
||||
return Mono.error(new IllegalArgumentException("invalid id: " + id));
|
||||
}
|
||||
return template.opsForValue()
|
||||
.get(KEY_PREFIX + id)
|
||||
.switchIfEmpty(Mono.just("not_found"));
|
||||
}
|
||||
|
||||
public Mono<Boolean> setValue(Long id, String value) {
|
||||
if (id == null || id <= 0 || value == null) {
|
||||
return Mono.error(new IllegalArgumentException("invalid parameters"));
|
||||
}
|
||||
return template.opsForValue()
|
||||
.set(KEY_PREFIX + id, value);
|
||||
}
|
||||
|
||||
private static final String KEY_PREFIX = "sentinel-reactor-test:";
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.demo.spring.webflux.service;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.scheduler.Scheduler;
|
||||
import reactor.core.scheduler.Schedulers;
|
||||
|
||||
/**
|
||||
* @author Eric Zhao
|
||||
*/
|
||||
@Service
|
||||
public class FooService {
|
||||
|
||||
@SuppressWarnings("PMD.ThreadPoolCreationRule")
|
||||
private final ExecutorService pool = Executors.newFixedThreadPool(8);
|
||||
private final Scheduler scheduler = Schedulers.fromExecutor(pool);
|
||||
|
||||
public Mono<String> emitSingle() {
|
||||
return Mono.just(ThreadLocalRandom.current().nextInt(0, 2000))
|
||||
.map(e -> e + "d");
|
||||
}
|
||||
|
||||
public Flux<Integer> emitMultiple() {
|
||||
int start = ThreadLocalRandom.current().nextInt(0, 6000);
|
||||
return Flux.range(start, 10);
|
||||
}
|
||||
|
||||
public Mono<String> doSomethingSlow() {
|
||||
return Mono.fromCallable(() -> {
|
||||
Thread.sleep(2000);
|
||||
System.out.println("doSomethingSlow: " + Thread.currentThread().getName());
|
||||
return "ok";
|
||||
}).publishOn(scheduler);
|
||||
}
|
||||
}
|
@@ -0,0 +1,2 @@
|
||||
spring.application.name=sentinel-webflux-demo-application
|
||||
server.port=8081
|
Reference in New Issue
Block a user