Feign declarative service invocation

Feign 声明式服务调用

一、feign介绍

1、什么是feign?

feign是spring cloud提供的声明式的http客户端,工作在consumer端
feign支持springmvc注解
feign集成了Ribbon也支持负载均衡
(ribbon+restTemplate)+优化=feign

2、feign的启动器

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

二、Feign的入门案例

1、创建provicer模块

provicer测试controller

@RestController
@RequestMapping("/provider")
public class ProviderController {
	
	@Autowired
	private UserService userService;
	
	//restful风格传参
	@RequestMapping("/getUserById/{id}")
	public User getUserById(@PathVariable Integer id){
		return userService.getUserById(id);
	}
	//拼接传参
	@RequestMapping("/getUserById")
	public User getUserByIdRequestParam(@RequestParam("id") Integer id){
		return userService.getUserById(id);
	}
	//接收对象
	@RequestMapping("/getUser")
	public User getUser(@RequestBody User user) {
		return userService.getUser(user);
	}
}

provicer测试UserService接口类

public interface UserService {

    User getUserById(Integer id);

    User getUserByIdRequestParam(Integer id);

    User getUser(User user);
}

provicer测试UserServiceImpl实现类

@Service
public class UserServiceImpl implements UserService {

	@Override
	public User getUserById(@RequestParam("id") Integer id) {
		return new User(id,"zs",22);
	}

    @Override
    public User getUserByIdRequestParam(Integer id) {
        return new User(id,"zs",22);
    }

    @Override
    public User getUser(User user){
        return user;
    }
}

启动类

@SpringBootApplication
@EnableDiscoveryClient//向注册中心注册该服务,并可以获取其他服务的调用地址
public class FeignProviderApp {
    public static void main(String[] args) {
        SpringApplication.run(FeignProviderApp.class,args);
    }
}

appliction.yml 配置文件

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.112.130:8848 #nacos服务的地址
  application:
    name: feign-provider #向注册中心注册的名字
server:
  port: 9090

创建 feign接口模块

feign接口类

@FeignClient("feign-provider")
@RequestMapping("/provider")
public interface UserFeign {

    @RequestMapping("/getUserById/{id}")
    User getUserById(@PathVariable("id") Integer id);

    @RequestMapping("/getUser")
    User getUser(@RequestBody User user);
}

feign的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">
    <parent>
        <artifactId>springbootCloud-parent</artifactId>
        <groupId>com.alibaba</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>feign_interface</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <!--nacos客户端-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--Spring Cloud OpenFeign Starter -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        
        <dependency>
            <groupId>com.bjpowernode</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
<!--        http连接池-->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>
    </dependencies>
</project>

创建consumer模块

consumer测试Usercontroller类

@RestController
@RequestMapping(value = "/consumer")
public class ConsumerController {

	@Autowired
	private UserFeign userFeign;

	@RequestMapping(value="/getUserById/{id}")
	public User getUserById(@PathVariable Integer id){
		return userFeign.getUserById(id);
	}
	@RequestMapping(value="/getUserById")
	public User getUserByIdRequestParam(@RequestParam("id") Integer id){
		return userFeign.getUserById(id);
	}
	@RequestMapping(value="/getUser")
	public User getUserById(@RequestBody User user){
		return userFeign.getUser(user);
	}
}

启动类

@SpringBootApplication
@EnableDiscoveryClient //启动feign客户端
@EnableFeignClients //feign扫描它自己的注解
public class FeignConsumerApp {
    public static void main(String[] args) {
        SpringApplication.run(FeignConsumerApp.class,args);
    }
}

application.yml 配置文件

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.112.130:8848 #nacos服务的地址
  application:
    name: feign-consumer #向注册中心注册的名字

server:
  port: 80
  compression:
    enabled: true #开启gzip压缩
#feign优化日志配置
feign:
  client:
    config:
      default:
        loggerLevel: full
#设置全局日志输出登记为debug级别配合feign日志输出
logging:
  level:
    com.bjpowernode.feign: debug
#feign对于超时的优化
ribbon:
  ConnectTimeout: 5000 #请求连接的超时时间
  ReadTimeout: 5000 #请求处理的超时时间

@EnableFeignClients 单独领出来说一下这个注解:一张图即可看懂
请添加图片描述

feign的传参方式

有上面的入门案例consumer测试Usercontroller类中可以看出三种传参方式,也是最常用的传参方式

  1. restful 传参:
    使用@PathVariable 注解接收路径中的参数。在feign接口类中注意,此时的@PathVariable 与
    consumer测试Usercontroller类 中的 @PathVariable 的作用完全不同,因为没有直接的Template的参与,路径
    需要feign自己进行路径拼接,所以此时的@Pathvariable 注解是为了给feign自己指明拼接方式。

  2. 路径拼接传参:
    使用@RequestParam 注解指明拼接方式

  3. 对象传参:
    使用 @RequestBody 注解指明拼接方式,
    注意:此时的对象传参是按照Json形式传参

此时小伙伴指定满头的问号?这什么东西就这就能远程调用了?
接下来刚给大家看一下我自己理解的feign远程调用原理

feign的原理

  1. 在未产生调用前,feign 首先进行指定包下的注解检索,如图
    请添加图片描述
  2. 通过实现远程调用的只有一个feign的接口,所以大概率使用的是类似Mybatis的代理方式,果不其然:
    请添加图片描述
  3. 代理类通过SynchronousMethodHandler.invoke()进行远程调用请添加图片描述
  4. 代理类会通过RequestTemplate创建Request,并且发送请求
    请添加图片描述
    主要就这了,不明白的小伙伴自己写个Demo测试跑跑看就明白了。

feign的优化

众所周知http协议三次握手四次挥手都比较慢,为什么还要用基于http协议的feign呢?为什么不用dubbo呢?

  • 从协议上来讲:
    Feign更加优雅简单,Feign通过REST API实现的远程调用,基于http协议,服务提供者可以直接对外暴露接口,
    供服务消费者直接调用。
    Dubbo是通过RPC实现的远程调用,支持多种传输协议,可以在更多的场景选择最适合的传输协议。

  • 负载均衡来讲:
    Feign默认使用了Ribbon作为负载均衡组件,使用方便
    Dubbo也同样支持负载均衡,但是支持的组件更加灵活

  • 当然还可以从通信性能,容错机制等等其他方面来对比feign这里就不再啰嗦,如果有想要研究的小伙伴可以自行百度,
    结果就是各有千秋,看小伙伴想学哪一种了。推荐使用feign,原因嘛就是毕竟全家桶。

  1. 日志优化
    此优化主要是为了更清晰的看到传参内容,以及请求头,请求体,请求路径,请求方法和响应头,响应体等等内容效果图如下:

请添加图片描述
2. 超时优化
此优化是为了处理feign连接超时的问题,毕竟http协议,当高并发的情况下很有可能会出现请添加图片描述
这个异常,所以还是需要配置一下的

  1. 连接池优化
    此优化为了提高feign的工作效率
    请添加图片描述

  2. gzip压缩优化
    无所多言,gzip 真香
    请添加图片描述

优化方式在consumer模块的application.yml 配置文件中,有需要的小伙伴可以自行CV,
注意超时和日志优化有的编辑器是不会提示的哦,

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值