Feign
- 什麼是Feign
Feign 與Ribbon 一樣,Feign也是有Netflix 提供的,Feign是一個聲明式、子產品化的Web Service 用戶端,它簡化了開發者編寫Web服務用戶端的操作,開發者可以通過簡單的接口和注解來調用HTTP API,Spring Cloud Feign,它整合了Ribbon 和Hystrix ,具有可插拔、基于注解、負載均衡、服務熔斷等一系列便捷功能。
相比較于Ribbon +RestTemplate 的方式,Feign 大大簡化了代碼的開發,Feign 支援多種注解,包括Feign 注解、JAX-RS注解、Spring MVC注解等,Spring Cloud 對Feign 進行了優化,整合了Ribbon 和Eureka ,進而讓Feign 的使用更加友善。
-
Ribbon 和Feign 的差別
1、 Fiegn 是一個聲明式的Web Service 用戶端。
2、支援Feign 注解、Spring MVC注解、JAX-RS注解。
3、Feign 基于Ribbon 實作,使用起來更加簡單。
4、Feign 內建了Hystrix ,具備服務熔斷的功能。
開啟Feign 的功能
1、建立新的Module ,命名為 feign ,pom.xml 添加以下依賴
<dependencies>
<!-- 都是作為服務注冊到Eureka Server ,是以需要添加這個依賴 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<!-- Feign 的依賴 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
2、 建立application.yml檔案
内容如下:
server:
port: 8050
spring:
application:
name: feign
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
3、建立啟動類,并添加上Feign相關的注解
啟動類名稱取名為FeignApplication
代碼如下:
package com.southwind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class FeignApplication {
public static void main(String[] args){
SpringApplication.run(FeignApplication.class,args);
}
}
4、因為還需要繼續操作第一篇文章建的學生實體類,是以需要把原來的實體類代碼複制過來
Student 類:
package com.southwind.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor //無參構造
@AllArgsConstructor //有參構造
public class Student {
private long id;
private String name;
private int age;
}
目錄結構如下:
4、 建立一個名叫 FeignProviderClient 的接口 放在com.southwind.feign 包裡
FeignProviderClient 代碼如下:
```java
package com.southwind.feign;
import com.southwind.entity.Student;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Collection;
//這裡就展現了Feign 的聲明式調用,都是接口,
//value = provider是因為提供者在注冊中心的名字叫做 provider
@FeignClient(value = "provider")
public interface FeignProviderClient {
/* 需要調用提供者的controller 裡面的方法,直接就行(有
* 點相當于它自己就會把provider 替換成IP位址,然後把Mapping 裡面的值給拼接
* 到後面,實作子產品間的調用。)
*/
@GetMapping("/student/findAll")
public Collection<Student> findAll();
@GetMapping("/student/index")
public String index();
}
5、建立controller ,命名為FeignHandler.java ,存放在com.southwind.controller 檔案夾裡
package com.southwind.controller;
import com.southwind.entity.Student;
import com.southwind.feign.FeignProviderClient;
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 java.util.Collection;
@RestController
@RequestMapping("/feign")
public class FeignHandler {
@Autowired
private FeignProviderClient feignProviderClient;
@GetMapping("/findAll")
public Collection<Student> findAll(){
return feignProviderClient.findAll();
}
@GetMapping("/index")
public String index(){
return feignProviderClient.index();
}
}
6、啟動注冊中心eruekaserver,然後與上一篇文章一樣,一個工程啟動兩個不同端口的提供者服務,啟動eurekaclient,然後啟動feign 工程
7、在浏覽器輸入:localhost:8050/feign/index
Feign 聲明式調用 也可以實作了負載均衡,并且比用zuul 網關的方法,簡化了代碼,更友善。
使用Feign 實作服務的熔斷
什麼是熔斷。
當微服務處理秒殺場景,或者類似場景,導緻通路伺服器并發量特别大的時候,有可能一個服務崩了,導緻調用它的服務因為長時間等不到該服務的響應繼而也發生崩潰,以此類推,導緻“雪崩效應”。這時候熔斷器發揮了作用,他像電路的熔斷器一樣,一旦電流超過了最大電流,熔斷器就斷電,防止漏電和觸電事件的發生。當某一個服務一直調用不無響應時,熔斷器啟動,暫時停止通路該服務,并且傳回一個熔斷處理的結果,告知使用者稍後再試。等待當機的服務重新恢複正常。待服務可以正常通路後,熔斷器自動關閉。
1、在原來feign 工程的yml檔案,添加feign熔斷開啟的代碼。
server:
port: 8050
spring:
application:
name: feign
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
feign:
hystrix:
enabled: true
feign.hystrix.enabled:true 是否開啟熔斷器
2、建立FeignProviderClient 的實作類FeignError, 定義容錯處理邏輯,通過@Component 注解将FeignError執行個體注入IoC容器中。
FeignError 代碼:
package com.southwind.feign.impl;
import com.southwind.entity.Student;
import com.southwind.feign.FeignProviderClient;
import org.springframework.stereotype.Component;
import java.util.Collection;
@Component
public class FeignError implements FeignProviderClient {
@Override
public Collection<Student> findAll() {
return null;
}
//當熔斷開啟時,停止對該服務的通路,然後調用此方法告知使用者系統繁忙
@Override
public String index() {
return "伺服器維護中.....";
}
}
3、在FeignProviderClient 定義處通過 @FeignClient 的fallback 屬性設映射,降級處理。
在FeignProviderClient 中,增加降級處理(紅色框框部分)
這時候,一旦Feign 通路服務提供者,服務提供者不是正常狀态導緻feign 通路不成功的話,他自己就會找到feignError 裡面的fallback 方法進行處理。這樣,就不會出現網頁狀态碼,如500,404等,而是會出現你寫的fallback ,即熔斷處理的方法裡面。
4、測試
先把服務提供者停掉,這時候使用 feign 調用提供者 ,會報500,即伺服器沒有響應。
這時候重新啟動feign(開啟feign 熔斷後,還沒有生效,現在重新開機feign 使熔斷生效)
重新在浏覽器通路:localhost:8050/feign/index
成功啟動了熔斷器。因為提供者調不通,是以直接調用自己熔斷方法。