天天看點

開啟一個spring cloud 工程 -第六步Feign 聲明式接口調用以及使用Hystrix的熔斷實作

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;

}
           

目錄結構如下:

開啟一個spring cloud 工程 -第六步Feign 聲明式接口調用以及使用Hystrix的熔斷實作

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

開啟一個spring cloud 工程 -第六步Feign 聲明式接口調用以及使用Hystrix的熔斷實作
開啟一個spring cloud 工程 -第六步Feign 聲明式接口調用以及使用Hystrix的熔斷實作
開啟一個spring cloud 工程 -第六步Feign 聲明式接口調用以及使用Hystrix的熔斷實作
開啟一個spring cloud 工程 -第六步Feign 聲明式接口調用以及使用Hystrix的熔斷實作

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容器中。

開啟一個spring cloud 工程 -第六步Feign 聲明式接口調用以及使用Hystrix的熔斷實作

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 中,增加降級處理(紅色框框部分)

開啟一個spring cloud 工程 -第六步Feign 聲明式接口調用以及使用Hystrix的熔斷實作

這時候,一旦Feign 通路服務提供者,服務提供者不是正常狀态導緻feign 通路不成功的話,他自己就會找到feignError 裡面的fallback 方法進行處理。這樣,就不會出現網頁狀态碼,如500,404等,而是會出現你寫的fallback ,即熔斷處理的方法裡面。

4、測試

先把服務提供者停掉,這時候使用 feign 調用提供者 ,會報500,即伺服器沒有響應。

開啟一個spring cloud 工程 -第六步Feign 聲明式接口調用以及使用Hystrix的熔斷實作

這時候重新啟動feign(開啟feign 熔斷後,還沒有生效,現在重新開機feign 使熔斷生效)

重新在浏覽器通路:localhost:8050/feign/index

開啟一個spring cloud 工程 -第六步Feign 聲明式接口調用以及使用Hystrix的熔斷實作

成功啟動了熔斷器。因為提供者調不通,是以直接調用自己熔斷方法。