成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

使用OpenFeign的五個步驟和七個高級功能

開發 前端
Feign是一個開源的Java庫,用于簡化Web請求的過程。Feign是一個流行的Java HTTP客戶端庫,具有多種優勢和特性,是開發基于HTTP的微服務和應用程序的不錯選擇。

什么是Feign?

Feign是一個開源的Java庫,用于簡化Web請求的過程。

它通過提供更高級別的抽象來簡化RESTful Web服務的實現,消除了樣板代碼的需要,使代碼庫更具可讀性和可維護性。

Feign是一個流行的Java HTTP客戶端庫,具有多種優勢和特性,是開發基于HTTP的微服務和應用程序的不錯選擇。

什么是聲明式HTTP客戶端?

聲明式HTTP客戶端是一種通過編寫Java接口來發起HTTP請求的方式。

Feign會根據我們提供的注解,在接口背后生成實際的實現。

為何使用Feign?

如果我們需要調用大量的API,手動編寫HTTP代碼或使用難以維護的代碼生成方式并不理想。

使用Feign,我們可以通過一個簡單的小接口來描述API,讓Feign在運行時解釋和實現該接口,這樣更加簡便且易于維護。

誰適合使用Feign?

如果我們在Java代碼中需要發起HTTP請求,并且不想編寫樣板代碼,或者不想直接使用像Apache httpclient這樣的庫,那么Feign是一個很好的選擇。

創建基本的Feign客戶端

步驟0:添加bom

我們依然使用feign-bom作為版本管理:

