springboot+cloud学习(⼆)应⽤间通信Feign(伪RPC,实则HTTP)
在微服务中,使⽤什么协议来构建服务体系,⼀直是个热门话题。争论的焦点集中在两个候选技术:  RPC or Restful
Restful架构是基于Http应⽤层协议的产物,RPC架构是基于TCP传输层协议的产物。
⽹络七层模型
在说RPC和HTTP的区别之前,了解⼀下七层⽹络结构模型(虽然实际应⽤中基本上都是五层),它可以分为以下⼏层:(从上到下)
第⼀层:应⽤层。定义了⽤于在⽹络中进⾏通信和传输数据的接⼝;
第⼆层:表⽰层。定义不同的系统中数据的传输格式,编码和解码规范等;
第三层:会话层。管理⽤户的会话,控制⽤户间逻辑连接的建⽴和中断;
springcloud难学吗第四层:传输层。管理着⽹络中的端到端的数据传输;
第五层:⽹络层。定义⽹络设备间如何传输数据;
第六层:链路层。将上⾯的⽹络层的数据包封装成数据帧,便于物理层传输;
第七层:物理层。这⼀层主要就是传输这些⼆进制数据。
实际应⽤过程中,五层协议结构⾥⾯是没有表⽰层和会话层的。应该说它们和应⽤层合并了。我们应该将重点放在应⽤层和传输层这两个层⾯。因为HTTP是应⽤层协议,⽽TCP是传输层协议。
RPC
RPC 即远程过程调⽤(Remote Procedure Call Protocol,简称RPC),像调⽤本地服务(⽅法)⼀样调⽤服务器的服务(⽅法)。通常的实现有 XML-RPC , JSON-RPC , 通信⽅式基本相同, 所不同的只是传输数据的格式.
RPC框架的主要⽬标就是让远程服务调⽤更简单、透明。RPC框架负责屏蔽底层的传输⽅式(TCP或者UDP)、序列化⽅式(XML/JSON/⼆进制)和通信细节。开发⼈员在使⽤的时候只需要了解谁在什么位置提供了什么样的远程服务接⼝即可,并不需要关⼼底层通信细节和调⽤过程。
Restful
REST即表述性状态传递(Representational State Transfer,简称REST),是⼀种软件架构风格。R
EST通过HTTP协议定义的通⽤动词⽅法(GET、PUT、DELETE、POST),以URI对⽹络资源进⾏唯⼀标识,响应端根据请求端的不同需求,通过⽆状态通信,对其请求的资源进⾏表述。满⾜REST约束条件和原则的架构,就被称为是RESTful架构.区别
使⽤RPC远程服务调⽤⽅式与传统http接⼝直接调⽤⽅式的差别在于:
1. 从使⽤⽅⾯看,Http接⼝只关注服务提供⽅(服务端),对于客户端怎么调⽤,调⽤⽅式怎样并不关⼼,通常情况下,客户端使⽤Http⽅式进⾏调⽤时,只要将内容进⾏传输即可,这样客户端在使⽤时,需要更关注⽹络⽅⾯的传输,⽐较不适⽤与业务⽅⾯的开发;⽽RPC服务则需要客户端接⼝与服务端保持⼀致,服务端提供⼀个⽅法,客户端通过接⼝直接发起调⽤,业务开发⼈员仅需要关注业务⽅法的调⽤即可,不再关注⽹络传输的细节,在开发上更为⾼效。
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为⽗项⽬,基本没什么代码,会定义⼀些依赖作统⼀管理,其l如下
<project xmlns="/POM/4.0.0"
xmlns:xsi="/2001/XMLSchema-instance"
xsi:schemaLocation="/POM/4.0.0 /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>
<!-- mvnrepository/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部分l如下
<project xmlns="/POM/4.0.0" xmlns:xsi="/2001/XMLSchema-instance" xsi:schemaLocation="/POM/4.0.0 /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服务,就可以正常调⽤了

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。