Dubbo + Sentinel集成
添加依赖
<!-- Dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<!-- Sentinel Dubbo适配器 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-apache-dubbo3-adapter</artifactId>
<version>1.8.6</version>
</dependency>
配置文件
dubbo:
application:
name: order-service
registry:
address: nacos://localhost:8848
protocol:
name: dubbo
port: 20880
consumer:
timeout: 3000
check: false
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
服务提供者保护
定义接口
public interface ProductService {
Product getProduct(Long id);
List<Product> listProducts(int page, int size);
}
实现类
@DubboService
public class ProductServiceImpl implements ProductService {
@Override
@SentinelResource(value = "getProduct", blockHandler = "handleBlock")
public Product getProduct(Long id) {
return productDao.findById(id);
}
@Override
@SentinelResource(value = "listProducts")
public List<Product> listProducts(int page, int size) {
return productDao.findAll(page, size);
}
public Product handleBlock(Long id, BlockException ex) {
return Product.builder()
.id(id)
.name("商品服务限流")
.build();
}
}
配置限流规则
@Configuration
public class ProviderSentinelConfig {
@PostConstruct
public void initRules() {
List<FlowRule> rules = new ArrayList<>();
// 保护getProduct接口
FlowRule rule1 = new FlowRule();
rule1.setResource("getProduct");
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule1.setCount(1000);
rules.add(rule1);
// 保护listProducts接口
FlowRule rule2 = new FlowRule();
rule2.setResource("listProducts");
rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule2.setCount(500);
rules.add(rule2);
FlowRuleManager.loadRules(rules);
}
}
服务消费者保护
引用服务
@Service
public class OrderService {
@DubboReference
private ProductService productService;
@SentinelResource(
value = "createOrder",
fallback = "handleFallback"
)
public Order createOrder(Long productId, int quantity) {
// 调用Dubbo服务
Product product = productService.getProduct(productId);
Order order = new Order();
order.setProductId(product.getId());
order.setQuantity(quantity);
return orderDao.save(order);
}
public Order handleFallback(Long productId, int quantity, Throwable ex) {
log.error("订单创建失败", ex);
throw new BusinessException("商品服务不可用");
}
}
配置熔断规则
@Configuration
public class ConsumerSentinelConfig {
@PostConstruct
public void initRules() {
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule();
rule.setResource("com.example.ProductService:getProduct(java.lang.Long)");
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
rule.setCount(1000); // RT > 1秒
rule.setSlowRatioThreshold(0.5);
rule.setTimeWindow(10);
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
}
基于来源限流
场景:不同消费者不同限流
// 提供者配置
FlowRule rule = new FlowRule();
rule.setResource("getProduct");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(100);
rule.setLimitApp("order-service"); // 只对订单服务限流100
自定义来源解析
public class DubboOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest request) {
// 从Dubbo上下文获取调用方应用名
String application = RpcContext.getContext()
.getAttachment("application");
return application != null ? application : "unknown";
}
}
Dubbo Filter实现
Sentinel通过Dubbo Filter自动拦截,资源名格式:
提供者侧:
接口全限定名:方法名(参数类型)
示例:com.example.ProductService:getProduct(java.lang.Long)
消费者侧:
接口全限定名:方法名(参数类型)
示例:com.example.ProductService:getProduct(java.lang.Long)
完整实战案例
商品服务(Provider)
@SpringBootApplication
@EnableDubbo
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
@DubboService(version = "1.0.0", timeout = 3000)
public class ProductServiceImpl implements ProductService {
@Override
@SentinelResource(value = "getProduct", blockHandler = "handleBlock")
public Product getProduct(Long id) {
return productDao.findById(id);
}
public Product handleBlock(Long id, BlockException ex) {
log.warn("商品查询被限流:id={}", id);
return Product.builder()
.id(id)
.name("商品查询繁忙")
.build();
}
}
@Configuration
public class ProductSentinelConfig {
@PostConstruct
public void initRules() {
List<FlowRule> flowRules = new ArrayList<>();
// 1. 总QPS限流
FlowRule totalRule = new FlowRule();
totalRule.setResource("com.example.ProductService:getProduct(java.lang.Long)");
totalRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
totalRule.setCount(1000);
flowRules.add(totalRule);
// 2. 针对订单服务限流
FlowRule orderRule = new FlowRule();
orderRule.setResource("com.example.ProductService:getProduct(java.lang.Long)");
orderRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
orderRule.setCount(500);
orderRule.setLimitApp("order-service");
flowRules.add(orderRule);
FlowRuleManager.loadRules(flowRules);
}
}
订单服务(Consumer)
@SpringBootApplication
@EnableDubbo
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
@Service
public class OrderService {
@DubboReference(version = "1.0.0", check = false)
private ProductService productService;
@SentinelResource(value = "createOrder", fallback = "createOrderFallback")
public Order createOrder(Long productId, int quantity) {
// 调用商品服务
Product product = productService.getProduct(productId);
Order order = new Order();
order.setProductId(product.getId());
order.setQuantity(quantity);
return orderDao.save(order);
}
public Order createOrderFallback(Long productId, int quantity, Throwable ex) {
log.error("创建订单失败", ex);
throw new BusinessException("商品服务不可用,请稍后重试");
}
}
@Configuration
public class OrderSentinelConfig {
@PostConstruct
public void initRules() {
List<DegradeRule> rules = new ArrayList<>();
// 对商品服务熔断
DegradeRule rule = new DegradeRule();
rule.setResource("com.example.ProductService:getProduct(java.lang.Long)");
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
rule.setCount(1000);
rule.setSlowRatioThreshold(0.5);
rule.setTimeWindow(10);
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
}
Dubbo泛化调用保护
ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
reference.setInterface("com.example.ProductService");
reference.setGeneric("true");
GenericService genericService = reference.get();
@SentinelResource(value = "genericCall")
public Object callGeneric(String method, String[] paramTypes, Object[] args) {
return genericService.$invoke(method, paramTypes, args);
}
总结
Dubbo + Sentinel集成要点:
- 自动拦截Dubbo调用,无需手动埋点
- 提供者限流保护服务端
- 消费者熔断保护调用端
- 支持基于来源的差异化限流
- 资源名格式:接口:方法(参数)