1. 程式人生 > >四、SpringCloud之Feign

四、SpringCloud之Feign

      spring cloud的Netflix中提供了兩個元件實現軟負載均衡呼叫:ribbon和feign。本例主要講解feign的適用,如需瞭解ribbon的適用,可以返回上一章進行閱讀。

Ribbon 是一個基於 HTTP 和 TCP 客戶端的負載均衡器 它可以在客戶端配置 ribbonServerList(服務端列表),然後輪詢請求以實現均衡負載。

Feign Spring Cloud Netflix 的微服務都是以 HTTP 介面的形式暴露的,所以可以用 Apache 的 HttpClient 或 Spring 的 RestTemplate 去呼叫,而 Feign 是一個使用起來更加方便的 HTTP 客戶端,使用起來就像是呼叫自身工程的方法,而感覺不到是呼叫遠端方法。

spring-cloud-starter-feign 裡面已經包含了 spring-cloud-starter-ribbon(Feign 中也使用了 Ribbon)

一、pom引入

<!--feign相關-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>
        <!-- Ribbon相關  Spring Cloud Ribbon是基於Netflix Ribbon實現的一套客戶端負載均衡的工具。-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
        </dependency>
        <!--Ribbon相關end-->

二、配置檔案application.yml編寫(和上一章ribbon的編寫相同)

server:
  port: 8080

#從eureka中獲取微服務
eureka:
  client:
    register-with-eureka: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

三、介面DeptClientService編寫,為了考慮複用性,解除安裝了公共模組api中

package com.zhanghf.springcloud.service;

import com.zhanghf.springcloud.entities.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: 修改microservicecloud-api工程,根據已經有的DeptClientService介面
 * Created by YQ11053 on 2018/10/5 0005.
 */
@FeignClient(value = "MICROSERVICECLOUD-DEPT")
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);
}

使用FeignClient註解,value為微服務提供者的名稱,需要和微服務提供者配置類appiication.yml中的命名一樣。

四、controller中

package com.zhanghf.springcloud.controller;

import com.zhanghf.springcloud.entities.Dept;
import com.zhanghf.springcloud.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 java.util.List;

/**
 * Created by YQ11053 on 2018/9/26 0026.
 */
@RestController
public class DeptController_Consumer {

    @Autowired
    DeptClientService deptClientService;

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

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

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

}

特此貼出使用ribbon的時候的controller中程式碼如下:

package com.zhanghf.springcloud.controller;

import com.zhanghf.springcloud.entities.Dept;
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 java.util.List;

/**
 * Created by YQ11053 on 2018/9/26 0026.
 */
@RestController
public class DeptController_Consumer {

//    private static final String REST_URL_PREFIX = "http://localhost:8001";
      private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT";

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping(value = "/consumer/dept/add")
    public boolean add(Dept dept)
    {
        return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
    }

    @RequestMapping(value = "/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id)
    {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class);
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/consumer/dept/list")
    public List<Dept> list()
    {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
    }

    // 測試@EnableDiscoveryClient,消費端可以呼叫服務發現
    @RequestMapping(value = "/consumer/dept/discovery")
    public Object discovery()
    {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/discovery", Object.class);
    }
}

使用feign時通過注入deptClientService來進行各種方法的呼叫,其餘工作都在介面中實現,而ribbon是通過RestTemplate 類實現。

五、啟動類

package com.zhanghf;

import com.myrule.MySelfRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.ComponentScan;


@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages= {"com.zhanghf.springcloud"})
@ComponentScan("com.zhanghf.springcloud")
public class DeptConsumer80_Feign
{
    public static void main( String[] args )
    {
        SpringApplication.run(DeptConsumer80_Feign.class,args);
    }
}

如果也需要進行負載均衡策略的調整或者自定義的話使用方法如上一章ribbon的介紹。