OpenFeign

OpenFeign

https://docs.spring.io/spring-cloud-openfeign/docs/current/reference/html/

@GetMapping("/album/{id}")
public Album getById(@PathVariable int id){
//调用唱片微服务获取
String url="http://musicstore-albumservice/album/"+id;
Album album=restTemplate.getForObject(url,Album.class);
return album;
}

由上述的代码可以看出,我们以字符串拼接的方式构造URL的,该URL只有一个参数。但是,在现实
中,URL中往往含有多个参数。这时候我们如果还用这种方式构造URL,那么就会非常痛苦。那应该如何解决?

1.1Feign组件简介

一.什么是Feign?

Feign是一个声明式 Web 服务客户端。它使编写 Web 服务客户端更容易。要使用 Feign,创建一个接口并对其进行注解。它具有可插入的注释支持,包括 Feign 注释和 JAX-RS 注释。Feign 还支持可插拔的编码器和解码器。Spring Cloud 添加了对 Spring MVC 注解的支持,并支持使用HttpMessageConvertersSpring Web 中默认使用的注释。Spring Cloud 集成了 Eureka、Spring Cloud CircuitBreaker 以及 Spring Cloud LoadBalancer,在使用 Feign 时提供负载均衡的 http 客户端。

二.什么是声明式,有什么作用,解决什么问题?

  1. 声明式调用就像调用本地方法一样调用远程方法,无感知远程HTTP请求。

  2. SpringCloud的声明式调用,可以做到使用HTTP请求远程服务时就像调用本地方法一样的体验,开发者完全感知不到这是远程方法。更感知不到这是一个HTTP请求

  3. 它像Dubbo一样,consumer直接调用接口方法调用provider,而不需要通过常规的Http Client构造请求再解析返回数据。

4.它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细节,更无需关注分布式环境开发。

1.2基于Feign组件的服务调用

(1)复制消费者项目生成order-service-feign,添加feign坐标

<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>

(2)在服务消费者—订单服务启动类上添加注解,启动feign的支持

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients //通过@EnableFeignClients注解开启Spring Cloud Feign的支持功能
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class);
 }
}

(3)创建feign接口,支持FeignClient–调用服务的核心接口

在订单服务中创建接口ProductFeignClient用于调用远程的Product服务

//指定要调用的微服务的名称
@FeignClient(name = "product-service")
public interface ProductFeignClient {
    @GetMapping("/product")
    public String  queryProduct();
}

定义各参数绑定时,@PathVariable、@RequestParam、@RequestHeader等可以指定参数属性,在Feign中绑定参数必须通过value属性来指明具体的参数名,不然会抛出异常。
@FeignClient:注解通过name指定需要调用的微服务的名称,用于创建Ribbon的负载均衡器。所以Ribbon会把product-service解析为注册中心的服务。

(4)配置请求调用者的调用接口

修改订单控制器OrderController,注入ProductService,实现服务调用

@RestController
public class IndexController {
    @Autowired
    private ProductFeignClient productFeignClient;
    @RequestMapping("/order")
    public String order(){
         return productFeignClient.queryProduct();
    }
}

(5)测试结果

在浏览器中可以看到正确的调用结果 ,同时开启多个提供者

1.3Feign工作原理

1、 启动类添加@EnableFeignClients注解,Spring会扫描标记了@FeignClient注解的接口,并生成此接口的代理对象

2、 @FeignClient(value = “product-service”)即指定了要调用的服务名称,Feign会从注册中心获取product-service服务列表,并通过负载均衡算法进行服务调用。

3、在接口方法 中使用注解@GetMapping(“/product”)"),指定调用的url,Feign将根据url进行远程调用。

  • 主程序入口添加了@EnableFeignClients注解开启对FeignClient扫描加载处理。根据Feign Client的开发规范,定义接口并加@FeignClient注解。
  • 当程序启动时,会进行包扫描,扫描所有@FeignClients的注解的类,并且讲这些信息注入Spring IOC容器中,当定义的的Feign接口中的方法调用时,通过JDK的代理方式,来生成具体的RequestTemplate.当生成代理时,Feign会为每个接口方法创建一个RequestTemplate。当生成代理时,Feign会为每个接口方法创建一个RequestTemplate对象,改对象封装可HTTP请求需要的全部信息,如请求参数名,请求方法等信息都是在这个过程中确定的。
  • 然后RequestTemplate生成Request,然后把Request交给Client去处理,这里指的时Client可以时JDK原生的URLConnection,Apache的HttpClient,也可以时OKhttp,最后Client被封装到LoadBalanceClient类,这个类结合Ribbon负载均衡发器服务之间的调用。

