SpringCloud实战四十:fallback服务降级

  作者:记性不好的阁主

I.FALLBACK


1、准备两个提供者9003、9004,和一个服务消费者


配置参照:https://www.aimaboge.com/article/717


2、编写接口


  • 服务提供者:


package com.laoxu.springcloud.controller;

import com.laoxu.springcloud.entities.CommonResult;
import com.laoxu.springcloud.entities.Payment;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;

@RestController
public class PaymentController {

@Value("${server.port}")
public String serverPort;

public static HashMap<Long, Payment> hashMap = new HashMap<Long, Payment>();
static
{
hashMap.put(1L, new Payment(1L, "a"));
hashMap.put(2L, new Payment(2L, "b"));
hashMap.put(3L, new Payment(3L, "c"));
}

@GetMapping("/paymentSQL/{id}")
public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id){
Payment payment = hashMap.get(id);
CommonResult<Payment> result = new CommonResult<Payment>(200, "from mysql, serverPort: " + serverPort, payment);
return result;
}

}


  • 服务消费者


package com.laoxu.springcloud.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.laoxu.springcloud.entities.CommonResult;
import com.laoxu.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@Slf4j
public class CircleBreakerController {

public static final String SERVICE_URL = "http://nacos-payment-provider";

@Autowired
private RestTemplate restTemplate;

@RequestMapping("/consumer/fallback/{id}")
@SentinelResource(value = "fallback", fallback = "handleFallback")
public CommonResult<Payment> fallback(@PathVariable("id") Long id){
CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/" + id, CommonResult.class);
if(id == 4){
throw new IllegalArgumentException("IllegalArgumentException, 非法参数异常。。。");
}else if(id > 4 && id < 8){
throw new NullPointerException("NullPointerException, id没有对应的记录,空指针异常");
}
return result;
}

public CommonResult<Payment> handleFallback(@PathVariable("id") Long id, Throwable e){
Payment payment = new Payment(id, "null");
return new CommonResult<Payment>(444, "fallback异常, 异常内容:"+ e.getMessage(), payment);
}


}


3、测试访问:http://localhost:84/consumer/fallback/1





负载均衡配置完成。


4、测试访问:http://localhost:84/consumer/fallback/4




5、测试访问:http://localhost:84/consumer/fallback/5




II.BLOCKEXCEPTION


1、服务提供者接口不变


package com.laoxu.springcloud.controller;

import com.laoxu.springcloud.entities.CommonResult;
import com.laoxu.springcloud.entities.Payment;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;

@RestController
public class PaymentController {

@Value("${server.port}")
public String serverPort;

public static HashMap<Long, Payment> hashMap = new HashMap<Long, Payment>();
static
{
hashMap.put(1L, new Payment(1L, "a"));
hashMap.put(2L, new Payment(2L, "b"));
hashMap.put(3L, new Payment(3L, "c"));
}

@GetMapping("/paymentSQL/{id}")
public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id){
Payment payment = hashMap.get(id);
CommonResult<Payment> result = new CommonResult<Payment>(200, "from mysql, serverPort: " + serverPort, payment);
return result;
}

}



2、消费者改变


package com.laoxu.springcloud.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.laoxu.springcloud.entities.CommonResult;
import com.laoxu.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@Slf4j
public class CircleBreakerController {

public static final String SERVICE_URL = "http://nacos-payment-provider";

@Autowired
private RestTemplate restTemplate;

@RequestMapping("/consumer/fallback/{id}")
// @SentinelResource(value = "fallback", fallback = "handleFallback")
@SentinelResource(value = "fallback", blockHandler = "blockHandler")
public CommonResult<Payment> fallback(@PathVariable("id") Long id){
CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/" + id, CommonResult.class);
if(id == 4){
throw new IllegalArgumentException("IllegalArgumentException, 非法参数异常。。。");
}else if(id > 4 && id < 8){
throw new NullPointerException("NullPointerException, id没有对应的记录,空指针异常");
}
return result;
}

public CommonResult<Payment> handleFallback(@PathVariable("id") Long id, Throwable e){
Payment payment = new Payment(id, "null");
return new CommonResult<Payment>(444, "fallback异常, 异常内容:"+ e.getMessage(), payment);
}
public CommonResult<Payment> blockHandler(@PathVariable Long id, BlockException exception){
Payment payment = new Payment(id, "null");
return new CommonResult<Payment>(445, "blockHandler-sentinel限流, 无此流水 异常内容:"+ exception.getMessage(), payment);
}

}


3、配置sentinel限流




4、测试访问:http://localhost:84/consumer/fallback/4


