1. 程式人生 > 實用技巧 >openfeign + hystrix 實現遠端呼叫,配置熔斷、超時、多 name

openfeign + hystrix 實現遠端呼叫,配置熔斷、超時、多 name

1,前提條件

生產者和消費者兩個專案必須都註冊到同一個註冊中心

2,生產者

生產者無需特殊配置,只需要是一個正常的web專案並且提供可訪問的介面即可,介面示例如下

package com.hwq.data.base.client;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HomeClient {
    @GetMapping("/client/home/index")
    public String index() {
        return "Open Feign";
    }
}

3,消費者

1,pom.xml
<!-- 遠端呼叫 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-archaius</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-netflix-archaius</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- Hystrix 熔斷器 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-archaius</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-netflix-archaius</artifactId>
        </exclusion>
    </exclusions>
</dependency>
2,配置開啟熔斷功能
feign:
  hystrix:
    # 開啟熔斷器
    enabled: true
3,啟動類
package com.hwq.admin.back;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication  // 啟動 SpringBoot 專案
@EnableDiscoveryClient  // 啟動 服務發現客戶端 功能
@EnableFeignClients     // 啟動 遠端呼叫
public class AdminBackApp {

    public static void main(String[] args) {
        SpringApplication.run(AdminBackApp.class);
    }

}
4,FeignClient 介面
package com.hwq.admin.back.feign;

import com.hwq.admin.back.feign.impl.HomeFeignImpl;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

// 宣告為 feign 遠端呼叫,name:生產者專案名,fallback:發生錯誤或超時時的熔斷類
@FeignClient(name = "sc-web-data-base", fallback = HomeFeignImpl.class)
public interface HomeFeign {

    // 這裡的方法簽名要和生產者保持一致
    @GetMapping("/client/home/index")
    String index();

}
5,熔斷類

該類需要實現 FeignClient 介面,並且配置在 fallback 引數中

package com.hwq.admin.back.feign.impl;

import com.hwq.admin.back.feign.HomeFeign;
import org.springframework.stereotype.Component;

@Component
public class HomeFeignImpl implements HomeFeign {

    @Override
    public String index() {
        return "觸發熔斷";
    }

}
5,呼叫的控制層
package com.hwq.admin.back.controller;

import com.hwq.admin.back.feign.HomeFeign;
import com.hwq.admin.back.vo.ResultVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HomeController {

    // FeignClient 介面 可以直接注入使用
    @Autowired
    private HomeFeign homeFeign;

    @GetMapping("/home/feign")
    public ResultVO<String> fegin() {
        String index = homeFeign.index();
        return ResultVO.success("OK", index);
    }
    
}

4,測試

啟動專案後,訪問:http://localhost:2011/home/feign

我們關閉生產者,再次訪問觸發熔斷

5,超時配置

配置超時可有效防止因為程式效能問題導致的長時間無響應,並且造成執行緒池忙碌堵塞

feign:
  hystrix:
    # 開啟熔斷器,如果要採用
    enabled: true

ribbon:
  # 遠端請求呼叫的超時時間 5 秒
  ConnectTimeout: 5000
  # 連線後的等待處理的超時時間 30 分鐘
  ReadTimeout: 1800000
  # 最大重試次數,當註冊中心中可以找到服務,但是服務連不上時將會重試
  MaxAutoRetries: 0
  # 切換例項的重試次數
  MaxAutoRetriesNextServer: 0

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            # 觸發熔斷的超時時間
            timeoutInMilliseconds: 1801000
  • openfeign 是依賴於 ribbon 的,所以超時配置配置 ribbon
  • ribbon 配置下的項必須使用駝峰,使用中橫線會失效,雖然這看起來怪怪的
  • 重生次數建議設定為 0,否則會出現冪等性的問題,當然查詢的無所謂
  • 熔斷觸發的超時時間應該大於 (ConnectTimeout + ReadTimeout)* (總重試次數 + 1)
  • 總重試次數 = MaxAutoRetries * MaxAutoRetriesNextServer + 1

6,相同 name 配置

1,場景

我們在開發中常常會配置多個 feignclient 指向同一個服務,這必然導致這些介面的 name 屬性是形同的,但是啟動之後卻會出現如下異常:

2,原因

如果我們要建立多個具有相同名稱或URL的偽客戶端,以便它們指向同一臺伺服器,但每個客戶端具有不同的自定義配置,則必須使用的contextId屬性

3,解決辦法
package com.hwq.admin.back.feign;

import com.hwq.admin.back.feign.impl.HomeFeignImpl;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

// 宣告為 feign 遠端呼叫,name:生產者專案名,contextId: 唯一標識,fallback:發生錯誤或超時時的熔斷類
@FeignClient(name = "sc-web-data-base", contextId = "home", fallback = HomeFeignImpl.class)
public interface HomeFeign {

    // 這裡的簽名要和生產者保持一致
    @GetMapping("/client/home/index")
    String index();

}