1.3Feign和Ribbon的区别

Ribbon是一个基于 HTTP 和 TCP 客户端 的负载均衡的工具。它可以 在客户端 配置RibbonServerList(服务端列表),使用 HttpClient 或 RestTemplate 模拟http请求,步骤相当繁琐。
Feign 是在 Ribbon的基础上进行了一次改进,是一个使用起来更加方便的 HTTP 客户端。采用接口的方式, 只需要创建一个接口,然后在上面添加注解即可 ,将需要调用的其他服务的方法定义成抽象方法即可, 不需要自己构建http请求。然后就像是调用自身工程的方法调用,而感觉不到是调用远程方法,使得编写客户端变得非常容易.

1.4负载均衡

Feign中本身已经集成了Ribbon依赖和自动配置,因此我们不需要额外引入依赖,也不需要再注册RestTemplate 对象。分别以8081和8282启动两个产品服务productService,可以看到结果还是使用ribbon的轮询策略进行服务调用,实现负载均衡。
总结:从SpringCloud Edgware开始,Feign支持使用属性自定义Feign。对于一个指定名称的FeignClient可以设置名称,连接超时时间,日志级别,请求拦截等等。

1.5参数处理

Feign传参确保消费者和提供者的参数列表一致 包括返回值 方法签名要一致

1. 通过URL传参数,GET请求,参数列表使用@PathVariable(“”)

2. 如果是GET请求,每个基本参数必须加@RequestParam(“”)

3. 如果是POST请求,而且是对象集合等参数,必须加@Requestbody 或者@RequestParam

1.5.1产品服务

@GetMapping("/detail/{id}")
public String detail(@PathVariable("id")Integer id){
    return "商品详情,编号:"+id+"....8081";
}

@GetMapping("/add")
public String add(Integer id,String name){
    return "增加商品信息为:id="+id+",name="+name+"...8081";
}

1.5.2Feign接口

@GetMapping("/detail/{id}")
 String detail(@PathVariable("id")Integer id);

@GetMapping("/add")
 String add(@RequestParam("id") Integer id,@RequestParam("name") String name);

1.6超时配置

feign:
    client:
        config:   # 因为一个应用中 feign的客户端可以有很多 这里需要写具体的一个feign的名称
            default: # 写成default就是所有的客户端都通用
                connectTimeout: 5000
                readTimeout: 5000 # 默认的超时 5s

1.7日志功能

从前面的测试中我们可以看出,没有任何关于远程调用的日志输出,如请头,参数

Feign提供了日志打印功能,我们可以通过配置来调整日志级别,从而揭开Feign中Http请求的所有细节

NONE 默认的,不显示日志
BASE 仅记录请求方法,URL ,响应状态码及执行时间
HEADERS 在BASE之上增加了请求和响应头的信息
FULL 在HEADERS之上增加了请求和响应的正文及无数据

1.7.1添加日志配置类

@Configuration
public class FeignConfig {
    @Bean
    Logger.Level feignLogger() {
        return Logger.Level.FULL;
    }
}

1.7.2修改配置文件application.yml

feign:
    client:
        config:   # 因为一个应用中 feign的客户端可以有很多 这里需要写具体的一个feign的名称
            default: # 写成default就是所有的客户端都通用
                connectTimeout: 5000
                readTimeout: 5000 # 默认的超时 5s
                loggerLevel: HEADERS
logging:
  level:
    com.powernode.feign.ProductFeign: debug  # 默认只支持debug级别

1.7.3测试

一旦通过ProductFeign调用远程方法,控制台会打印日志信息

你可能感兴趣的:(spring,java,spring,cloud)