<project>
    ……
    <properties>
        <openfeign.version>13.4</openfeign.version>
    </properties>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>io.github.openfeign</groupId>
                <artifactId>feign-bom</artifactId>
                <version>${openfeign.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

步驟1:添加Feign依賴

引入feign-core:

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-core</artifactId>
</dependency>

步驟2:定義客戶端接口

該接口通常包含帶有Feign注解的方法聲明。

我們將為服務器上要調用的每個REST端點聲明一個客戶端接口方法,這些只是聲明,無需實現這些方法,Feign會為我們完成。方法簽名應包括HTTP方法以及所有必需的數據。

假設我們要定義一個表示計算器服務的接口,它有執行加法、減法、乘法和除法等計算的簡單API方法:

public interface CalculatorService {
    /**
     * 兩整數相加。
     *
     * @param firstNumber  第一個整數
     * @param secondNumber 第二個整數
     * @return 兩數之和
     */
    @RequestLine("POST /operations/add?firstNumber={firstNumber}&secondNumber={secondNumber}")
    Long add(@Param("firstNumber") Long firstNumber,
             @Param("secondNumber") Long secondNumber);

    /**
     * 兩整數相減。
     *
     * @param firstNumber  第一個整數
     * @param secondNumber 第二個整數
     * @return 兩數之差
     */
    @RequestLine("POST /operations/subtract?firstNumber={firstNumber}&secondNumber={secondNumber}")
    Long subtract(@Param("firstNumber") Long firstNumber,
                  @Param("secondNumber") Long secondNumber);

    /**
     * 兩整數相乘。
     *
     * @param firstNumber  第一個整數
     * @param secondNumber 第二個整數
     * @return 兩數之積
     */
    @RequestLine("POST /operations/multiply?firstNumber={firstNumber}&secondNumber={secondNumber}")
    Long multiply(@Param("firstNumber") Long firstNumber,
                  @Param("secondNumber") Long secondNumber);

    /**
     * 兩整數相除。
     *
     * @param firstNumber  第一個整數
     * @param secondNumber 第二個整數,不應為零
     * @return 兩數之商
     */
    @RequestLine("POST /operations/divide?firstNumber={firstNumber}&secondNumber={secondNumber}")
    Long divide(@Param("firstNumber") Long firstNumber,
                @Param("secondNumber") Long secondNumber);
}

@RequestLine定義了請求的HTTP方法和url模板,而@Param定義了一個模板變量。

?

不用擔心,稍后我們將詳細了解OpenFeign提供的注解。

步驟3:創建客戶端對象

我們使用Feign的builder()方法來準備客戶端:

final CalculatorService target = Feign
       .builder()
       .decoder(new JacksonDecoder())
       .target(CalculatorService.class, HOST);

準備客戶端的方式有很多種,具體取決于我們的需求。

上面給出的代碼片段只是準備客戶端的一種簡單方式。

我們注冊了用于解碼JSON響應的解碼器,解碼器可以根據服務返回的響應的內容類型進行更改,稍后我們將詳細了解解碼器。

步驟4:使用客戶端進行API調用

現在讓我們調用客戶端的add()方法:

final Long result = target.add(firstNumber, secondNumber);

與其他HTTP客戶端相比,使用Feign HTTP客戶端調用服務相當簡單。

Feign注解

OpenFeign使用一組注解來定義HTTP請求及其參數,常用的OpenFeign注解及其示例如下:

注解

描述

示例

@RequestLine

指定HTTP方法和路徑

@RequestLine("GET /resource/{id}")

@Headers

指定請求的HTTP頭

@Headers("Authorization: Bearer {token}")

@QueryMap

將查詢參數映射到請求

@QueryMap Map<String, Object> queryParams

@Body

發送特定對象作為請求體

@Body RequestObject requestObject

@Param

向請求添加查詢參數

@Param("id") long resourceId

@Path

替換路徑中的模板變量

@Path("id") long resourceId

@RequestHeader

向請求添加頭

@RequestHeader("Authorization") String authToken

@Headers

指定請求的其他頭

@Headers("Accept: application/json")

這些注解可以用來定義OpenFeign客戶端接口,使其易于使用OpenFeign與遠程服務進行交互。我們可以根據特定的API要求混合和匹配這些注解。

處理響應

Feign還提供了一種聲明式的API集成方法。

與手動編寫處理響應或錯誤的樣板代碼不同,Feign允許我們定義自定義處理程序并將其注冊到Feign構建器中。

這不僅減少了我們需要編寫的代碼量,還提高了可讀性和可維護性。

讓我們看一個解碼器的示例:

final CalculatorService target = Feign.builder()
       .encoder(new JacksonEncoder())
       .decoder(new JacksonDecoder())
       .target(CalculatorService.class, HOST);

這段給定的代碼片段展示了創建一個Feign客戶端,使用Jackson進行請求編碼和響應解碼:

  • encoder(new JacksonEncoder()):在這里,為Feign客戶端設置了一個JacksonEncoder。JacksonEncoder是Feign Jackson模塊的一部分,用于將Java對象編碼為JSON格式的HTTP請求體。當需要在請求體中發送對象時,這特別有用。
  • decoder(new JacksonDecoder()):同樣,為Feign客戶端設置了一個JacksonDecoder。JacksonDecoder負責將服務器的JSON響應解碼為Java對象,它將JSON響應反序列化為相應的Java對象。

處理錯誤

錯誤處理是構建健壯可靠應用程序的關鍵方面,尤其是在進行遠程API調用時。Feign提供了強大的功能來幫助有效地處理錯誤。

Feign讓我們對處理意外響應有更多的控制。我們可以通過構建器注冊一個自定義的ErrorDecoder。

final CalculatorService target = Feign.builder()
       .errorDecoder(new CalculatorErrorDecoder())
       .target(CalculatorService.class, HOST);

以下是一個錯誤處理的示例:

public class CalculatorErrorDecoder implements ErrorDecoder {
    private final ErrorDecoder defaultErrorDecoder = new Default();

    @Override
    public Exception decode(String methodKey, Response response) {
        ExceptionMessage message = null;
        try (InputStream bodyIs = response.body().asInputStream()) {
            ObjectMapper mapper = new ObjectMapper();
            message = mapper.readValue(bodyIs, ExceptionMessage.class);
        } catch (IOException e) {
            return new Exception(e.getMessage());
        }
        final String messageStr = message == null? "" : message.getMessage();
        switch (response.status()) {
            case 400:
                return new RuntimeException(messageStr.isEmpty()
                       ? "Bad Request"
                        : messageStr
                );
            case 401:
                return new RetryableException(response.status(),
                        response.reason(),
                        response.request().httpMethod(),
                        null,
                        response.request());
            case 404:
                return new RuntimeException(messageStr.isEmpty()
                       ? "Not found"
                        : messageStr
                );
            default:
                return defaultErrorDecoder.decode(methodKey, response);
        }
    }
}

所有HTTP狀態不在HTTP 2xx范圍內的響應,例如HTTP 400,都將觸發ErrorDecoder的decode()方法。

在這個重寫的decode()方法中,我們可以處理響應,將失敗包裝成自定義異常或執行任何其他處理。

我們甚至可以通過拋出RetryableException來再次重試請求,這將調用注冊的Retryer。Retryer將在高級技術部分詳細解釋。

高級技術

集成編碼器/解碼器

編碼器和解碼器分別用于對請求和響應數據進行編碼/解碼。我們根據請求和響應的內容類型選擇它們,例如,對于JSON數據可以使用Gson或Jackson。

以下是一個使用Jackson編碼器和解碼器的示例:

final CalculatorService target = Feign.builder()
       .encoder(new JacksonEncoder())
       .decoder(new JacksonDecoder())
       .target(CalculatorService.class, HOST);

更改HTTP客戶端

默認情況下,Feign使用其自帶的HTTP客戶端。將Feign的默認HTTP客戶端從原始的Apache HTTP Client更改為其他庫(如OkHttp)的主要動機是為了獲得更好的性能、改進的功能以及與現代HTTP標準更好的兼容性。

現在讓我們看看如何覆蓋HTTP客戶端:

final CalculatorService target = Feign.builder()
       .client(new OkHttpClient())
       .target(CalculatorService.class, HOST);

配置日志記錄器

SLF4JModule用于將Feign的日志記錄發送到SLF4J。通過SLF4J,我們可以輕松使用我們選擇的日志后端(Logback、Log4J等)。

以下是一個構建客戶端的示例:

final CalculatorService target = Feign.builder()
       .logger(new Slf4jLogger())
       .logLevel(Level.FULL)
       .target(CalculatorService.class, HOST);

要在Feign中使用SLF4J,需要將SLF4J模塊和我們選擇的SLF4J綁定添加到類路徑中,然后按照上述方式配置Feign使用Slf4jLogger。

配置請求攔截器

Feign中的請求攔截器允許我們在將HTTP請求發送到遠程服務器之前對其進行自定義和操作。它們可用于多種目的,例如添加自定義頭、日志記錄、身份驗證或請求修改。

以下是我們可能希望在Feign中使用請求攔截器的原因:

  • 身份驗證:我們可以使用請求攔截器向每個請求添加身份驗證令牌或憑據,例如添加帶有JWT令牌的“Authorization”頭。
  • 日志記錄:攔截器有助于記錄傳入和傳出的請求和響應,這對于調試和監控很有用。
  • 請求修改:我們可以在發送請求之前修改請求,包括更改頭、查詢參數甚至請求體。
  • 速率限制:通過檢查發出的請求數量來決定是否允許或阻止請求,從而實現速率限制。
  • 緩存:根據特定標準緩存請求/響應數據。

以下是一個演示如何使用請求攔截的代碼片段:

static class AuthorizationInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate template) {
        // 檢查令牌是否存在,如果不存在則添加它
        template.header("Authorization", "Bearer " + generatedToken);
    }
}

