- SpringCloud 學習總結(一)
- SpringCloud 學習總結(二)
服務容錯保護Hystrix
Hystix是Netflix開源的一個延遲和容錯庫,其中提供了基礎的熔斷功能,用于隔離訪問遠程服務、第三方庫,防止出現級聯失敗,關于Hystrix更詳細的原理,可以參考官方檔案:https://github.com/Netflix/Hystrix/

雪崩問題: 在微服務框架中,系統間都通過微服務進行呼叫,在微服務之間會存在這相互依賴關系,假設每個微服務運行在不同的行程中,依賴的呼叫只則需要使用遠程呼叫方式,如果其中一個網路出現問題,或者延遲,此時,呼叫方式在不斷的呼叫,后方的依賴會出現故障,當回應過多時,就可能出現雪崩效應,造成系統的崩潰,
下圖中,我們可以看到微服務中,服務間復雜的呼叫關系,一個請求,可能需要呼叫多個微服務介面才能實作,會形成非常復雜的呼叫鏈路:

如圖,一次業務請求,需要呼叫A、P、H、I四個服務,這四個服務又可能呼叫其它服務,如果此時,某個服務出現例外:

例如:微服務I發生例外,請求阻塞,用戶不會得到回應,則tomcat的這個執行緒不會釋放,于是越來越多的用戶請求到來,越來越多的執行緒會阻塞:

服務器支持的執行緒和并發數有限,請求一直阻塞,會導致服務器資源耗盡,從而導致所有其它服務都不可用,形成雪崩效應,
Hystix解決雪崩問題:
- 執行緒隔離(服務降級)
- 服務熔斷
服務降級
服務降級: 當系統的訪問量突然特別大時,因為資源有限,不可能提供全部服務的時候,優先保證核心服務,非核心服務不可用或者弱可用,
在Hystrix中也提供了服務降級的機制,Hystrix為每個依賴服務呼叫分配一個小的執行緒池,如果執行緒池已滿呼叫將被立即拒絕,默認不采用排隊,加速失敗判定時間,用戶的請求將不再直接訪問服務,而是通過執行緒池中的空閑執行緒來訪問服務,如果執行緒池已滿,或者請求超時,則會進行降級處理,
通過服務降級,用戶的請求故障時,不會被阻塞,更不會無休止的等待或者看到系統崩潰,至少可以看到一個執行結果(例如回傳友好的提示資訊),服務降級雖然會導致請求失敗,但是不會導致阻塞,而且最多會影響這個依賴服務對應的執行緒池中的資源,對其它服務沒有回應,
觸發Hystix服務降級的情況:
- 執行緒池已滿
- 請求超時
Hystrix將降級策略封裝在Commend中,不同的Commend根據group分割開,Commend內置了run和fallback兩個方法,內置方法,正常情況下,會先執行run方法(正常執行邏輯),若發生了故障,再執行fallback方法并回傳其結果,若發生多次故障會在一定時間范圍內觸發短路,即跳過run方法,直接執行fallback方法,
在程式中測驗Hystrix:
引入依賴:首先在springboot-service-consumer的pom.xml中引入Hystrix依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
修改啟動器的代碼:添加開啟熔斷注解:@EnableCircuitBreaker
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker //開啟熔斷
public class SpringbootServiceConsumerApplication {
、、、、
}
組合注解:@SpringCloudApplication,相當于@SpringBootApplication + @EnableDiscoveryClient + @EnableCircuitBreaker,可以用來簡化我們的注解:

使用組合注解代替之前的3個注解:
@SpringCloudApplication //組合注解,相當于@SpringBootApplication + @EnableDiscoveryClient + @EnableCircuitBreaker
public class SpringbootServiceConsumerApplication {
@Bean
@LoadBalanced //開啟負載均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(SpringbootServiceConsumerApplication.class, args);
}
}
撰寫降級邏輯:
改造springboot-service-consumer,當目標服務的呼叫出現故障,我們希望快速失敗,給用戶一個友好提示,因此需要提前撰寫好失敗時的降級處理邏輯,要使用@HystixCommond來完成:
@RestController
@RequestMapping("consumer/user")
public class UserController {
@Autowired
private RestTemplate restTemplate;
@GetMapping
@HystrixCommand(fallbackMethod = "queryUserByIdFallback") //宣告熔斷(降級邏輯)的方法
public String queryUserById(@RequestParam("id") Long id) {
return this.restTemplate.getForObject("http://service-provider/user/" + id, String.class);
}
public String queryUserByIdFallBack(Long id){
return "請求繁忙,請稍后再試!";
}
}
注意:熔斷的降級邏輯方法必須跟正常邏輯方法保證:相同的引數串列和回傳值宣告,失敗邏輯中回傳User物件沒有太大意義,一般會回傳友好提示,所以我們把queryById的方法改造為回傳String,反正也是Json資料,這樣失敗邏輯中回傳一個錯誤說明,會比較方便,
運行測驗:
當springboot-service-provder正常提供服務時

