亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringCloud超詳細講解Feign聲明式服務(wù)調(diào)用

 更新時間:2022年06月21日 09:37:29   作者:墨鴉_Cormorant  
Feign可以把Rest的請求進行隱藏,偽裝成類似Spring?MVC的Controller一樣。不用再自己拼接url,拼接參數(shù)等等操作,一切都交給Feign去做

入門案例

在服務(wù)消費者導入依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

在啟動類上添加@EnableFeignClients注解

Feign中已經(jīng)自動集成了Ribbon負載均衡,因此不需要自己定義RestTemplate

@SpringCloudApplication
@EnableFeignClients		// 開啟Feign注解
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
}

編寫Feign客戶端

@FeignClient(value = "user-service")    // 添加FeignClient,指定服務(wù)ID
public interface UserClient {
    /**
     * 聲明一個feign的接口,它的實現(xiàn)是服務(wù)提供者的controller實現(xiàn)
     */
    @GetMapping("/user/{id}")
    User getById(@PathVariable("id") Long id);
}

代碼中調(diào)用,使用userClient訪問:

@Autowired  // 注入UserClient
private UserClient userClient;
public User getUserById(@PathVariable long id) {
    User user = userClient.getById(id);
    return user;
}

@FeignClient注解詳解

@FeignClient注解只能在Interface接口上使用。Feign會通過動態(tài)代理,生成實現(xiàn)類。

FeignClient注解被@Target(ElementType.TYPE)修飾,表示FeignClient注解的作用目標在接口上

@FeignClient ,聲明這是一個Feign客戶端,同時通過 name / value 屬性指定服務(wù)名稱

接口中定義的方法,完全采用SpringMVC的注解,F(xiàn)eign會根據(jù)注解生成URL,并訪問獲取結(jié)果

服務(wù)的啟動類要有@EnableFeignClients 注解才能使Fegin生效

@FeignClient注解的常用屬性如下:

name / value:指定FeignClient的名稱,如果項目使用了Ribbon(注冊中心),name屬性會作為微服務(wù)的名稱,用于服務(wù)發(fā)現(xiàn)

url:一般用于調(diào)試,可以手動指定@FeignClient調(diào)用的地址。默認為空

url可以從配置文件獲取,如果有則通過url調(diào)用,沒有則根據(jù)服務(wù)名調(diào)用。格式為 url = "${xxx.xxx.xxx: }"

configuration:Feign配置類,可以自定義Feign的Encoder、Decoder、LogLevel、Contract,可以為每一個feign client指定不同的配置

fallback:定義容錯的處理類,當調(diào)用遠程接口失敗或超時時,會調(diào)用對應(yīng)接口的容錯邏輯,fallback指定的類必須實現(xiàn)@FeignClient標記的接口

fallbackFactory:工廠類,用于生成fallback類示例,通過這個屬性可以實現(xiàn)每個接口通用的容錯邏輯,減少重復的代碼

path:定義當前FeignClient的統(tǒng)一前綴,當項目中配置了server.context-path, server.servlet-path時使用

decode404:當發(fā)生http 404錯誤時,如果該字段位true,會調(diào)用decoder進行解碼,否則拋出FeignException

調(diào)用方式:

方式一:接口提供方在注冊中心

如果服務(wù)提供方已經(jīng)注冊到注冊中心了,那么name或者value的值為:服務(wù)提供方的服務(wù)名稱。必須為所有客戶端指定一個name或者value

@FeignClient(value="run-product",fallback = ProductClientServiceFallBack.class)

方式二:單獨的一個http接口,接口提供方?jīng)]有注冊到注冊中心

@FeignClient(name="runClient11111",url="localhost:8001")

此處name的值為:調(diào)用客戶端的名稱

以上兩種方式都能正常調(diào)用。name可以為注冊中心的服務(wù)名稱,加上url屬性時,name的值就與注冊中心服務(wù)名稱無關(guān)。

Feign Client的配置

feign配置是在ribbon配置的基礎(chǔ)上做了擴展,可以支持服務(wù)級超時時間配置,所以,feign配置和ribbon配置的效果是?樣的。

SpringCloud對配置的優(yōu)先級順序如下:

  • Feign局部配置 > Feign全局配置 > Ribbon局部配置 > Ribbon全局配置
  • 配置文件屬性和配置類的優(yōu)先級順序為:配置文件屬性配置 > 配置類代碼配置

