1. 程式人生 > 實用技巧 >Feign:負載均衡(基於服務端)

Feign:負載均衡(基於服務端)

摘自狂神說筆記!

7.1 Feign簡介

Feign是宣告式Web Service客戶端,它讓微服務之間的呼叫變得更簡單,類似controller呼叫service。SpringCloud集成了Ribbon和Eureka,可以使用Feigin提供負載均衡的http客戶端

只需要建立一個介面,然後添加註解即可~

Feign,主要是社群版,大家都習慣面向介面程式設計。這個是很多開發人員的規範。呼叫微服務訪問兩種方法

  1. 微服務名字 【ribbon】

  2. 介面和註解 【feign】

Feign能幹什麼?

  • Feign旨在使編寫Java Http客戶端變得更容易

  • 前面在使用Ribbon + RestTemplate

    時,利用RestTemplate對Http請求的封裝處理,形成了一套模板化的呼叫方法。但是在實際開發中,由於對服務依賴的呼叫可能不止一處,往往一個介面會被多處呼叫,所以通常都會針對每個微服務自行封裝一個客戶端類來包裝這些依賴服務的呼叫。所以,Feign在此基礎上做了進一步的封裝,由他來幫助我們定義和實現依賴服務介面的定義,在Feign的實現下,我們只需要建立一個介面並使用註解的方式來配置它 (類似以前Dao介面上標註Mapper註解,現在是一個微服務介面上面標註一個Feign註解),即可完成對服務提供方的介面繫結,簡化了使用Spring Cloud Ribbon 時,自動封裝服務呼叫客戶端的開發量。

Feign預設集成了Ribbon

  • 利用Ribbon維護了MicroServiceCloud-Dept的服務列表資訊,並且通過輪詢實現了客戶端的負載均衡,而與Ribbon不同的是,通過Feign只需要定義服務繫結介面且以宣告式的方法,優雅而簡單的實現了服務呼叫。

7.2 Feign的使用步驟

  1. 建立springcloud-consumer-fdept-feign模組

    拷貝springcloud-consumer-dept-80模組下的pom.xml,resource,以及java程式碼到springcloud-consumer-feign模組,並新增feign依賴。

    <!--Feign的依賴-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-feign</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    

      

    通過Ribbon實現:—原來的controller:DeptConsumerController.java

    /**
     * @Auther: csp1999
     * @Date: 2020/05/17/22:44
     * @Description:
     */
    @RestController
    public class DeptConsumerController {
    ​
        /**
         * 理解:消費者,不應該有service層~
         * RestTemplate .... 供我們直接呼叫就可以了! 註冊到Spring中
         * (地址:url, 實體:Map ,Class<T> responseType)
         * <p>
         * 提供多種便捷訪問遠端http服務的方法,簡單的Restful服務模板~
         */
        @Autowired
        private RestTemplate restTemplate;
    ​
        /**
         * 服務提供方地址字首
         * <p>
         * Ribbon:我們這裡的地址,應該是一個變數,通過服務名來訪問
         */
    //    private static final String REST_URL_PREFIX = "http://localhost:8001";
        private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";
    ​
        /**
         * 消費方新增部門資訊
         * @param dept
         * @return
         */
        @RequestMapping("/consumer/dept/add")
        public boolean add(Dept dept) {
            // postForObject(服務提供方地址(介面),引數實體,返回型別.class)
            return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
        }
    ​
        /**
         * 消費方根據id查詢部門資訊
         * @param id
         * @return
         */
        @RequestMapping("/consumer/dept/get/{id}")
        public Dept get(@PathVariable("id") Long id) {
            // getForObject(服務提供方地址(介面),返回型別.class)
            return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class);
        }
    ​
        /**
         * 消費方查詢部門資訊列表
         * @return
         */
        @RequestMapping("/consumer/dept/list")
        public List<Dept> list() {
            return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
        }
    }
    

      

    通過Feign實現:—改造後controller:DeptConsumerController.java

    /**
     * @Auther: csp1999
     * @Date: 2020/05/17/22:44
     * @Description:
     */
    @RestController
    public class DeptConsumerController {
    ​
        @Autowired
        private DeptClientService deptClientService;
    ​
        /**
         * 消費方新增部門資訊
         * @param dept
         * @return
         */
        @RequestMapping("/consumer/dept/add")
        public boolean add(Dept dept) {
            return deptClientService.addDept(dept);
        }
    ​
        /**
         * 消費方根據id查詢部門資訊
         * @param id
         * @return
         */
        @RequestMapping("/consumer/dept/get/{id}")
        public Dept get(@PathVariable("id") Long id) {
           return deptClientService.queryById(id);
        }
    ​
        /**
         * 消費方查詢部門資訊列表
         * @return
         */
        @RequestMapping("/consumer/dept/list")
        public List<Dept> list() {
            return deptClientService.queryAll();
        }
    }
    

      

    Feign和Ribbon二者對比,前者顯現出面向介面程式設計特點,程式碼看起來更清爽,而且Feign呼叫方式更符合我們之前在做SSM或者SprngBoot專案時,Controller層呼叫Service層的程式設計習慣!

    主配置類

    /**
     * @Auther: csp1999
     * @Date: 2020/05/17/22:47
     * @Description:
     */
    @SpringBootApplication
    @EnableEurekaClient
    // feign客戶端註解,並指定要掃描的包以及配置介面DeptClientService
    @EnableFeignClients(basePackages = {"com.haust.springcloud"})
    // 切記不要加這個註解,不然會出現404訪問不到
    //@ComponentScan("com.haust.springcloud")
    public class FeignDeptConsumer_80 {
        public static void main(String[] args) {
            SpringApplication.run(FeignDeptConsumer_80.class, args);
        }
    }
    

      

  2. 改造springcloud-api模組

    pom.xml新增feign依賴

    <!--Feign的依賴-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-feign</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    

      

    新建service包,並新建DeptClientService.java介面,

    // @FeignClient:微服務客戶端註解,value:指定微服務的名字,這樣就可以使Feign客戶端直接找到對應的微服務
    @FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")
    public interface DeptClientService {
    ​
        @GetMapping("/dept/get/{id}")
        public Dept queryById(@PathVariable("id") Long id);
    ​
        @GetMapping("/dept/list")
        public Dept queryAll();
    ​
        @GetMapping("/dept/add")
        public Dept addDept(Dept dept);
    }
    

      

7.3 Feign和Ribbon如何選擇?

根據個人習慣而定,如果喜歡REST風格使用Ribbon;如果喜歡社群版的面向介面風格使用Feign.

Feign 本質上也是實現了 Ribbon,只不過後者是在呼叫方式上,為了滿足一些開發者習慣的介面呼叫習慣!

下面我們關閉springcloud-consumer-dept-80 這個服務消費方,換用springcloud-consumer-dept-feign(埠還是80) 來代替:(依然可以正常訪問,就是呼叫方式相比於Ribbon變化了)