SpringCloud升級之路2020.0.x版-25.OpenFeign簡介與使用

乾貨滿滿張雜湊發表於2021-10-03

本系列程式碼地址:https://github.com/JoJoTec/spring-cloud-parent

OpenFeign 的由來和實現思路

在微服務系統中,我們經常會進行 RPC 呼叫。在 Spring Cloud 體系中,RPC 呼叫一般就是 HTTP 協議的呼叫。對於每次呼叫,基本都要經過如下步驟:

  • 找到微服務例項列表並選擇一個例項
  • 呼叫引數序列化
  • 使用 Http 客戶端將請求傳送出去
  • 響應處理,反序列化等等
    除了這些公共邏輯,業務上只需要定義引數,HTTP 方法,HTTP URI,響應就可以,也就是使用介面就能定義:
interface HttpBin {
    @Get(uri = "/get")
    String get(@Param("param") String param);
}

例如上面這個介面,就定義了一個 HTTP 請求,HTTP 方法為 GET,路徑是 /get,引數是 param,響應為 String 型別。之後只要定義好公共邏輯,就能使用這個介面進行呼叫了。

對於這些公共邏輯的實現設計,我們很自然的就能想到切面與動態代理。之前的章節,我們提到過 JDK 中有針對介面的動態代理,其實就是實現 java.lang.reflect.InvocationHandler 然後針對這個介面實現代理類。之後使用這個代理類進行呼叫即可走入 InvocationHandler 中定義的邏輯。

以上,就是 OpenFeign 的設計實現思路與用途

OpenFeign 簡介

OpenFeign 是一個基於宣告式(通過類後設資料定義,例如註解等)定義的 HTTP 請求客戶端。這個庫可以讓你通過註解來自動生成呼叫對應 HTTP 服務的客戶端,從程式碼上看呼叫這個遠端服務和呼叫本地服務方法一樣。OpenFeign 支援多種 HTTP 註解,包括 Feign 註解和 JAX-RS 註解,並且可以通過配置類似於外掛的形式支援不同種類的註解。同時,還可以配置編碼器,解碼器,來編碼請求並解碼響應。底層的 HTTP Client 也是可以配置的,你可以使用 Java 原生的 Http 連結,也可以使用 Apache HttpClient 還有 OkHttpClient 等等。

目前 OpenFeign 還在不斷迭代更新中,可以通過這個連結檢視當前的 RoadMap。當前我們使用的是 OpenFeign 11,當前實現中或者計劃中的特性包括:

  • 響應快取,支援程式內或者跨程式響應快取(實現中)
  • 實現更完善的 URI 模板支援(實現中)
  • 重構 Logger 日誌 API(實現中)
  • 重構 Retry 重試 API(實現中)
  • 採集指標相關 API(下一步要實現)
  • 通過 CompletableFuture 作為基礎類,實現非同步 API(當前已經有基本實現,下一步完整實現)
  • 響應式 API (下一步要實現)
  • 斷路器相關支援(計劃中)

OpenFeign 基本使用

我們先來看 OpenFeign 的使用,先不關心 Spring Cloud 環境下如何使用,這樣更能理解其底層原理。單獨使用 OpenFeign 分以下幾步:

  1. 定義遠端 HTTP 呼叫 API 介面
  2. 建立 Feign 代理的 HTTP 呼叫介面實現
  3. 使用代理類進行呼叫

具體例子是:

interface GitHub {
    /**
     * 定義get方法,包括路徑引數,響應返回序列化類
     * @param owner
     * @param repository
     * @return
     */
    @RequestLine("GET /repos/{owner}/{repo}/contributors")
    List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repository);

    /**
     * 響應體結構類
     */
    class Contributor {
        String login;
        int contributions;

        public Contributor() {
        }

        public String getLogin() {
            return login;
        }

        public void setLogin(String login) {
            this.login = login;
        }

        public int getContributions() {
            return contributions;
        }

        public void setContributions(int contributions) {
            this.contributions = contributions;
        }
    }
}

public static void main(String[] args) {
    //建立 Feign 代理的 HTTP 呼叫介面實現
    GitHub github = Feign.builder()
                        //指定解碼器為 FastJsonDecoder
                        .decoder(new FastJsonDecoder())
                        //指定代理類為 GitHub,基址為 https://api.github.com
                        .target(GitHub.class, "https://api.github.com");
    List<GitHub.Contributor> contributors = github.contributors("OpenFeign", "feign");
}


/**
 * 基於 FastJson 的反序列化解碼器
 */
static class FastJsonDecoder implements Decoder {
    @Override
    public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException {
        //讀取 body
        byte[] body = response.body().asInputStream().readAllBytes();
        return JSON.parseObject(body, type);
    }
}

在上面這個例子中,我們定義了訪問 GET https://api.github.com/repos/{owner}/{repo}/contributors 這個介面的 OpenFeign 客戶端,並自定義了響應解碼器,反序列化了響應體。這就是 OpenFeign 的基本使用。

我們這一節詳細介紹了 OpenFeign 的設計思路以及 RoadMap,瞭解這些之後,我們再來詳細分析 Openfeign,就能理解其中的一些設計以及使用思路了。並且某些重構中的特性,我們在使用中需要格外注意,不過也不必擔心,因為在 Spring Cloud 中使用 OpenFeign 的特性都是通過加入膠水專案依賴實現的,底層 API 重構是膠水專案需要關心的事情。

微信搜尋“我的程式設計喵”關注公眾號,每日一刷,輕鬆提升技術,斬獲各種offer

相關文章