feign:
  client:
    config:
      default:    # 全部服務(wù)配置
        connectTimeout: 5000    # 建立連接的超時時長,單位:毫秒。默認為1000
        readTimeout: 5000        # 指建立連接后從服務(wù)端讀取到可用資源所用的超時時間,單位:毫秒。默認為1000
        loggerLevel: FULL        # 日志級別
        errorDecoder: com.example.SimpleErrorDecoder  # Feign的錯誤解碼器,相當于代碼配置方式中的ErrorDecoder
        retryer: com.example.SimpleRetryer  # 配置重試,相當于代碼配置方式中的Retryer
        requestInterceptors: # 配置攔截器,相當于代碼配置方式中的RequestInterceptor
          - com.example.FooRequestInterceptor
          - com.example.BarRequestInterceptor
        decode404: false    # 是否對404錯誤解碼
        encode: com.example.SimpleEncoder
        decoder: com.example.SimpleDecoder
        contract: com.example.SimpleContract
      serverName:    # 單獨給某?服務(wù)配置。serverName是服務(wù)名,使?的時候要?服務(wù)名替換掉這個
        connectTimeout: 5000
        readTimeout: 5000

Feign請求添加headers

方案一:方法上的@RequestMapping注解添加headers信息

@RequestMapping注解的屬性中包含一個headers數(shù)組,可以在指定的方法上@RequestMapping注解中添加需要的headers,可以是寫死的,也可以讀取配置=

同理@RequestMapping一組的@PostMapping,@GetMapping注解等均適用

@FeignClient(name = "server",url = "127.0.0.1:8080")
public interface FeignTest {
    @RequestMapping(value = "/test",headers = {"app=test-app","token=${test-app.token}"})
    String test();
}

方案二:接口上的@RequestMapping注解添加headers信息

如果同一個接口中所有的方法都需要同樣的headers,可以在接口上的@RequestMapping注解中添加headers,使整個接口的方法均被添加同樣的headers

@FeignClient(name = "server",url = "127.0.0.1:8080")
@RequestMapping(value = "/",headers = {"app=test-app","token=${test-app.token}"})
public interface FeignTest {
    @RequestMapping(value = "/test")
    String test();
}

方案三:使用@Headers注解添加headers信息(不推薦)

@FeignClient(name = "server",url = "127.0.0.1:8080")
@Headers({"app: test-app","token: ${test-app.token}"})
public interface FeignTest {
    @RequestMapping(value = "/test")
    String test();
}

查看openfeign官方文檔發(fā)現(xiàn)其使用的是@Headers來添加headers,測試發(fā)現(xiàn)并沒有生效,spring cloud使用了自己的SpringMvcContract來解析注解,所以需要自己實現(xiàn)一個Contract來實現(xiàn)對@Headers注解的支持,具體實現(xiàn)參照(http://chabaoo.cn/article/252325.htm

方案四:自定義RequestInterceptor添加headers信息

feign提供了一個攔截器接口RequestInterceptor,實現(xiàn)RequestInterceptor接口就可以實現(xiàn)對feign請求的攔截,接口提供了一個方法apply(),實現(xiàn)apply()方法

實現(xiàn)apply()方法直接添加header會攔截所有的請求都加上headers,如果不是所有的feign請求都需要用到不建議此方法

@Component
public class FeignRequestInterceptor implements RequestInterceptor {
    @Value("${test-app.token}")
    private String token;
    @Override
    public void apply(RequestTemplate requestTemplate) {
        requestTemplate.header("app","test-app");//靜態(tài)
        requestTemplate.header("token",token);//讀配置
    }
}

方案五:自定義RequestInterceptor實現(xiàn)添加動態(tài)數(shù)據(jù)到header

以上方案都不適合把動態(tài)的數(shù)據(jù)放入headers中,而通常場景下可能經(jīng)常需要把計算的簽名,用戶id等動態(tài)信息設(shè)置到headers,所以還需要一個更加完善的方案。方案1/2/3均不能設(shè)置動態(tài)的值,方案4可以設(shè)置動態(tài)值,但是沒做到請求的區(qū)分,所以在方案4的基礎(chǔ)上進行改進得到了較為完善的方案5。具體實現(xiàn)如下:

在請求調(diào)用代碼中,獲取到HttpServletRequest對象,將需要添加到headers中的值封裝成一個map后放入HttpServletRequest的attribute域中

    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
    String signedMsg = getSignedMsg(reqJson); 		// 計算簽名字符串
    Map<String, String> reqMap = new HashMap<>();
    reqMap.put("content-type", "application/json");	//常量字段
    reqMap.put("accessKey", accessKey);		//常量字段
    reqMap.put("signedMsg", signedMsg);		//動態(tài)計算/獲取字段
    request.setAttribute("customizedRequestHeader", reqMap);

在自定義RequestInterceptor中獲取到HttpServletRequest對象的attribute域中指定的key,將key對應(yīng)map中的所有參數(shù)加入到headers。

@Component
public class FeignRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 設(shè)置自定義header
        // 設(shè)置request中的attribute到header以便轉(zhuǎn)發(fā)到Feign調(diào)用的服務(wù)
        Enumeration<String> reqAttrbuteNames = request.getAttributeNames();
        if (reqAttrbuteNames != null) {
            while (reqAttrbuteNames.hasMoreElements()) {
                String attrName = reqAttrbuteNames.nextElement();
                if (!"customizedRequestHeader".equalsIgnoreCase(attrName)) {
                    continue;
                }
                Map<String,String> requestHeaderMap = (Map)request.getAttribute(attrName);
                for (Map.Entry<String, String> entry : requestHeaderMap.entrySet()) {
                    requestTemplate.header(entry.getKey(), entry.getValue());
                }
                break;
            }
        }
    }
}