將springboot-service-provider停機時,會發現頁面回傳了降級處理資訊:

指定全域熔斷的熔斷方法:
區域:(要和被熔斷的方法回傳值和引數串列一致)
@HystrixCommand(fallbackMethod=“區域熔斷方法名”):宣告被熔斷的方法
全域:(回傳值型別要被熔斷的方法一致,引數串列必須為空)
@DefaultProperties(defaultFallback = “defaultFallBack”):在類上指明統一的失敗降級方法
defaultFallback:默認降級方法,不用任何引數,以匹配更多方法,但是回傳值一定一致
@HystrixCommand:在方法上直接使用該注解,使用默認的剪輯方法,
優先級:區域>全域
我們剛才把fallback寫在了某個業務方法上,如果這樣的方法很多,那豈不是要寫很多,所以我們可以把Fallback配置加在類上,實作默認fallback:
@RestController
@RequestMapping("consumer/user")
@DefaultProperties(defaultFallback = "fallBackMethod") // 指定一個類的全域熔斷方法
public class UserController {
@Autowired
private RestTemplate restTemplate;
@GetMapping
@HystrixCommand // 標記該方法需要熔斷
public String queryUserById(@RequestParam("id") Long id) {
String user = this.restTemplate.getForObject("http://service-provider/user/" + id, String.class);
return user;
}
/**
* 熔斷方法
* 回傳值要和被熔斷的方法的回傳值一致
* 熔斷方法不需要引數
* @return
*/
public String fallBackMethod(){
return "服務器正忙,請稍后再試!";
}
}

設定超時
在微服務中,由于網路或者運算量等問題,超時是很常見的,Hystix中的默認超時時長為1,在互聯網中,有些服務需要訪問第三方應用,或者處理大量的資料,使用默認的1秒很容易超時,這時需要問們進行超時設定,通過hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds可以設定Hystrix超時時間,該配置沒有提示:
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000 # 設定hystrix的超時時間為6000ms
改造服務提供者
改造服務提供者的UserController介面,隨機休眠一段時間,以觸發熔斷:
@GetMapping("{id}")
public User queryUserById(@PathVariable("id") Long id) {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return this.userService.queryUserById(id);
}
運行查看結果:

服務熔斷
熔斷原理:熔斷器(斷路器),當某些服務反應慢或者存在大量超時問題時,服務呼叫方可以自己進行判斷,并進行熔斷,防止整個系統被拖垮,當情況好轉時,在進行自動重連,
通過斷路器的方式,可以將后續請求直接拒絕掉,一段時間之后允許部分請求通過,如果呼叫成功則回到電路閉合狀態,否則繼續斷開,
熔斷狀態機3個狀態:
- Closed:關閉狀態,所有請求都正常訪問,
- Open:打開狀態,所有請求都會被降級,Hystix會對請求情況計數,當一定時間內失敗請求百分比達到閾值,則觸發熔斷,斷路器會完全打開,默認失敗比例的閾值是50%,請求次數最少不低于20次,
- Half Open:半開狀態,open狀態不是永久的,打開后會進入休眠時間(默認是5S),隨后斷路器會自動進入半開狀態,此時會釋放部分請求通過,若這些請求都是健康的,則會完全關閉斷路器,否則繼續保持打開,再次進行休眠計時
在程式中測驗:
在consumer的呼叫業務中加入一段邏輯:
@GetMapping
@HystrixCommand(fallbackMethod = "queryUserByIdFallback") //宣告熔斷的方法
public String queryUserById(@RequestParam("id") Long id) {
if(id==1){
throw new RuntimeException();
}
return this.restTemplate.getForObject("http://service-provider/user/" + id, String.class);
}
這樣如果引數是id為1,一定失敗,其它情況都成功,(不要忘了清空service-provider中的休眠邏輯)
當我們連續訪問id為1的請求時(超過20次,手速要快),就會觸發熔斷,斷路器會斷開,一切請求都會被降級處理,此時你訪問id為2的請求,會發現回傳的也是失敗,而且失敗時間很短,只有幾毫秒左右:
第一次訪問id=2:

連續訪問id=1:

再次訪問id=2:

不過,默認的熔斷觸發要求較高,休眠時間窗較短,為了測驗方便,我們可以通過配置修改熔斷策略:
circuitBreaker:
requestVolumeThreshold: 10 #觸發熔斷的最小請求次數,默認20
sleepWindowInMilliseconds: 10000 #觸發熔斷的失敗請求最小占比,默認50%
errorThresholdPercentage: 50 #休眠時長,默認是5000毫秒
宣告式服務呼叫Feign
Feign是Netfix開發的宣告式、模板化的HTTP客戶端,它可幫助我們更加快捷的呼叫HTTP API,其中支持自帶的注解,JAX-Rs注解,SpringMVC注解,并且還整合了Ribbon與Eureka,通過使用Feign可以把Rest的請求進行隱藏,偽裝成類似SpringMVC的Controller一樣,你不用再自己拼接url,拼接引數等等操作,一切都交給Feign去做,十分方便,
Feign專案地址:https://github.com/OpenFeign/feign
在前面的學習中,我們使用了Ribbon的負載均衡功能,大大簡化了遠程呼叫時的代碼:
String user = this.restTemplate.getForObject("http://service-provider/user/" + id, String.class);
快速入門:
改造springboot-service-consumer工程:

匯入依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
開啟Feign功能:在啟動類上,添加注解,@EnableFeignClients開啟Feign功能
@SpringCloudApplication //組合注解,相當于@SpringBootApplication + @EnableDiscoveryClient + @EnableCircuitBreaker
@EnableFeignClients //啟用feign組件
public class SpringbootServiceConsumerApplication {
/*@Bean
@LoadBalanced //開啟負載均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}*/
public static void main(String[] args) {
SpringApplication.run(SpringbootServiceConsumerApplication.class, args);
}
}
洗掉RestTemplate:feign已經自動集成了Ribbon負載均衡的RestTemplate,所以,此處不需要再注冊RestTemplate,
配置Feign的客戶端:
在springboot-service-consumer工程中,添加UserClient介面:
//@FeignClient(value = "service-provider") // 標注該類是一個feign介面
@FeignClient(value = "service-provider",fallback = UserClientFallBack.class)
public interface UserClient {
@GetMapping("user/{id}")
User queryById(@PathVariable("id") Long id);
}
- 首先這是一個介面,Feign會通過動態代理,幫我們生成實作類,這點跟mybatis的mapper很像
@FeignClient,宣告這是一個Feign客戶端,類似@Mapper注解,同時通過value屬性指定服務名稱- 介面中的定義方法,完全采用SpringMVC的注解,Feign會根據注解幫我們生成URL,并訪問獲取結果
改造原來的呼叫邏輯,呼叫UserClient介面:
@RestController
@RequestMapping("consumer/user")
public class UserController {
@Autowired
private UserClient userClient;
@GetMapping
public String queryUserById(@RequestParam("id") Long id){
User user = this.userClient.queryUserById(id);
return user.toString();
}
}
啟動測驗:
訪問介面:

正常獲取到了結果,
負載均衡與Hystrix支持:
Feign中本身已經集成了Ribbon依賴和自動配置,因此我們不需要額外引入依賴,也不需要再注冊RestTemplate物件,
同時Feign默認也有對Hystrix的集成,只不過,默認情況下是關閉的,我們需要通過下面的引數來開啟:(在springboot-service-consumer工程添加配置內容):
feign:
hystrix:
enabled: true # 開啟Feign的熔斷功能
但是,Feign中的Fallback配置不像hystrix中那樣簡單了,首先,我們要定義一個類UserClientFallback,實作剛才撰寫的UserClient,作為fallback的處理類
@Component
public class UserClientFallBack implements UserClient {
@Override
public User queryUserById(Long id) {
User user = new User();
user.setUsername("服務器正忙,請稍后再試!!!");
return user;
}
}
然后在UserFeignClient中,指定剛才撰寫的實作類
@FeignClient(value = "service-provider", fallback = UserClientFallback.class) // 標注該類是一個feign介面
public interface UserClient {
@GetMapping("user/{id}")
User queryUserById(@PathVariable("id") Long id);
}
重啟測驗:

請求壓縮:
Spring Cloud Feign 支持對請求和回應進行GZIP壓縮,以減少通信程序中的性能損耗,通過下面的引數即可開啟請求與回應的壓縮功能:
feign:
compression:
request:
enabled: true # 開啟請求壓縮
response:
enabled: true # 開啟回應壓縮
同時,我們也可以對請求的資料型別,以及觸發壓縮的大小下限進行設定:
feign:
compression:
request:
enabled: true # 開啟請求壓縮
mime-types: text/html,application/xml,application/json # 設定壓縮的資料型別
min-request-size: 2048 # 設定觸發壓縮的大小下限
注:上面的資料型別、壓縮大小下限均為默認值,
Zuul網關
通過前面的學習,使用Spring Cloud實作微服務的架構基本成型,大致是這樣的:
- 使用Spring Cloud Netflix中的Eureka實作了服務注冊中心以及服務注冊與發現;
- 服務間通過Ribbon或Feign實作服務的消費以及均衡負載,
- 為了使得服務集群更為健壯,使用Hystrix的融斷機制來避免在微服務架構中個別服務出現例外時引起的故障蔓延,

在該架構中,我們的服務集群包含:內部服務Service A和Service B,他們都會注冊與訂閱服務至Eureka Server,而Open Service是一個對外的服務,通過均衡負載公開至服務呼叫方,我們把焦點聚集在對外服務這塊,直接暴露我們的服務地址,這樣的實作是否合理,或者是否有更好的實作方式呢?
我們可以將權限控制這樣的東西從我們的服務單元中抽離出去,而最適合這些邏輯的地方就是處于對外訪問最前端的地方,我們需要一個更強大一些的均衡負載器的服務網關,
服務網關是微服務架構中一個不可或缺的部分,通過服務網關統一向外系統提供REST API的程序中,除了具備服務路由、均衡負載功能之外,它還具備了權限控制等功能,Spring Cloud Netflix中的Zuul就擔任了這樣的一個角色,為微服務架構提供了前門保護的作用,同時將權限控制這些較重的非業務邏輯內容遷移到服務路由層面,使得服務集群主體能夠具備更高的可復用性和可測驗性,
Zuul網關官網:https://github.com/Netflix/zuul

Zuul加入后的架構

不管是來自于客戶端(PC或移動端)的請求,還是服務內部呼叫,一切對服務的請求都會經過Zuul這個網關,然后再由網關來實作 鑒權、動態路由等等操作,Zuul就是我們服務的統一入口,
快速入門
新建工程:


添加Zuul依賴:


工程目錄:

pom.xml檔案
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.11.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ly</groupId>
<artifactId>ly-zuul</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ly-zuul</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR9</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
新建application.yml檔案,撰寫配置
server:
port: 10010 #服務埠
spring:
application:
name: ly-zuul #指定服務名
撰寫引導類:
通過@EnableZuulProxy注解開啟Zuul的功能:
@SpringBootApplication
@EnableZuulProxy // 開啟網關功能
public class ItcastZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ItcastZuulApplication.class, args);
}
}
撰寫路由規則:
我們需要用Zuul來代理service-provider服務,先看一下控制面板中的服務狀態:

映射規則:
server:
port: 10010
spring:
application:
name: ly-zuul
zuul:
routes:
service-provider: /service-provider/** #路由名稱,可以隨便起,習慣上是服務名
path: /service-provider/** # 這里是映射路徑
url: http://localhost:8081 # 映射路徑對應的實際url地址
我們將符合path 規則的一切請求,都代理到 url引數指定的地址
本例中,我們將 /service-provider/**開頭的請求,代理到http://localhost:8081
啟動測驗:
訪問的路徑中需要加上配置規則的映射路徑,我們訪問:http://localhost:10010/service-provider/user/2

面向服務的路由
在剛才的路由規則中,我們把路徑對應的服務地址寫死了!如果同一服務有多個實體的話,這樣做顯然就不合理了,我們應該根據服務的名稱,去Eureka注冊中心查找 服務對應的所有實體串列,然后進行動態路由才對!
對ly-zuul工程修改優化,添加Eureka客戶端依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
添加Eureka配置,獲取服務資訊:
eureka:
client:
registry-fetch-interval-seconds: 5 # 獲取服務串列的周期:5s
service-url:
defaultZone: http://localhost:10086/eureka
開啟Eureka客戶端發現功能:
@SpringBootApplication
@EnableZuulProxy //啟用zuul網關組件
@EnableDiscoveryClient //啟用客戶端
public class LyZuulApplication {
public static void main(String[] args) {
SpringApplication.run(LyZuulApplication.class, args);
}
}
修改映射配置,通過服務名稱獲取:
因為已經有了Eureka客戶端,我們可以從Eureka獲取服務的地址資訊,因此映射時無需指定IP地址,而是通過服務名稱來訪問,而且Zuul已經集成了Ribbon的負載均衡功能,
zuul:
routes:
service-provider: # 這里是路由id,隨意寫
path: /service-provider/** # 這里是映射路徑
serviceId: service-provider # 指定服務名稱
啟動測驗:
再次啟動,這次Zuul進行代理時,會利用Ribbon進行負載均衡訪問:

路由配置的四種方式: (一般使用的是第三種)
zuul:
routes:
service-provider:
path: /service-provider/** #路由名稱,可以隨便起,習慣上是服務名
url: http://localhost:8081
zuul:
routes:
service-provider:
path: /service-provider/** #路由名稱,可以隨便起,習慣上是服務名
serviceId: service-provider #指定服務名
#而大多數情況下,路由名稱往往和服務名會寫成一樣的,因此Zuul就提供了一種簡化的配置語法:
zuul:
routes:
service-provider: /provider/** #路由名稱,可以隨便起,習慣上是服務名
-不用配置,默認就是服務id開頭路徑
-Zuul就指定了默認的路由規則:默認情況下,一切服務的映射路徑就是服務名本身
測驗第三種方法:使用prefix: /*配置虛擬路徑
zuul:
routes:
service-provider: /provider/** #路由名稱,可以隨便起,習慣上是服務名
prefix: /api #虛擬路徑

過濾器
Zuul作為網關的其中一個重要功能,就是實作請求的鑒權,而這個動作我們往往是通過Zuul提供的過濾器來實作的,
ZuulFilter:
ZuulFilter是過濾器的頂級父類,在這里我們看一下其中定義的4個最重要的方法:
public abstract ZuulFilter implements IZuulFilter{
abstract public String filterType();
abstract public int filterOrder();
boolean shouldFilter();// 來自IZuulFilter
Object run() throws ZuulException;// IZuulFilter
}
shouldFilter:回傳一個Boolean值,判斷該過濾器是否需要執行,回傳true執行,回傳false不執行,run:過濾器的具體業務邏輯,filterType:回傳字串,代表過濾器的型別,包含以下4種:pre:請求在被路由之前執行route:在路由請求時呼叫post:在route和errror過濾器之后呼叫error:處理請求時發生錯誤呼叫
filterOrder:通過回傳的int值來定義過濾器的執行順序,數字越小優先級越高,
過濾器執行生命周期:
這張是Zuul官網提供的請求生命周期圖,清晰的表現了一個請求在各個過濾器的執行順序,

正常流程:
- 請求到達首先會經過pre型別過濾器,而后到達route型別,進行路由,請求就到達真正的服務提供者,執行請求,回傳結果后,會到達post過濾器,而后回傳回應,
例外流程:
- 整個程序中,pre或者route過濾器出現例外,都會直接進入error過濾器,在error處理完畢后,會將請求交給POST過濾器,最后回傳給用戶,
- 如果是error過濾器自己出現例外,最終也會進入POST過濾器,將最終結果回傳給請求客戶端,
- 如果是POST過濾器出現例外,會跳轉到error過濾器,但是與pre和route不同的是,請求不會再到達POST過濾器了,
所有內置過濾器串列:

使用場景:
- 請求鑒權:一般放在pre型別,如果發現沒有訪問權限,直接就攔截了
- 例外處理:一般會在error型別和post型別過濾器中結合來處理,
- 服務呼叫時長統計:pre和post結合使用,
自定義過濾器:
接下來我們來自定義一個過濾器,模擬一個登錄的校驗,基本邏輯:如果請求中有access-token引數,則認為請求有效,放行,
定義過濾器類:
@Component
public class LoginFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
/**
* 執行順序,回傳值越小,優先級越高
* @return
*/
@Override
public int filterOrder() {
return 10;
}
/**
* 是否執行該過濾器
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 撰寫過濾器的業務邏輯
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
//初始化context背景關系物件,servlet spring
RequestContext context =RequestContext.getCurrentContext();
//獲取request物件
HttpServletRequest request =context.getRequest();
//獲取引數
String token =request.getParameter("token");
if(StringUtils.isBlank(token)){
//攔截,不轉發請求
context.setSendZuulResponse(false);
//回應狀態碼,401-身份未認證
context.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
//設定回應的提示
context.setResponseBody("request error!");
}
//回傳值為null,就代表該過濾器什么都不做
return null;
}
}
運行測驗:
沒有token引數時,訪問失敗:

添加token引數后:

負載均衡和熔斷:
Zuul中默認就已經集成了Ribbon負載均衡和Hystix熔斷機制,但是所有的超時策略都是走的默認值,比如熔斷超時時間只有1S,很容易就觸發了,因此建議我們手動進行配置:
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 2000 # 設定hystrix的超時時間為6000ms
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/233997.html
標籤:其他
