書接前文:
微服務(wù)間的遠(yuǎn)程接口調(diào)用:OpenFeign 的使用
當(dāng)項目中使用了?OpenFeign
?后,可以很方便的進(jìn)行遠(yuǎn)程服務(wù)調(diào)用,現(xiàn)在有個問題,假如遠(yuǎn)程服務(wù)出現(xiàn)故障了,調(diào)不了遠(yuǎn)程的接口,這邊又著急等著返回結(jié)果,怎么辦呢?
當(dāng)然是使用?服務(wù)降級?,本篇就使用?OpenFeign
?進(jìn)行遠(yuǎn)程調(diào)用,并結(jié)合?Sentinel
?對出現(xiàn)的異常、故障等問題進(jìn)行服務(wù)降級。
準(zhǔn)備
仍以前面?open-feign-service
?服務(wù)為調(diào)用方,?nacos-provider
?服務(wù)為提供方來進(jìn)行操練。
Jar 包依賴
Open-feign-service
?除了引入?spring-cloud-starter-openfeign
?外,再引入?spring-cloud-starter-alibaba-sentinel
?組件,另外我們這里使用?nacos
?的配置中心做?Sentinel
?限流規(guī)則的持久化,所以還需要引入?spring-cloud-alibaba-sentinel-datasource
?和?sentinel-datasource-nacos
?:
<!-- 引入二方庫 -->
<dependency>
<groupId>cn.chendapeng.springcloud</groupId>
<artifactId>internal-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
復(fù)制代碼
配置文件
配置文件?application.yml
?:
spring:
application:
name: open-feign-service
cloud:
nacos:
discovery:
server-addr: 192.168.242.112:81
sentinel:
transport:
dashboard: localhost:8080
port: 8719
# https://github.com/alibaba/Sentinel/issues/1213
web-context-unify: false
# Sentinel 規(guī)則持久化到 Nacos
datasource:
rule1:
nacos:
serverAddr: 192.168.242.112:81
groupId: DEFAULT_GROUP
dataId: sentinelFlowRule.json
ruleType: flow
feign:
client:
config:
# 默認(rèn)的超時時間設(shè)置
default:
connectTimeout: 5000
readTimeout: 5000
# 在指定的 FeignClient 設(shè)置超時時間,覆蓋默認(rèn)的設(shè)置
nacos-provider:
connectTimeout: 1000
readTimeout: 1000
loggerLevel: full
# 激活 Sentinel
sentinel:
enabled: true
復(fù)制代碼
這里增加了?Sentinel
?的數(shù)據(jù)持久化內(nèi)容,以及激活?OpenFeign
?與?Sentinel
?聯(lián)合使用的?feign.sentinel.enabled=true
?配置。
全局統(tǒng)一異常處理
不管是?Sentinel
?限流后返回,還是?OpenFeign
?的?fallback
?返回,本質(zhì)上他們都是出現(xiàn)異常了,這里配置一下全局的統(tǒng)一異常處理。
首先,增加一個業(yè)務(wù)異常類:
public class BusinessException extends RuntimeException {
private String code;
private String message;
public BusinessException(String code, String message) {
this.code = code;
this.message = message;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
復(fù)制代碼
然后使用?Spring?的?@RestControllerAdvice?注解進(jìn)行全局的異常進(jìn)行處理:
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 業(yè)務(wù)異常,統(tǒng)一處理
* @param e 異常對象
* @return ResponseResult 全局異常響應(yīng)
*/
@ExceptionHandler(BusinessException.class)
public ResponseResult<String> businessException(BusinessException e) {
LOGGER.info("code={}, message={}", e.getCode(), e.getMessage());
return ResponseResult.fail(e.getCode(), e.getMessage());
}
// 其他異常...
}
復(fù)制代碼
這樣,只要指定了拋出的異常類型,就會返回統(tǒng)一的響應(yīng)格式。
操練
@FeignClient 的 fallback
在上一篇文章中,我們通過?FeignClient
?接口調(diào)用遠(yuǎn)程的服務(wù):
@Service
@FeignClient("nacos-provider")
public interface ProductService {
/**
* 調(diào)用遠(yuǎn)程服務(wù) nacos-provider 的 product/{id} 接口
* @param id 參數(shù) id
* @return 返回
*/
@GetMapping("/product/{id}")
String getProductById(@PathVariable("id") Long id);
}
復(fù)制代碼
如果遠(yuǎn)程接口不通,這里可以在?@FeignClient?注解上增加一個屬性?fallback?,該屬性定義一個容錯的處理類,當(dāng)調(diào)用遠(yuǎn)程接口失敗或超時時,會調(diào)用對應(yīng)接口的容錯邏輯,fallback?指定的類必須實(shí)現(xiàn)?@FeignClient?標(biāo)記的接口。
先來定義一個實(shí)現(xiàn)?ProductService
?的類:
@Component
@Slf4j
public class ProductServiceImpl implements ProductService {
/**
* 調(diào)用遠(yuǎn)程服務(wù) nacos-provider 的 product/{id} 接口失敗后的處理方法
*
* @param id 參數(shù) id
* @return 返回
*/
@Override
public String getProductById(Long id) {
log.error("調(diào)用接口 getProduct 失敗,id={}", id);
//return "OpenFeign 降級";
throw new BusinessException(ResponseCode.RPC_ERROR.getCode(), ResponseCode.RPC_ERROR.getMessage());
}
}
復(fù)制代碼
該類需要被?Spring?識別,所以加個?@Component?。該類的實(shí)現(xiàn)方法可以添加實(shí)際業(yè)務(wù)的處理邏輯,本案例只是打印一些信息后直接拋出自定義的異常。
Tips?:ResponseCode.RPC_ERROR 在二方庫中有定義。
給?FeignClient?接口增加?fallback?屬性:
@FeignClient(name = "nacos-provider", fallback = ProductServiceImpl.class)
復(fù)制代碼
OK,不啟動服務(wù)提供方?nacos-provider
,直接調(diào)用接口測試。
接口返回:
控制臺打印信息:
這樣就實(shí)現(xiàn)了?fallback?的容錯處理,即時遠(yuǎn)程服務(wù)不可用,也能進(jìn)行降級處理。
@SentinelResource 限流
在 Controller 層使用 FeignClient 定義的接口進(jìn)行遠(yuǎn)程調(diào)用服務(wù)時,還可以定義 Sentinel 資源,并設(shè)置規(guī)則對資源進(jìn)行限流。
@SentinelResource?的一些使用方法在前幾篇文章中已有提及,這里再結(jié)合?OpenFeign
?使用,本例中有如下定義:
@GetMapping("/product/{id}")
@SentinelResource(value = "getProduct",
blockHandler = "getProductBlock",
fallback = "getProductFallback")
public String getProduct(@PathVariable("id") Long id) {
return productService.getProductById(id);
}
public String getProductBlock(Long id, BlockException e) {
log.error("訪問資源 getProduct 被限流,id={}", id);
throw new BusinessException("C0002", "訪問資源 getProduct 被限流");
}
public String getProductFallback(Long id) {
log.error("訪問資源 getProduct fallback");
return "請稍后重試";
}
復(fù)制代碼
在前面的準(zhǔn)備工作中,我們已經(jīng)配置了 Sentinel 資源限流規(guī)則持久化到 Nacos,現(xiàn)在 Nacos 中配置一下資源?getProduct
?的限流規(guī)則:
[
{
"resource": "getProduct",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
復(fù)制代碼
限流規(guī)則是 QPS 閾值為1,只要我1秒大于1次請求就會被限流。
啟動遠(yuǎn)程服務(wù)?nacos-provider
?,下面來驗證一下。
1秒只發(fā)一個請求的結(jié)果:
1秒內(nèi)快速刷新幾次,造成QPS大于1,將會被限流:文章來源:http://www.zghlxwxcb.cn/news/detail-410866.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-410866.html
小結(jié)
-
OpenFeign
?整合?Sentinel
?需要引入?Sentinel
?相關(guān)依賴包; - 在配置文件通過?
feign.sentinel.enabled=true
?來開啟 Feign 與 Sentinel的結(jié)合使用; - 在?@FeignClient?注解中增加?
fallback
?屬性,該屬性定義遠(yuǎn)程接口訪問有問題時的容錯處理邏輯的類; -
fallback
?定義的類需實(shí)現(xiàn)?@FeignClient?定義的接口。
到了這里,關(guān)于強(qiáng)強(qiáng)聯(lián)合:OpenFeign 整合 Sentinel的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!