負載均衡 (Ribbon)

Feign中本身已經(jīng)集成了Ribbon依賴和自動配置,默認支持Ribbon。

Fegin內(nèi)置的ribbon默認設(shè)置了請求超時時長,默認是1000ms。因為Ribbon內(nèi)部有重試機制,一旦超時,會自動重新發(fā)起請求

可以通過配置來修改:

全局配置 使用 ribbon.=

ribbon:
  ReadTimeout: 2500     # 數(shù)據(jù)通信超時時長,單位:ms。默認為1000
  ConnectTimeout: 500     # 連接超時時長,單位:ms。默認為1000
  OkToRetryOnAllOperations: false     # 是否對所有的異常請求(連接異常和請求異常)都重試。默認為false
  MaxAutoRetriesNextServer: 1         # 最多重試多少次連接服務(wù)(實例)。默認為1。不包括首次調(diào)用
  MaxAutoRetries: 0     # 服務(wù)的單個實例的重試次數(shù)。默認為0。不包括首次調(diào)用
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule    # 切換負載均衡策略為隨機

指定服務(wù)配置 <服務(wù)名稱>.ribbon. =

serverName:    # 單獨給某?服務(wù)配置。serverName是服務(wù)名,使?的時候要?服務(wù)名替換掉這個
  ribbon:
    connectTimeout: 5000
    readTimeout: 5000

容錯機制

Hystrix支持

Feign默認也有對Hystix的集成,只不過,默認情況下是關(guān)閉的。需要通過下面的參數(shù)來開啟:

feign:
  hystrix:
    enabled: true    # 開啟hystrix熔斷機制
hystrix:
  command:
    default:    # 全局默認配置
      execution:    # 線程隔離相關(guān)
        timeout:
          enabled: true        # 是否給方法執(zhí)行設(shè)置超時時間,默認為true。一般不改。
        isolation:
          strategy: THREAD    # 配置請求隔離的方式,這里是默認的線程池方式。還有一種信號量的方式semaphore,
          thread:
            timeoutlnMilliseconds: 10000    # 方式執(zhí)行的超時時間,默認為1000毫秒,在實際場景中需要根據(jù)情況設(shè)置
      circuitBreaker:    # 服務(wù)熔斷相關(guān)
        requestVolumeThreshold: 10            # 觸發(fā)熔斷的最小請求次數(shù),默認20
        sleepWindowInMilliseconds: 10000    # 休眠時長,單位毫秒,默認是5000毫秒
        errorThresholdPercentage: 50        # 觸發(fā)熔斷的失敗請求最小占比,默認50%
    serverName:    # 單獨給某?服務(wù)配置
      execution:
        timeout:
          enabled: true
        isolation:
          strategy: THREAD
          thread:
            timeoutlnMilliseconds: 10000

注意:

Hystix的超時時間應(yīng)該比Ribbon重試的總時間要大 ,否則Hystrix命令超時后,該命令直接熔斷,重試機制就沒有任何意義了。

Ribbon:總重試次數(shù) = 訪問的服務(wù)器數(shù) * 單臺服務(wù)器最大重試次數(shù)

即 總重試次數(shù) = (1+MaxAutoRetriesNextServer)*(1+MaxAutoRetries )

