客戶端遠程調用Feign

客戶端遠程調用

Feign

什麼是Feign?

Feign是 Netflix 公司開源的聲明式HTTP客戶端java

Github : Feign 源碼git

爲何須要Feign?

  1. 原代碼可讀性不高
  2. 複雜的URL難以維護(https://user-center/s?wd={userId}&rsv_spt=1&rsv_iqid=0x93bff3cd000cf3da&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=4&rsv_sug1=4&rsv_sug7=100&rsv_t=10c2risCimsUZC0RBruMerdnQRN1gRxFI%2BywuD0L3LwGGNd2dR8XE6x%2FyFOjHnR0oEi0&rsv_sug2=0&inputT=1535&rsv_sug4=1535&rsv_sug=2
  3. 難以應對需求的快速變化
  4. 編碼體驗和咱們寫JAVA差別較大

舉例重構代碼

//替換前 
        ResponseEntity<UserDTO> userEntity = restTemplate.getForEntity(
                "http://user-center/users/{userId}",
                UserDTO.class, userId
        );
        UserDTO userDTO = new UserDTO();
        if (null != userEntity) {
            userDTO = userEntity.getBody();
            log.info("ShareService#findById userDTO: {}", userDTO);
        }
  1. 添加依賴
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
  1. 啓動類添加註解 @EnableFeignClients
  2. 添加配置
  3. 實現對應微服務的client
/**
 * IUserCenterFeignClient for 定義 user-center feign client
 *
 * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>
 * @since 2019/7/15
 */
@FeignClient(name = "user-center")
public interface IUserCenterFeignClient {

    /**
     * Feign client 會將請求轉換爲
     * http://user-center/users/{userId}
     *
     * @param userId 用戶id
     * @return 返回用戶對象
     */
    @GetMapping(path = "/users/{userId}")
    public UserDTO findById(@PathVariable Long userId);
}
  1. 替換後代碼
//使用 FeignClient 來替換掉RestTemplate調用
        UserDTO userDTO = this.userCenterFeignClient.findById(userId);

Feign的組成

Feign的配置方式

Java Code

支持的配置項

自定義Feign日誌級別
  • 級別內容

Demo

**Tip **: 有可能出現父子上下文重疊問題github

  1. 在client添加配置
/**
 * IUserCenterFeignClient for 定義 user-center feign client
 *
 * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>
 * @since 2019/7/15
 */
@FeignClient(name = "user-center",configuration = UserCenterFeignConfiguration.class)
public interface IUserCenterFeignClient {
   ...
}
  1. 編寫java配置文件
/**
 * UserCenterFeignConfiguration for 自定義user-center服務請求中,feign的配置信息
 * {@link @Configuration} 不能添加該註解,不然會和ribbon同樣,出現上下文重疊問題,形成配置全局共享
 * 如要添加該註解,須要將該類放在主程序啓動掃描不到的包下
 *
 * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>
 * @since 2019/7/15
 */
public class UserCenterFeignConfiguration {
    @Bean
    public Logger.Level level() {
        // 配置feign 日誌級別,記錄請求和響應的header、body以及元數據
        return Logger.Level.FULL;
    }
}
  1. 必定要在配置文件中添加該client 全路徑spring

    logging:
      level:
       #com.sxzhongf: debug
        com.sxzhongf.sharedcenter.feignclients.IUserCenterFeignClient: debug
  2. 打印信息apache

2019-07-15 15:06:11.650 DEBUG 20286 --- [nio-8010-exec-1] c.s.s.f.IUserCenterFeignClient           : [IUserCenterFeignClient#findById] <--- HTTP/1.1 200 (402ms)
2019-07-15 15:06:11.651 DEBUG 20286 --- [nio-8010-exec-1] c.s.s.f.IUserCenterFeignClient           : [IUserCenterFeignClient#findById] content-type: application/json;charset=UTF-8
2019-07-15 15:06:11.651 DEBUG 20286 --- [nio-8010-exec-1] c.s.s.f.IUserCenterFeignClient           : [IUserCenterFeignClient#findById] date: Mon, 15 Jul 2019 07:06:11 GMT
2019-07-15 15:06:11.651 DEBUG 20286 --- [nio-8010-exec-1] c.s.s.f.IUserCenterFeignClient           : [IUserCenterFeignClient#findById] transfer-encoding: chunked
2019-07-15 15:06:11.652 DEBUG 20286 --- [nio-8010-exec-1] c.s.s.f.IUserCenterFeignClient           : [IUserCenterFeignClient#findById] 
2019-07-15 15:06:11.652 DEBUG 20286 --- [nio-8010-exec-1] c.s.s.f.IUserCenterFeignClient           : [IUserCenterFeignClient#findById] {"id":1,"wxId":"","wxNickname":"IsaacZhang","roles":"","avatarUrl":"aaa","createTime":"2019-07-11T06:08:18.000+0000","updateTime":"2019-07-11T06:08:18.000+0000","bonus":100}
2019-07-15 15:06:11.652 DEBUG 20286 --- [nio-8010-exec-1] c.s.s.f.IUserCenterFeignClient           : [IUserCenterFeignClient#findById] <--- END HTTP (173-byte body)

Configuration

支持的配置項

demo

使用配置文件來定義log leveljson

#logging:
  #level:
   #com.sxzhongf: debug
    #com.sxzhongf.sharedcenter.feignclients.IUserCenterFeignClient: debug
feign:
  client:
    config:
      user-center: #單服務配置
        loggerLevel: full
---        
feign:
  client:
    config:
      default: #全局配置日誌級別
        loggerLevel: full

Feign的繼承性

  • 官方不建議使用
  • 大多數公司使用?

架構師須要根據自身業務狀況來決定,是否須要將不一樣的微服務進行業務耦合,仍是使用冗餘代碼的方式來解放業務耦合性。性能優化

Feign多參請求

Get

  1. 使用@SpringQueryMap
@FeignClient(name = "user-center")
public interface ITestUserCenterFeignClient {

    @GetMapping("/users/q")
    public UserDTO query(@SpringQueryMap UserDTO userDTO);
}
  1. 使用 @RequestParam
@FeignClient(name = "user-center")
public interface ITestUserCenterFeignClient {

    @RequestMapping(value = "/users/q",method = RequestMethod.GET)
    public UserDTO query(@RequestParam("id") Long id,@RequestParam("name") String name);
}
  1. 使用Map構建,(不推薦)
@FeignClient(name = "user-center")
public interface ITestUserCenterFeignClient {

    @RequestMapping(value = "/users/q",method = RequestMethod.GET)
    public UserDTO query(@RequestParam Map<String,Object> conditions);
}

注意:這種方式不建議使用。主要是由於可讀性很差,並且若是參數爲空的時候會有一些問題,例如map.put("username", null); 會致使user-center 服務接收到的username是"" ,而不是null。架構

Post

服務提供者方法app

@PostMapping("/create")
    public User createUser(@RequestBody User user){
        return null;
    }

服務調用者微服務

@FeignClient(name = "user-center")
public interface ITestUserCenterFeignClient {

    @RequestMapping(value = "/users/q",method = RequestMethod.POST)
    public UserDTO query(@RequestBody UserDTO user);
}

Feign脫離服務註冊/Ribbon調用

@FeignClient(name = "xxxxx",url = "http://www.baidu.com")
public interface ITestBaiduFeignClient {

    @GetMapping("")
    public String getBaidu();
}

Feign 性能優化

使用鏈接池

httpClient

  1. 加依賴
<!--Feign 性能優化,須要使用鏈接池,引入依賴-->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>
  1. 加註解(不須要)
  2. 改配置
httpclient:
    # 爲feign啓用 apache httpclient 作請求,而不使用默認的urlconection
    enabled: true
    # feign 最大鏈接數
    max-connections: 200
    # feign 單個路徑請求的最大鏈接數
    max-connections-per-route: 50

okHttp

  1. 加依賴
<!--Feign 性能優化,須要使用鏈接池,引入依賴-->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-okhttp</artifactId>
        </dependency>
  1. 加註解(不須要)
  2. 改配置
httpclient:
    # 爲feign啓用 apache httpclient 作請求,而不使用默認的urlconection
    #enabled: true
    # feign 最大鏈接數
    max-connections: 200
    # feign 單個路徑請求的最大鏈接數
    max-connections-per-route: 50
  okhttp:
    enabled: true

合理使用Feign日誌

生產環境使用Logger.Level.BASIC

RestTemplate

RestTemplate VS. Feign

相關文章
相關標籤/搜索