会看到error page,java运行报错页面,blockException只管配置违规,不管java报错





当2s内访问次数超过2次那么触发blockException





III.BLOCKEXCEPTION && FALLBACK


1、服务提供者接口不变


package com.laoxu.springcloud.controller;

import com.laoxu.springcloud.entities.CommonResult;
import com.laoxu.springcloud.entities.Payment;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;

@RestController
public class PaymentController {

@Value("${server.port}")
public String serverPort;

public static HashMap<Long, Payment> hashMap = new HashMap<Long, Payment>();
static
{
hashMap.put(1L, new Payment(1L, "a"));
hashMap.put(2L, new Payment(2L, "b"));
hashMap.put(3L, new Payment(3L, "c"));
}

@GetMapping("/paymentSQL/{id}")
public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id){
Payment payment = hashMap.get(id);
CommonResult<Payment> result = new CommonResult<Payment>(200, "from mysql, serverPort: " + serverPort, payment);
return result;
}

}


2、消费者改变


package com.laoxu.springcloud.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.laoxu.springcloud.entities.CommonResult;
import com.laoxu.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@Slf4j
public class CircleBreakerController {

public static final String SERVICE_URL = "http://nacos-payment-provider";

@Autowired
private RestTemplate restTemplate;

@RequestMapping("/consumer/fallback/{id}")
// @SentinelResource(value = "fallback", fallback = "handleFallback")
// @SentinelResource(value = "fallback", blockHandler = "blockHandler")
@SentinelResource(value = "fallback", fallback = "handleFallback", blockHandler = "blockHandler")
public CommonResult<Payment> fallback(@PathVariable("id") Long id){
CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/" + id, CommonResult.class);
if(id == 4){
throw new IllegalArgumentException("IllegalArgumentException, 非法参数异常。。。");
}else if(id > 4 && id < 8){
throw new NullPointerException("NullPointerException, id没有对应的记录,空指针异常");
}
return result;
}

public CommonResult<Payment> handleFallback(@PathVariable("id") Long id, Throwable e){
Payment payment = new Payment(id, "null");
return new CommonResult<Payment>(444, "fallback异常, 异常内容:"+ e.getMessage(), payment);
}
public CommonResult<Payment> blockHandler(@PathVariable Long id, BlockException exception){
Payment payment = new Payment(id, "null");
return new CommonResult<Payment>(445, "blockHandler-sentinel限流, 无此流水 异常内容:"+ exception.getMessage(), payment);
}

}


3、配置sentinel限流




4、测试访问:http://localhost:84/consumer/fallback/4


当没有达到限流规则的条件的情况下,走fallback异常






当达到限流规则的条件的情况下,走blockException异常




结论:sentinel平台违规优先级大于java报错



5、异常忽略


  • 修改接口

异常忽略:exceptionsToIgnore = IllegalArgumentException.class

加上后,出现IllegalArgumentException后不会走handleFallback


@RestController
@Slf4j
public class CircleBreakerController {

public static final String SERVICE_URL = "http://nacos-payment-provider";

@Autowired
private RestTemplate restTemplate;

@RequestMapping("/consumer/fallback/{id}")
// @SentinelResource(value = "fallback", fallback = "handleFallback")
// @SentinelResource(value = "fallback", blockHandler = "blockHandler")
// @SentinelResource(value = "fallback", fallback = "handleFallback", blockHandler = "blockHandler")
@SentinelResource(value = "fallback", fallback = "handleFallback",
blockHandler = "blockHandler", exceptionsToIgnore = IllegalArgumentException.class)
public CommonResult<Payment> fallback(@PathVariable("id") Long id){
CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/" + id, CommonResult.class);
if(id == 4){
throw new IllegalArgumentException("IllegalArgumentException, 非法参数异常。。。");
}else if(id > 4 && id < 8){
throw new NullPointerException("NullPointerException, id没有对应的记录,空指针异常");
}
return result;
}

public CommonResult<Payment> handleFallback(@PathVariable("id") Long id, Throwable e){
Payment payment = new Payment(id, "null");
return new CommonResult<Payment>(444, "fallback异常, 异常内容:"+ e.getMessage(), payment);
}
public CommonResult<Payment> blockHandler(@PathVariable Long id, BlockException exception){
Payment payment = new Payment(id, "null");
return new CommonResult<Payment>(445, "blockHandler-sentinel限流, 无此流水 异常内容:"+ exception.getMessage(), payment);
}

}



6、测试访问:http://localhost:84/consumer/fallback/4







相关推荐

评论 抢沙发

表情

分类选择