Hystrix超時時間 > (Ribbon超時時間總和)* 重試次數(shù)

故 建議hystrix的超時時間為:

( ( 1+MaxAutoRetriesNextServer) * (1+MaxAutoRetries ) ) * (ReadTimeout + connectTimeout)

  • MaxAutoRetries:Ribbon配置: 服務(wù)的單個實例的重試次數(shù)。不包括首次調(diào)用
  • MaxAutoRetriesNextServer:Ribbon配置: 最多重試多少次連接服務(wù)(實例)。不包括首次調(diào)用
  • ReadTimeout:Ribbon配置: 通信超時時間
  • connectTimeout:Ribbon配置: 建立連接超時時間

Sentinel支持

Sentinel 可以通過并發(fā)線程數(shù)模式的流量控制來提供信號量隔離的功能。并且結(jié)合基于響應(yīng)時間的熔斷降級模式,可以在不穩(wěn)定資源的平均響應(yīng)時間比較高的時候自動降級,防止過多的慢調(diào)用占滿并發(fā)數(shù),影響整個系統(tǒng)。

依賴

        <!--Sentinel-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

在配置文件中開啟Feign對Sentinel的支持

feign:
  sentinel:
    enabled: true

Feign開啟容錯機制支持后的使用方式

Feign 開啟 Hystrix 或 Sentinel 容錯機制支持后的使用方式均是如下兩種:

方案一:直接繼承被容錯的接口,并為每個方法實現(xiàn)容錯方案

方案二:實現(xiàn)FallbackFactory接口

方案一:直接繼承被容錯的接口,并為每個方法實現(xiàn)容錯方案

定義一個類,作為fallback的處理類 。直接繼承被容錯的接口,并為每個方法實現(xiàn)容錯方案

@Component
public class UserClientFallback implements UserClient {
    @Override
    public User getById(Long id) {
        return new User(1L, "我是備份-feign", 18, new Date());
    }
}

在 @FeignClient 注解中使用 fallback 屬性指定自定義的容錯處理類

@FeignClient(value = "user-service",fallback = UserClientFallback.class)
public interface UserClient {
    @GetMapping("/user/{id}")
    User getById(@PathVariable("id") Long id);
}

測試驗證

方案二:實現(xiàn)FallbackFactory接口。可以拿到具體的服務(wù)錯誤信息,便于后期排查問題

@FeignClient(value="34-SPRINGCLOUD-SERVICE-GOODS", fallbackFactory = GoodsRemoteClientFallBackFactory.class)
public interface GoodsRemoteClient {
    @RequestMapping("/service/goods")
    public ResultObject goods();
}
@Component
public class GoodsRemoteClientFallBackFactory implements FallbackFactory<GoodsRemoteClient> {
    @Override
    public GoodsRemoteClient create(Throwable throwable) {
        return new GoodsRemoteClient() {
            @Override
            public ResultObject goods() {
                String message = throwable.getMessage();	// message即為錯誤信息
                System.out.println("feign遠程調(diào)用異常:" + message);
                return new ResultObject();
            }
        };
    }
}

請求壓縮feign.compression

Spring Cloud Feign 支持對請求和響應(yīng)進行GZIP壓縮,以減少通信過程中的性能損耗。通過下面的參數(shù)即可開啟請求與響應(yīng)的壓縮功能:

feign:
  compression:
    request:
      enabled: true
    response:
      enabled: true

也可以對請求的數(shù)據(jù)類型,以及觸發(fā)壓縮的大小下限進行設(shè)置,只有超過這個大小的請求才會對其進行壓縮:

feign:
  compression:
    request:
      enabled: true
      mime-types: text/xml,application/xml,application/json
      min-request-size: 2048

日志級別

通過logging.level.xx=debug來設(shè)置日志級別。然而這個對Fegin客戶端而言不會產(chǎn)生效果。因為@FeignClient注解修改的客戶端在被代理時,都會創(chuàng)建一個新的Fegin.Logger實例,所以需要額外指定這個日志的級別才可以。

Feign支持4種日志級別:

  • NONE:不記錄任何日志信息,這是默認值。
  • BASIC:僅記錄請求的方法,URL以及響應(yīng)狀態(tài)碼和執(zhí)行時間
  • HEADERS:在BASIC的基礎(chǔ)上,額外記錄了請求和響應(yīng)的頭信息
  • FULL:記錄所有請求和響應(yīng)的明細,包括頭信息、請求體、元數(shù)據(jù)。

全局配置