public class CalculatorServiceTest {
    public static void main(String[] args) {
        final AuthorizationInterceptor interceptor = new AuthorizationInterceptor();
        final CalculatorService target = Feign.builder()
               .requestInterceptor(interceptor)
               .target(CalculatorService.class, HOST);
    }
}

實現RequestInterceptor并覆蓋其apply()方法,以根據需要對請求進行任何修改。

配置重試器

OpenFeign Retryer是一個組件,允許我們配置Feign在請求失敗時如何處理重試。它對于處理網絡通信中的瞬時故障特別有用,我們可以指定Feign應自動重試失敗請求的條件。

重試器配置

要在OpenFeign中使用重試器,需要提供Retryer接口的實現。Retryer接口有兩個方法:

  • boolean continueOrPropagate(int attemptedRetries, int responseStatus, Request request):此方法用于確定是繼續重試還是傳播錯誤。它接受嘗試重試的次數、HTTP響應狀態和請求作為參數,并返回true以繼續重試或false以傳播錯誤。
  • Retryer clone():此方法創建重試器實例的克隆。

默認重試器

Feign提供了一個默認的重試器實現,名為Retryer.Default。當我們創建Feign客戶端而未顯式指定自定義重試器時,將使用此默認重試器。

它提供了兩個工廠方法來創建Retryer對象。

第一個工廠方法不需要任何參數:

public Default() {
    this(100L, TimeUnit.SECONDS.toMillis(1L), 5);
}

它定義了一個簡單的重試策略,具有以下特點:

  • 最大嘗試次數:對于失敗的請求,最多允許5次重試嘗試。
  • 退避期:在重試之間使用指數退避策略,從100毫秒的退避開始,每次后續重試將退避時間加倍。
  • 可重試異常:如果請求導致任何被認為可重試的異常(通常包括網絡相關異常,如連接超時或套接字異常),則會重試請求。

