1. 程式人生 > >SpringCloud學習筆記五--Feign遠端呼叫及負載均衡

SpringCloud學習筆記五--Feign遠端呼叫及負載均衡

官網解釋:
http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign
 
 Feign是一個宣告式WebService客戶端。使用Feign能讓編寫Web Service客戶端更加簡單, 它的使用方法是定義一個介面,然後在上面添加註解,同時也支援JAX-RS標準的註解。Feign也支援可拔插式的編碼器和解碼器。Spring Cloud對Feign進行了封裝,使其支援了Spring MVC標準註解和HttpMessageConverters。Feign可以與Eureka和Ribbon組合使用以支援負載均衡。
 ;
 
 Feign是一個宣告式的Web服務客戶端,使得編寫Web服務客戶端變得非常容易,
只需要建立一個介面,然後在上面添加註解即可。
參考官網:https://github.com/OpenFeign/feign 
 


Feign旨在使編寫Java Http客戶端變得更容易。
前面在使用Ribbon+RestTemplate時,利用RestTemplate對http請求的封裝處理,形成了一套模版化的呼叫方法。但是在實際開發中,由於對服務依賴的呼叫可能不止一處,往往一個介面會被多處呼叫,所以通常都會針對每個微服務自行封裝一些客戶端類來包裝這些依賴服務的呼叫。所以,Feign在此基礎上做了進一步封裝,由他來幫助我們定義和實現依賴服務介面的定義。在Feign的實現下,我們只需建立一個介面並使用註解的方式來配置它(以前是Dao介面上面標註Mapper註解,現在是一個微服務介面上面標註一個Feign註解即可),即可完成對服務提供方的介面繫結,簡化了使用Spring cloud Ribbon時,自動封裝服務呼叫客戶端的開發量。
 
Feign集成了Ribbon
利用Ribbon維護了MicroCloud-Dept-8001的服務列表資訊,並且通過輪詢實現了客戶端的負載均衡。而與Ribbon不同的是,通過feign只需要定義服務繫結介面且以宣告式的方法,優雅而簡單的實現了服務呼叫


 下面就把我們Feign整合到我們的專案中

首先, 參考80專案新建microcloud-consumer-feign, 目錄結構如圖


修改部分:  啟動類名字

pom檔案新增依賴

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

修改microcloud-api工程

pom檔案新增依賴

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>

Dept.java修改, 使用lombok來代替我們生成構造方法及構造器訪問器和toString方法

@Data:  生成構造器訪問器和toString方法

@Accessors(chain=true):  支援鏈式注入

@NoArgsConstructor:  生成無參構造方法

package com.sedin.microcloudapi;

import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
 * @Description:部門類
 * @Auther: 陳歡
 * @Date: 2018/10/8 13:53
 */
@SuppressWarnings("serial")
@NoArgsConstructor
@Data
@Accessors(chain=true)
public class Dept implements Serializable {

    private Long deptno;
    private String dname;
    private String loc;

}

新建DeptClientService介面並新增註解@FeignClient

@FeignClient標籤的常用屬性如下:

  • name:指定FeignClient的名稱,如果專案使用了Ribbon,name屬性會作為微服務的名稱,用於服務發現
  • url: url一般用於除錯,可以手動指定@FeignClient呼叫的地址
  • decode404:當發生http 404錯誤時,如果該欄位位true,會呼叫decoder進行解碼,否則丟擲FeignException
  • configuration: Feign配置類,可以自定義Feign的Encoder、Decoder、LogLevel、Contract
  • fallback: 定義容錯的處理類,當呼叫遠端介面失敗或超時時,會呼叫對應介面的容錯邏輯,fallback指定的類必須實現@FeignClient標記的介面
  • fallbackFactory: 工廠類,用於生成fallback類示例,通過這個屬性我們可以實現每個介面通用的容錯邏輯,減少重複的程式碼
  • path: 定義當前FeignClient的統一字首
package com.sedin.microcloudapi.service;

import com.sedin.microcloudapi.Dept;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.List;

/**
 * @Description: feign遠端呼叫介面
 * @Author: 陳歡
 * @Date: 2018/10/12 14:46
 */
@FeignClient(value = "MICROCLOUDPROVIDERDEPT8001")
public interface DeptClientService {

    @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET)
    public Dept get(@PathVariable("id") long id);

    @RequestMapping(value = "/dept/list", method = RequestMethod.GET)
    public List<Dept> list();

    @RequestMapping(value = "/dept/add", method = RequestMethod.POST)
    public boolean add(Dept dept);
}

因為新增了內容, 所以需要我們maven重新編譯和打包到本地, 切記別忘了

第二步,  修改新新增的microcloud-consumer-feign工程, 修改controller

package com.sedin.microcloudconsumerFeign.controller;

import com.sedin.microcloudapi.Dept;
import com.sedin.microcloudapi.service.DeptClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.List;

/**
 * @Description: feign遠端呼叫介面
 * @Author: 陳歡
 * @Date: 2018/10/8 15:54
 */
@RestController
public class ConsumerDeptController_Feign {

    @Resource
    private DeptClientService deptClientService;

    @RequestMapping(value = "/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id)
    {
        return this.deptClientService.get(id);
    }

    @RequestMapping(value = "/consumer/dept/list")
    public List<Dept> list()
    {
        return this.deptClientService.list();
    }

    @RequestMapping(value = "/consumer/dept/add")
    public Object add(Dept dept)
    {
        return this.deptClientService.add(dept);
    }


}

修改啟動類, 新增@EnableFeignClients註解, @ComponentScan註解

@EnableFeignClients: 通過FeignClientsRegistrar類實現掃描並註冊feign client

注:  @ComponentScan註解用於元件掃描, 這個地方要求我們能夠同時掃描到api工程下新建的service和此工程下的controller,

否則呼叫介面會報錯

package com.sedin.microcloudconsumerFeign;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = "com.sedin.microcloudapi")
@ComponentScan("com.sedin")
public class MicrocloudConsumerFeignApplication {

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

最後,  啟動3個eureka叢集,  啟動3個部門微服務8001/8002/8003,  啟動Feign, 測試http://localhost/consumer/dept/list,  Feign自帶負載均衡配置項

 Feign通過介面的方法呼叫Rest服務(之前是Ribbon+RestTemplate),
該請求傳送給Eureka伺服器(http://MICROCLOUDPROVIDERDEPT8001/dept/list),
通過Feign直接找到服務介面,由於在進行服務呼叫的時候融合了Ribbon技術,所以也支援負載均衡作用。