Skip to content

Commit

Permalink
哨兵流控规则对应 Controller、Service 服务示例
Browse files Browse the repository at this point in the history
  • Loading branch information
YClimb committed Oct 12, 2020
1 parent 0888d47 commit 4696416
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 5 deletions.
3 changes: 0 additions & 3 deletions sentinel-sample/.mvn/wrapper/MavenWrapperDownloader.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;

public class MavenWrapperDownloader {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.example.demo.config;

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

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* 哨兵流控规则异常处理器
*
* @author yclimb
* @date 2020/10/12
*/
public interface BlockExceptionHandler {

/**
* 在此处处理限流异常,可以跳转到指定页面或返回指定的内容
*
* @param request req
* @param response resp
* @param e e
* @throws Exception e
*/
void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.example.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.PrintWriter;

/**
* 哨兵流控规则异常处理配置项(流控规则对应 Controller 中的方法)
*
* @author yclimb
* @date 2020/10/12
*/
@Configuration
public class SentinelWebConfig {

@Bean
public BlockExceptionHandler sentinelBlockExceptionHandler() {
return (request, response, e) -> {
// 429 Too Many Requests
response.setStatus(429);

PrintWriter out = response.getWriter();
out.print("Oops, blocked by Sentinel: " + e.getClass().getSimpleName());
out.flush();
out.close();
};
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,38 @@
package com.example.demo.controller;

import com.example.demo.service.TestService;
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.RestController;

/**
* 测试
* 测试控制层
*
* @author yclimb
* @date 2020/10/12
*/
@RestController
public class TestController {

@Autowired
private TestService testService;

@GetMapping("/test")
public void test() {
testService.test();
}

@GetMapping("/hello/{name}")
public String hello(@PathVariable String name) {
/*String str = testService.hello(111L);
System.out.println(str);*/
return testService.sayHello(name);
}

@GetMapping("/hello")
public void hello() {
testService.hello();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package com.example.demo.service;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
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.example.demo.util.ExceptionUtil;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
* 测试服务层(流控规则对应 Service 中的方法)
*
* @author yclimb
* @date 2020/10/12
*/
@Service
public class TestService {

/**
* 自定义流控规则,手动代码实现
*/
public void hello() {
initFlowRules();

// 循环30次
int i = 30;
while (i > 0) {
// 1.5.0 版本开始可以直接利用 try-with-resources 特性,自动 exit entry
try (Entry entry = SphU.entry("HelloWorld")) {
// 被保护的逻辑
System.out.println(i + ":hello world");
} catch (BlockException ex) {
// 处理被流控的逻辑
System.out.println(i + "blocked!");
}
i--;
}
}

/**
* 初始化流控规则,用于 hello 自定义流控规则方法使用
*/
private static void initFlowRules(){
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("HelloWorld");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// Set limit QPS to 20.
rule.setCount(20);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}

/**
* 哨兵自定义异常类
* 对应的 `handleException` 函数需要位于 `ExceptionUtil` 类中,并且必须为 static 函数.
*/
@SentinelResource(value = "test", blockHandler = "handleException", blockHandlerClass = {ExceptionUtil.class})
public void test() {
System.out.println("Test");
}

/**
* 默认哨兵,触动规则无异常处理
* @param name name
* @return String
*/
@SentinelResource(value = "sayHello")
public String sayHello(String name) {
return "Hello, " + name;
}

/**
* 原始函数
* 需要借助于本类方法 exceptionHandler、helloFallback 来使用
* @param s s
* @return String
*/
@SentinelResource(value = "hello", blockHandler = "exceptionHandler", fallback = "helloFallback")
public String hello(long s) {
return String.format("Hello at %d", s);
}

/**
* Fallback 函数,函数签名与原函数一致或加一个 Throwable 类型的参数.
* @param s s
* @return String
*/
public String helloFallback(long s) {
return String.format("Halooooo %d", s);
}

/**
* Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致.
* @param s s
* @param ex ex
* @return String
*/
public String exceptionHandler(long s, BlockException ex) {
// Do some log here.
ex.printStackTrace();
return "Oops, error occurred at " + s;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.example.demo.util;

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

/**
* 异常处理工具类
*
* @author yclimb
* @date 2020/10/12
*/
public final class ExceptionUtil {

/**
* 使用 @SentinelResource(blockHandlerClass) 时使用,返回值必须和方法返回值一致
* @param ex ex
*/
public static void handleException(BlockException ex) {
System.out.println("Oops: " + ex.getClass().getCanonicalName());
}
}
3 changes: 2 additions & 1 deletion sentinel-sample/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ server.port=8080
# spring 静态资源扫描路径
spring.resources.static_locations=classpath:/static/

# PS:哨兵控制台需要自己实现,可以使用 docker,地址: https://hub.docker.com/r/bladex/sentinel-dashboard
# Sentinel 控制台地址
spring.cloud.sentinel.transport.dashboard=localhost:8080
spring.cloud.sentinel.transport.dashboard=localhost:8858
# 取消Sentinel控制台懒加载
# 默认情况下 Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包
# 配置 sentinel.eager=true 时,取消Sentinel控制台懒加载功能
Expand Down

0 comments on commit 4696416

Please sign in to comment.