第二個工廠方法需要一些參數。如果默認配置不適合我們,可以使用它:

public Default(long period, long maxPeriod, int maxAttempts)

// 使用它創建重試器
new Retryer.Default(1, 100, 10);

雖然Feign提供的默認重試器涵蓋了許多常見的重試場景,但在某些情況下,我們可能希望定義自定義重試器。以下是定義自定義重試器的一些動機:

  • 精細控制:如果我們需要對默認重試行為進行更多控制,例如指定不同的最大重試次數或自定義退避策略,自定義重試器允許我們根據特定要求定制行為。
  • 重試邏輯:在某些情況下,我們可能只希望針對特定的響應代碼或異常重試請求。自定義重試器允許我們實現自己的邏輯來確定何時應該進行重試。
  • 日志記錄和指標:如果我們想要記錄或收集與重試嘗試相關的指標,實現自定義重試器提供了添加此功能的機會。
  • 與斷路器集成:如果我們將斷路器模式與Feign結合使用,自定義重試器可以與斷路器的狀態集成,以便在決定何時重試或何時打開斷路器時做出更明智的決策。
  • 非標準重試策略:對于不適合默認重試器提供的標準重試策略的場景,例如速率限制的API或具有特定重試要求的API,我們可以定義適合我們用例的自定義重試器。

以下是在OpenFeign中實現自定義Retryer的示例:

public class CalculatorRetryer implements Retryer {
    /**
     * 重試之間等待的毫秒數
     */
    private final long period;

    /**
     * 最大重試次數
     */
    private final int maxAttempts;

    private int attempt = 1;

    @Override
    public void continueOrPropagate(RetryableException e) {
        log.info("Feign retry attempt {} of {} due to {}",
                attempt,
                maxAttempts,
                e.getMessage());
        if (++attempt > maxAttempts) {
            throw e;
        }
        if (e.status() == 401) {
            try {
                Thread.sleep(period);
            } catch (InterruptedException ex) {
                throw e;
            }
        } else {
            throw e;
        }
    }

    @Override
    public Retryer clone() {
        return this;
    }

    public int getRetryAttempts() {
        return attempt - 1; // 減去1以排除初始嘗試
    }
}

它專門重試HTTP 401錯誤。

總之,當我們需要對HTTP請求中的重試處理方式有更大的控制權和靈活性時,就有必要在Feign中創建自定義重試器。當我們的需求與默認重試器的行為不同時,自定義重試器允許我們根據特定用例修改重試邏輯。

斷路器

斷路器通常使用單獨的庫或工具(如Netflix Hystrix、Resilience4j或Spring Cloud Circuit Breaker)來實現。

為何使用斷路器?

在Feign中使用斷路器的主要動機是增強基于微服務的應用程序的彈性。以下是一些關鍵原因:

  • 故障隔離:斷路器通過隔離故障組件,防止一個服務中的故障級聯到其他服務。
  • 快速失敗:當電路打開(表示故障狀態)時,后續請求會“快速失敗”,而不會嘗試向可能無響應或故障的服務發出調用,從而減少延遲和資源消耗。
  • 優雅降級:當依賴服務出現問題時,斷路器允許應用程序優雅降級,確保它能夠繼續提供一組簡化的功能。
  • 監控和指標:斷路器提供指標和監控功能,使我們能夠跟蹤服務的健康狀況和性能。

配置斷路器

HystrixFeign用于配置Hystrix提供的斷路器支持。

Hystrix是一個延遲和容錯庫,旨在隔離分布式環境中對遠程系統、服務和第三方庫的訪問點。它有助于阻止級聯故障,并在故障不可避免的復雜分布式系統中實現彈性。

要在Feign中使用Hystrix,需要將Hystrix模塊添加到類路徑中,并使用HystrixFeign構建器,如下所示:

final CalculatorService target = HystrixFeign.builder()
      .target(CalculatorService.class, HOST);

讓我們看看如何使用回退類來處理服務錯誤。

在Hystrix中,回退類是為Hystrix命令定義回退邏輯的另一種方式,而不是直接在Hystrix命令類的getFallback方法中定義回退邏輯。回退類提供了關注點分離,使我們能夠將命令類專注于主要邏輯,并將回退邏輯委托給單獨的類。這可以提高代碼的組織性和可維護性。

以下是為CalculatorService實現回退的示例代碼:

@Slf4j
public class CalculatorHystrixFallback implements CalculatorService {

