springboot+cloud 學習(二)應用間通訊Feign(僞RPC,實則HTTP)

在微服務中,使用什麼協議來構建服務體系,一直是個熱門話題。 爭論的焦點集中在兩個候選技術:  RPC or Restful前端

Restful架構是基於Http應用層協議的產物,RPC架構是基於TCP傳輸層協議的產物。web

網絡七層模型

在說RPC和HTTP的區別以前,瞭解一下七層網絡結構模型(雖然實際應用中基本上都是五層),它能夠分爲如下幾層: (從上到下)spring

  • 第一層:應用層。定義了用於在網絡中進行通訊和傳輸數據的接口;
  • 第二層:表示層。定義不一樣的系統中數據的傳輸格式,編碼和解碼規範等;
  • 第三層:會話層。管理用戶的會話,控制用戶間邏輯鏈接的創建和中斷;
  • 第四層:傳輸層。管理着網絡中的端到端的數據傳輸;
  • 第五層:網絡層。定義網絡設備間如何傳輸數據;
  • 第六層:鏈路層。將上面的網絡層的數據包封裝成數據幀,便於物理層傳輸;
  • 第七層:物理層。這一層主要就是傳輸這些二進制數據。

實際應用過程當中,五層協議結構裏面是沒有表示層和會話層的。應該說它們和應用層合併了。咱們應該將重點放在應用層和傳輸層這兩個層面。由於HTTP是應用層協議,而TCP是傳輸層協議。apache

RPC

RPC 即遠程過程調用(Remote Procedure Call Protocol,簡稱RPC),像調用本地服務(方法)同樣調用服務器的服務(方法)。一般的實現有 XML-RPC , JSON-RPC , 通訊方式基本相同, 所不一樣的只是傳輸數據的格式.springboot

RPC框架的主要目標就是讓遠程服務調用更簡單、透明。RPC框架負責屏蔽底層的傳輸方式(TCP或者UDP)、序列化方式(XML/JSON/二進制)和通訊細節。開發人員在使用的時候只須要了解誰在什麼位置提供了什麼樣的遠程服務接口便可,並不須要關心底層通訊細節和調用過程。服務器

Restful

REST即表述性狀態傳遞(Representational State Transfer,簡稱REST),是一種軟件架構風格。REST經過HTTP協議定義的通用動詞方法(GET、PUT、DELETE、POST) ,以URI對網絡資源進行惟一標識,響應端根據請求端的不一樣需求,經過無狀態通訊,對其請求的資源進行表述。知足REST約束條件和原則的架構,就被稱爲是RESTful架構.網絡

 

區別

使用RPC遠程服務調用方式與傳統http接口直接調用方式的差異在於:架構

1. 從使用方面看,Http接口只關注服務提供方(服務端),對於客戶端怎麼調用,調用方式怎樣並不關心,一般狀況下,客戶端使用Http方式進行調用時,只要將內容進行傳輸便可,這樣客戶端在使用時,須要更關注網絡方面的傳輸,比較不適用與業務方面的開發;而RPC服務則須要客戶端接口與服務端保持一致,服務端提供一個方法,客戶端經過接口直接發起調用,業務開發人員僅須要關注業務方法的調用便可,再也不關注網絡傳輸的細節,在開發上更爲高效。app

2. 從性能角度看,使用Http時,Http自己提供了豐富的狀態功能與擴展功能,但也正因爲Http提供的功能過多,致使在網絡傳輸時,須要攜帶的信息更多,從性能角度上講,較爲低效。而RPC服務網絡傳輸上僅傳輸與業務內容相關的數據,傳輸數據更小,性能更高。負載均衡

3. 從運維角度看,使用Http接口時,經常使用一個前端代理,來進行Http轉發代理請求的操做,須要進行擴容時,則須要去修改代理服務器的配置,較爲繁瑣,也容易出錯。而使用RPC方式的微服務,則只要增長一個服務節點便可,註冊中心可自動感知到節點的變化,通知調用客戶端進行負載的動態控制,更爲智能,省去運維的操做。

Feign

Feign 是一個聲明web服務客戶端,這便得編寫web服務客戶端更容易,使用Feign 建立一個接口並對它進行註解,它具備可插拔的註解支持包括Feign註解與JAX-RS註解,Feign還支持可插拔的編碼器與解碼器,Spring Cloud 增長了對 Spring MVC的註解,Spring Web 默認使用了HttpMessageConverters, Spring Cloud 集成 Ribbon 和 Eureka 提供的負載均衡的HTTP客戶端 Feign.

maven 多模塊下的Feign使用

目前個人項目中有2個模塊device和equip,每一個模塊因爲業務的須要拆分紅4部分(parent、client、common、server)

 

parent爲父項目,基本沒什麼代碼,會定義一些依賴做統一管理,其pom.xml以下

<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.skyworth.tvmanage</groupId>
    <artifactId>management-equip</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>equip</name>
    <description>equip servers</description>

    <modules>
        <module>management-equip-client</module>
        <module>management-equip-common</module>
        <module>management-equip-server</module>
    </modules>

    <!-- 必需要引入 springboot parent ,幫咱們實現了不少jar包的依賴管理 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <!-- 版本集中配置 -->
    <properties>
        <spring.cloud.version>Finchley.RELEASE</spring.cloud.version>
        <management-common.version>0.0.1-SNAPSHOT</management-common.version>
    </properties>

    <!-- cloud -->
    <dependencyManagement>
        <dependencies>
            <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.skyworth.tvmanage</groupId>
                <artifactId>management-equip-common</artifactId>
                <version>${management-common.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

server部分爲業務模塊,common爲一些公共調用的類,client部分定義向外暴露的接口,client部分pom.xml以下

<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>
  <parent>
    <groupId>com.skyworth.tvmanage</groupId>
    <artifactId>management-equip</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <!-- 向外暴露的接口 client -->
  <artifactId>management-equip-client</artifactId>
  <name>equip-client</name>
  <description>equip servers</description>
  
  <!-- 版本集中配置 -->
    <properties>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.skyworth.tvmanage</groupId>
            <artifactId>management-equip-common</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>
</project>

而後,再來看client接口的定義 ManagementEquipClient.class,  @FeignClient裏的名稱爲Eureka裏註冊的須要調用的服務名稱


@FeignClient("MANAGEMENT-EQUIP")
public interface ManagementEquipClient {
    
    @PostMapping("/tvmanage/equip/addEquip")
    public void addEquip(@RequestBody Equip equip);
    
    @RequestMapping(value="/tvmanage/equip/checkEquipExists", method=RequestMethod.GET)
    Integer checkEquipExists(@RequestParam String core,@RequestParam String type,@RequestParam String country);
    
    @RequestMapping(value="/tvmanage/equip/getDefaultScheme", method=RequestMethod.GET)
    Integer getDefaultScheme(@RequestParam String core,@RequestParam String type,@RequestParam String country);
}

 

因爲我這裏,feign是device調用equip,基本equip部分配置就差很少了,再來看看devcie部分,在device應用主類中經過@EnableFeignClients註解開啓Feign功能。

這裏須要注意的是@EnableFeignClients的掃包問題,就是***的地址要正確

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackages="****")
public class Application {
    public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
    }
}

而後在device部分的controller中,聲明equip服務,就能夠正常調用了

相關文章
相關標籤/搜索