1. 程式人生 > >SpringCloud進擊 | 三淺出:服務消費者(Feign)【Finchley版本】

SpringCloud進擊 | 三淺出:服務消費者(Feign)【Finchley版本】


1.前言

上一節:SpringCloud進擊 | 二淺出:服務消費者(Ribbon+REST)【Finchley版本】

上一節講述瞭如何通過 Ribbon + RestTemplate 的方式去消費服務,而在實際工作中,我們基本上都是使用 Feign 來完成呼叫。這篇就來說說如何通過 Feign 實現服務消費者去消費服務。

Feign 預設集成了 Ribbon,並和 Eureka 結合,預設實現了負載均衡的效果。其特點有:

  • 可插拔的註解支援
  • 支援可插拔的 HTTP 編碼器和解碼器
  • 支援 Hystrix 和它的 Fallback
  • 支援 Ribbon 的負載均衡
  • 支援 HTTP 請求和響應的壓縮

 

2.準備

三個角色,依舊使用上面章節已經建立好的工程:

  • 服務註冊中心:wei-eureka-server,啟動一個
  • 服務提供者:wei-service-provider,分別以 8010、8011 埠啟動一次,獲得兩個例項的叢集
  • 服務消費者:Feign,建立一個 wei-consumer-feign 模組

 

3.實踐

3.1 建立服務消費者(Feign)

在專案上新建一個模組:wei-consumer-feign,建立方法與第一節建立模組過程類似。但在Dependencies選擇依賴時需要注意以下:
a)

 選擇左側的 Web 後,這裡需要鉤上 Web 項
b) 選擇左側的 Cloud Discovery 後,這裡需要鉤上 Eureka Discovery 項
c) 選擇左側的 Cloud Routing後,這裡需要鉤上 Feign 項 

最後點Finish後,一個模組就自動生成了,其 pom.xml 全內容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wei</groupId>
    <artifactId>wei-consumer-feign</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>wei-consumer-feign</name>
    <description>服務消費者(Feign)(Finchley版本)</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--Feign實現宣告式HTTP客戶端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

3.2 配置服務消費者

■ 編寫配置 application.yml

server:
  port: 8030
spring:
  application:
    name: wei-cloud-feign    # 指定進行服務註冊時該服務的名稱,服務與服務之間相互呼叫一般都是根據這個name
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8090/eureka/    # 指定進行服務註冊的地址

這裡,指定的服務註冊中心地址為 http://localhost:8090/eureka/,服務名稱為:wei-consumer-feign,程式埠為:8030,spring.application.name:指定進行服務註冊時該服務的名稱,服務與服務之間相互呼叫一般都是根據這個name。

■ 編寫配置Service

package com.wei.service.demo;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * 通過@FeignClient("Eureka服務名稱"),來指定呼叫消費哪個服務
 */
@FeignClient(value = "wei-service-provider")
public interface IDemoFeignService {

    /**
     * 註解@RequestMapping,對映服務提供者中的URL
     * @param name 入參
     * @return
     */
    @RequestMapping(value = "/demo/info", method = RequestMethod.GET)
    String getDemoFeignServiceName(@RequestParam(value = "name") String name);

    // Feign客戶端和Ribbon類似,同樣實現了客戶端的負載均衡
    // 與Ribbon不同的是,Feign的呼叫與本地介面的呼叫更加類似,並且更加便捷、更加優雅,傳入引數較多時得以體現
}

注意,這個 Service 是一個介面類。通過@FeignClient("Eureka服務提供者名稱"),來指定呼叫和消費哪個服務提供者。當前配置是消費服務提供者 wei-service-provider 的 “/demo/info” 介面。

■ 編寫配置Controller

package com.wei.controller.demo;

import com.wei.service.demo.IDemoFeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoFeignController {

    /**
     * 編譯器報錯,無視。因為這個Bean是在程式啟動的時候注入的,編譯器感知不到,所以報錯
     */
    @Autowired
    private IDemoFeignService iDemoFeignService;

    @RequestMapping(value = {"/feign/demo/info", "/demo/info"}, method = RequestMethod.GET)
    public String getDemoFeignName(@RequestParam(value = "name") String name) {
        String result = iDemoFeignService.getDemoFeignServiceName(name);
        result += "[Feign]";
        System.out.println(result);
        return result;
    }
}

具體使用時,通過 Service層,呼叫服務提供者的方法就像呼叫本地方法一樣進行呼叫即可。

■ 配置main啟動類

package com.wei;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * 註解@EnableFeignClients,開啟Feign客戶端功能
 */
@SpringBootApplication
@EnableFeignClients
public class WeiConsumerFeignApplication {

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

以前使用註解@EnableDiscoveryClient向服務中心註冊,因為Eureka2.0已經不需要,所以這裡可以不用該註解。

通過 Spring Cloud Feign 來實現服務呼叫的方式非常簡單,註解 @EnableFeignClients 即可開啟 Feign 客戶端功能。

 

最後,Run一下這個啟動類。我們再去 Spring Eureka 的服務註冊資訊面板,看一看這個服務消費者有沒有被Eureka所發現並註冊進去。

看來,一切正常。

 

3.3 驗證服務消費者

好了,一切準備就緒。我們就來驗證一下吧:

瀏覽器反覆請求URL:http://localhost:8030/demo/info?name=tester 或者 http://localhost:8030/feign/demo/info?name=tester

Hi,tester,我是服務,我被呼叫了,服務名為:wei-service-provider,埠為:8010[Feign]

Hi,tester,我是服務,我被呼叫了,服務名為:wei-service-provider,埠為:8011[Feign]

我們可以看到瀏覽器也在8010和8011埠之間,也就是這個小的Service服務提供者叢集之間交替列印輸出內容。

到此,Feign 的負載均衡功能驗證成功。論點2成立。

 

4.總結

Feign 客戶端和 Ribbon 類似,同樣實現了客戶端的負載均衡,但與 Ribbon 不同的是,Feign 的呼叫與本地介面的呼叫更加類似,並且更加便捷、更加優雅,傳入引數較多時得以體現。

4.1 案例中有三個角色:

     服務註冊中心、服務提供者、服務消費者

4.2 它們的工作流:

  1. 啟動服務註冊中心
  2. 服務提供者 生產服務並註冊到服務中心 
  3. 服務消費者 從服務中心中獲取服務並使用

4.3 此時的架構圖:

 


原始碼:https://github.com/itanping/wei-springcloud/tree/master/chapter03-feign

下一節,請關注:SpringCloud進擊 | 四淺出:斷路器(Hystrix)【Finchley版本】