    @Override
    public Long add(Long firstNumber, Long secondNumber) {
        log.info("[Fallback add] Adding {} and {}", firstNumber, secondNumber);
        return firstNumber + secondNumber;
    }

    @Override
    public Long subtract(Long firstNumber, Long secondNumber) {
        return null;
    }

    @Override
    public Long multiply(Long firstNumber, Long secondNumber) {
        return null;
    }

    @Override
    public Long divide(Long firstNumber, Long secondNumber) {
        return null;
    }
}

為了演示回退,我們僅實現了add方法。然后在構建客戶端時使用此回退:

final CalculatorHystrixFallback fallback = new CalculatorHystrixFallback();
final CalculatorService target = HystrixFeign.builder()
      .decoder(new JacksonDecoder())
      .target(CalculatorService.class,
               HOST, fallback);

當add端點返回錯誤或電路打開時,Hystrix將調用add回退方法。

收集指標

Feign本身不像其他一些庫或框架那樣提供內置的指標功能API。

與Feign相關的指標,如請求持續時間、錯誤率或重試次數,通常需要使用外部庫或工具來收集和跟蹤。

在Java應用程序中收集指標的流行庫包括Micrometer和Dropwizard Metrics。

以下是如何使用常用的Micrometer庫來收集和報告與Feign調用相關的指標:

public class CalculatorServiceTest {
    public static void main(String[] args) {
        final CalculatorService target = Feign.builder()
              .addCapability(new MicrometerCapability())
              .target(CalculatorService.class, HOST);
        target.contributors("OpenFeign", "feign");
        // 從此時起指標將可用
    }
}

請注意,我們需要將Micrometer作為依賴項添加到項目中并進行適當配置。

文末總結

本文算是溫故知新的一篇,由淺入深介紹了使用OpenFeign的5個步驟和7個高級功能,OpenFeign的使用方面,已經涵蓋全了。后續再看看在SpringCloud中,OpenFeign的使用,以及在于Ribbon等組件結合使用時,又能碰撞出哪些火花。

責任編輯:武曉燕 來源: 看山的小屋
相關推薦

2010-04-09 09:55:43

Oracle sqlp

2011-03-02 09:34:58

AppFuse

2014-03-12 15:23:20

2022-08-02 20:22:01

SaaS安全網絡攻擊

2023-07-10 13:28:43

智能建筑工具

2023-04-25 12:45:09

2024-05-07 08:00:00

自然語言處理機器學習

2015-12-23 09:48:32

2023-06-01 13:09:09

智能建筑數字孿生

2023-03-06 08:48:52

2022-02-15 11:03:40

SD-WAN軟件定義WAN

2009-12-25 14:52:49

2019-07-11 15:26:50

數據中心技術數據網絡

2022-04-13 10:25:08

基礎設施IT 團隊

2021-11-22 12:13:54

Linuxwget 命令

2022-07-28 11:33:23

數據分析經驗

2024-07-26 10:28:50

前端開發CSS

2022-11-18 14:33:39

2018-05-17 13:59:28

IT顧問

2023-07-14 14:53:38

人工智能prompt
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美日韩看片 | 国外成人在线视频网站 | a在线视频观看 | 一区二区三区国产好的精 | 国产一区欧美 | 性色av香蕉一区二区 | 精品成人佐山爱一区二区 | 国产在线精品一区二区三区 | h视频亚洲 | 超碰操 | 亚洲精品一区二区三区蜜桃久 | 日韩在线一区二区三区 | 给我免费的视频在线观看 | 欧美自拍网站 | 久久精品久久久 | 中文字幕亚洲精品 | 97日日碰人人模人人澡分享吧 | 午夜视频免费在线观看 | 国产丝袜av | 久久久久久电影 | 亚洲精品在线视频 | 精品欧美一区二区三区久久久 | 国内自拍视频在线观看 | 97精品超碰一区二区三区 | 高清人人天天夜夜曰狠狠狠狠 | 可以免费看的毛片 | 亚洲视频中文字幕 | 亚洲欧美视频在线观看 | 日韩欧美黄色 | 天天拍夜夜爽 | 亚洲一区二区在线免费观看 | 欧洲成人免费视频 | 国产香蕉视频在线播放 | 国产九九精品视频 | 亚洲高清在线观看 | 午夜成人在线视频 | 黄色网络在线观看 | 国产高清在线视频 | 日韩免费视频一区二区 | 欧美一区二| 99久久精品免费看国产高清 |