方式一:配置文件屬性實現(xiàn)

feign:
  client:
    config:
      default:    # 將調(diào)用的微服務(wù)名稱設(shè)置為default即為配置成全局
        loggerLevel: FULL

方式一:代碼實現(xiàn)

//在啟動類上為@EnableFeignClients注解添加defaultConfiguration配置
@EnableFeignClients(defaultConfiguration = FeignConfig.class)

細粒度(指定服務(wù)配置)

方式一:配置文件實現(xiàn)

feign:
  client:
    config:
      server-1:        # 想要調(diào)用的微服務(wù)名稱
        loggerLevel: FULL

方式二:代碼實現(xiàn)

1)編寫配置類,定義日志級別

@Configuration
public class FeignConfig {
    @Bean
    Logger.Level level(){
        return Logger.Level.FULL;
    }
}

2)在FeignClient中指定配置類:(可以省略)

@FeignClient(value = "user-service", configuration = FeignConfig.class)
// 添加FeignClient,指定服務(wù)ID
public interface UserClient {
    @GetMapping("/user/{id}")
    User getById(@PathVariable("id") Long id);
}

Feign每次訪問的日志示例:

到此這篇關(guān)于SpringCloud超詳細講解Feign聲明式服務(wù)調(diào)用的文章就介紹到這了,更多相關(guān)SpringCloud Feign內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring AOP注解失效的坑及JDK動態(tài)代理

    Spring AOP注解失效的坑及JDK動態(tài)代理

    這篇文章主要介紹了Spring AOP注解失效的坑及JDK動態(tài)代理,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • Flask接口如何返回JSON格式數(shù)據(jù)自動解析

    Flask接口如何返回JSON格式數(shù)據(jù)自動解析

    這篇文章主要介紹了Flask接口如何返回JSON格式數(shù)據(jù)自動解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11
  • 詳述 DB2 分頁查詢及 Java 實現(xiàn)的示例

    詳述 DB2 分頁查詢及 Java 實現(xiàn)的示例

    本篇文章主要介紹了詳述 DB2 分頁查詢及 Java 實現(xiàn)的示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • Java定時器Timer與TimerTask的使用詳解

    Java定時器Timer與TimerTask的使用詳解

    這篇文章主要介紹了Java定時器Timer與TimerTask的使用詳解,在JDK類庫中Timer主要負責計劃任務(wù)的功能,也就是在指定時間執(zhí)行某一任務(wù),執(zhí)行時候會在主線程之外起一個單獨的線程執(zhí)行指定的任務(wù),該類主要是設(shè)置任務(wù)計劃,但封裝的類是TimerTask類,需要的朋友可以參考下
    2023-10-10
  • Java國際化簡介_動力節(jié)點Java學院整理

    Java國際化簡介_動力節(jié)點Java學院整理

    這篇文章主要為大家簡單介紹了Java國際化的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Java?GenericObjectPool?對象池化技術(shù)之SpringBoot?sftp?連接池工具類詳解

    Java?GenericObjectPool?對象池化技術(shù)之SpringBoot?sftp?連接池工具類詳解

    這篇文章主要介紹了Java?GenericObjectPool?對象池化技術(shù)之SpringBoot?sftp?連接池工具類詳解,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04
  • 使用SpringBoot配置多數(shù)據(jù)源的經(jīng)驗分享

    使用SpringBoot配置多數(shù)據(jù)源的經(jīng)驗分享

    這篇文章主要介紹了使用SpringBoot配置多數(shù)據(jù)源的經(jīng)驗分享,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04
  • java 中ThreadLocal本地線程和同步機制的比較

    java 中ThreadLocal本地線程和同步機制的比較

    這篇文章主要介紹了java 中ThreadLocal本地線程和同步機制的比較的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • SpringBoot Security整合JWT授權(quán)RestAPI的實現(xiàn)

    SpringBoot Security整合JWT授權(quán)RestAPI的實現(xiàn)

    這篇文章主要介紹了SpringBoot Security整合JWT授權(quán)RestAPI的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-11-11
  • Spring中的SpringData詳細說明

    Spring中的SpringData詳細說明

    這篇文章主要介紹了Spring中的SpringData詳細說明,Spring Data 是Spring 的一個子項目, 旨在統(tǒng)一和簡化對各類型持久化存儲, 而不拘泥于是關(guān)系型數(shù)據(jù)庫還是NoSQL 數(shù)據(jù)存儲,需要的朋友可以參考下
    2023-11-11

最新評論