在 上篇博客,我們完成了項目的基本搭建工作,那這篇博客就來實現(xiàn)一下微服務的熔斷和降級。
1. 熔 斷
1.1 發(fā)生場景
在前面,我們用 springcloud-service-consumer 這個服務消費者調用 springcloud-service-provider 這個服務提供者的接口,現(xiàn)在我們假設一種情況,如果某天服務提供者宕機了,它的服務器壞掉不能及時為服務消費者提供正常服務,那會發(fā)生什么情況?大概是服務消費者調不通接口,它的日志會一堆報錯,前端頁面也會報錯,如果流量大,整個系統(tǒng)可能會發(fā)生雪崩,將正常的服務消費者的服務也壓垮掉。
面對這樣的情況,我們就需要做熔斷處理了,將不可用的服務提供者,暫時從整個系統(tǒng)中斷開,以保證系統(tǒng)其它服務的正??捎?。
1.2 熔斷實現(xiàn)
將服務提供者從系統(tǒng)中斷開后,原來服務消費者調用服務提供者的接口,改為由服務消費者自身直接返回結果。下面,我們在 springcloud-service-consumer 這個服務消費者中具體實現(xiàn)一下。
第一步,引入依賴
實現(xiàn)熔斷,需要用到一個組件 Hystrix ,由于我這里用到的 openFeign 是 3.0.2 這個版本的,它沒有集成 Hystrix ,所以需要額外在 springcloud-service-consumer 的 pom.xml 文件中加入對 Hystrix 的依賴。
<!-- 增加hystrix依賴 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>
第二步,在properties配置文件中加配置
在 application.properties 配置文件中加入配置,以開啟熔斷支持
#開啟服務熔斷支持
feign.circuitbreaker.enabled=true
第三步,在啟動類加上注解
在 SpringCloudServiceConsumerApplication.java 這個啟動類上,加上注解 @EnableHystrix ,開啟支持。
package com.yuhuofei;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* @Description
* @ClassName SpringCloudServiceConsumerApplication
* @Author yuhuofei
* @Date 2023/5/22 18:59
* @Version 1.0
*/
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrix
public class SpringCloudServiceConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudServiceConsumerApplication.class, args);
}
}
第四步,新建一個接口實現(xiàn)類
新建一個接口實現(xiàn)類 FeignServiceApiImpl.java 實現(xiàn)接口 FeignServiceApi.java ,內容如下所示
package com.yuhuofei.api;
import com.yuhuofei.entity.PersonInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* @Description 接口回調實現(xiàn)類
* @ClassName FeignServiceApiImpl
* @Author yuhuofei
* @Date 2023/6/18 11:12
* @Version 1.0
*/
@Service
@Slf4j
public class FeignServiceApiImpl implements FeignServiceApi {
@Override
public List<PersonInfo> queryAllUser() {
PersonInfo personInfo = new PersonInfo();
personInfo.setId(0);
personInfo.setName("服務暫時不可用,請稍后再試");
personInfo.setPassWord("000000");
List<PersonInfo> list = new ArrayList<>();
list.add(personInfo);
log.info("調用了熔斷實現(xiàn)類,熔斷返回信息{}", list);
return list;
}
}
第五步,更改接口注解信息
將接口 FeignServiceApi 的注解 @FeignClient(value = “springcloud-service-provider”) 改為 @FeignClient(value = “springcloud-service-provider”, fallback = FeignServiceApiImpl.class)
package com.yuhuofei.api;
import com.yuhuofei.entity.PersonInfo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;
/**
* @Description feign調用服務提供者的接口
* @InterfaceName FeignServiceApi
* @Author yuhuofei
* @Date 2023/5/23 19:26
* @Version 1.0
*/
@Service
@FeignClient(value = "springcloud-service-provider", fallback = FeignServiceApiImpl.class)
public interface FeignServiceApi {
//調用服務提供者的接口
@GetMapping("/provider/user/list")
List<PersonInfo> queryAllUser();
}
到這里,所有的實現(xiàn)步驟就完成了,下面來測試一下結果。
1.3 熔斷測試
我們依次啟動注冊中心和服務消費者的服務,作為模擬服務提供者宕機,所以不用啟動服務提供者的服務。
在瀏覽器中,訪問 http://localhost:8002/consumer/person/list-by-openfeign ,我們可以看到,前端頁面能拿到做熔斷后返回的信息。
服務消費者的后端日志,也能正常打印出來,沒有報錯。
2. 降 級
2.1 發(fā)生場景
還是以服務消費者的接口為例,前端通過調用接口 http://localhost:8002/consumer/person/list-by-openfeign 來獲取列表信息,如果這個接口的邏輯處理比較復雜或者前端傳的參數(shù)出現(xiàn)特殊情況,導致這個接口響應很慢或者超時,而同時又有很多請求在訪問這個接口,并且這個接口又是后面所有業(yè)務流程的入口,那勢必會影響業(yè)務的正常開展,這是其一。其二則是在這種糟糕的情況下,不斷地請求還有可能會使系統(tǒng)奔潰,這種時候,就得考慮對這個接口做降級處理了。
2.2 降級處理
由于前面在 springcloud-service-consumer 這個服務消費者中,做熔斷的時候,已經(jīng)引入了 Hystrix 的依賴、在 properties 文件中加了配置、在啟動類上加了注解 @EnableHystrix
,所以這里就不需要重復做這幾步了。
接下來就是改造需要做降級的接口 http://localhost:8002/consumer/person/list-by-openfeign ,如下所示。
主要是在原來的 ConsumerController.java 類中做了兩步
- 第一步,新增了一個降級后的執(zhí)行方法 personListFallBackMethod
- 第二步,在原來的 getPersonListUseOpenFeign 方法上,新增一個注解 @HystrixCommand(fallbackMethod = “personListFallBackMethod”,
commandProperties = {@HystrixProperty(name = “execution.isolation.thread.timeoutInMilliseconds”, value = “1500”)}),表示這個接口如果超過 1500 毫秒沒有影響,則進行降級并調用降級后的方法。
package com.yuhuofei.controller;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.yuhuofei.api.FeignServiceApi;
import com.yuhuofei.entity.PersonInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.List;
/**
* @Description
* @ClassName ConsumerController
* @Author yuhuofei
* @Date 2023/5/23 18:55
* @Version 1.0
*/
@RestController
@RequestMapping("/consumer/person")
@Slf4j
public class ConsumerController {
public static final String PROVIDER_URL = "http://localhost:8001/";
@Autowired
private FeignServiceApi feignServiceApi;
@Autowired
private RestTemplate restTemplate;
@GetMapping("/list")
public List<PersonInfo> getPersonList() {
return restTemplate.getForObject(PROVIDER_URL + "provider/user/list", List.class);
}
//設置降級后回調方法,設置超時降級策略,超時時間1500毫秒
@HystrixCommand(fallbackMethod = "personListFallBackMethod",
commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")})
@GetMapping("/list-by-openfeign")
public List<PersonInfo> getPersonListUseOpenFeign() {
//為了模擬降級情況,設置線程睡眠2000毫秒
try {
Thread.sleep(2000);
} catch (Exception e) {
log.error("線程處理異常", e);
}
log.info("通過openfeign調用");
List<PersonInfo> list = feignServiceApi.queryAllUser();
log.info("得到的列表:{}",list);
return list;
}
//降級后,執(zhí)行的方法
private List<PersonInfo> personListFallBackMethod() {
PersonInfo personInfo = new PersonInfo();
personInfo.setId(-1);
personInfo.setName("正常服務暫時不可用,已進行降級處理,請稍后再試");
personInfo.setPassWord("111111");
List<PersonInfo> list = new ArrayList<>();
list.add(personInfo);
log.info("調用了降級后的方法,降級后返回信息{}", list);
return list;
}
}
2.3 降級測試
一切改造工作完成后,我們依次啟動注冊中心、服務消費者的服務,然后在瀏覽器中調用 http://localhost:8002/consumer/person/list-by-openfeign 。
瀏覽器中,展示結果如下:
查看服務消費者的日志打印情況:
這里分析一下,先是打印線程處理異常,然后繼續(xù)往下執(zhí)行,打印通過openfeign調用,超時了,調用降級后要執(zhí)行的方法并返回結果給前端,后端由于不是阻塞的,所以繼續(xù)執(zhí)行調用服務提供者的接口,調不通,最后走到了熔斷類里面,流程上沒問題,符合預期。文章來源:http://www.zghlxwxcb.cn/news/detail-704680.html
需要提一句的是,微服務的熔斷和降級,無論是在服務消費者中還是服務提供者里面,都可以做都可以去實現(xiàn),我這里只是以服務消費者為例進行了實現(xiàn)。文章來源地址http://www.zghlxwxcb.cn/news/detail-704680.html
到了這里,關于【SpringCloud】2.微服務的熔斷和降級的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!