SpringCloud--OpenFeign--服务调用

OpenFeign–服务调用

1、Feign与OpenFeign

​ Feign英文表意为“假装,伪装,变形” ,是一个http请求调用的轻量级框架,属于NetFlix公司,和其他的NetFlix组件一样,已经宣布不再进行更新了。因此Spring社区在Feign的基础之上推出了OpenFeign, 对Feign进行增强支持Spring MVC注解,可以像Spring Web一样使用HttpMessageConverters等。 本质上来讲,二者都是完成服务调用的轻量级框架,使用方法也一致。

​ 在服务消费者中使用Feign,可以做到使用HTTP请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访问HTTP请求。

2、OpenFeign的使用

​ 第一步:pom依赖

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

​ 第二步:主启动类

@SpringBootApplication
//开启Feign功能支持
@EnableFeignClients
public class OrderFeignMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderFeignMain80.class,args);
    }
}

​ 第三步:书写服务接口

//表示当前FeignClient消费的服务是CLOUD-PAYMENT-SERVICE(Eureka上的服务名)
@FeignClient("CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {
    //服务提供者暴露出来的uri路径和访问方式
    @GetMapping(value = "/payment/get/{id}")
    //服务提供者暴露出来的方法声明
    CommonResult getPaymentById(@PathVariable("id") Long id);
}

​ 第四步:书写控制器

@RestController
public class OrderController {
    //自动装配服务接口
    @Autowired
    private PaymentFeignService paymentFeignService;
	
    //当用户访问此路径时,调用自己的服务接口
    //服务接口因为使用了@FeignClient注解,所以会根据配置请求:
    //http://CLOUD-PAYMENT-SERVICE/payment/get/{id}
    //因为Feign集成了Ribbon,Ribbon会做负载均衡,并且将服务名转化成真实的url地址完成调用
    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult getPaymentById(@PathVariable Long id){
        return paymentFeignService.getPaymentById(id);
    }
}

3、OpenFeign与RestTemplate

相同点

​ 1、本质上讲,二者都是用来向服务提供者发送http请求的工具

​ 2、二者本身都不具备负载均衡的能力

​ 3、向服务端发送请求时都是使用的服务名而非真实ip+port

​ 4、都是利用了Ribbon完成的负载均衡,地址转换等工作。

​ 5、默认情况下,都是采用轮询的方式完成负载均衡

不同点

​ 1、OpenFeign使用的是动态代理技术,RestTemplate使用的是拦截器技术。

​ 2、使用的注解不同,OpenFeign使用的是@EnableFeignClients和@FeigeClient;RestTemplate使用的是@LoadBalanced;

​ 3、OpenFeign本身已经继承了NetFlix Ribbon(并非Spring Cloud Ribbon),直接就可以使用Ribbon的负载均衡功能;RestTemplate只是Spring推出的一个类库,想要使用Ribbon的负载均衡功能,必须另外引入Spring Cloud Ribbon的依赖(经常是由Eureka间接引入的)。

优缺点对比

​ 1、 在使用RestTemplate来调用接口服务时,需要向方法传入服务提供者的接口地址,当接口地址较多时,不太方便管理。而OpenFeign通过一个服务接口把所有要调用的接口地址集中管理起来,这是一个比较好的管理方式。

​ 2、使用OpenFeign进行服务调用,我们不需要像使用RestTemplate那样关心调用哪一个方法、参数类型和返回值等问题,使用起来更加方便。

​ 3、OpenFeign是面向接口的编程方式,更加符合程序员的习惯,类似于三层架构中的controller调用service。

​ 所以实际开发当中,使用OpenFeign完成服务调用的场景比使用RestTemplate的场景要多得多

4、更换Ribbon的默认负载均衡策略

​ 因为OpenFeign和RestTemplate一样,都是和Ribbon搭配使用的,只不过一个采用了动态代理的方式,一个采用了拦截器的方式,最终负载均衡的工作都是交给Ribbon来做的,所以替换Ribbon默认负载均衡策略的方式也是一样的。如下:

​ 默认情况下,自动装配好的RestTemplate使用的负载均衡策略是轮询,即根据服务清单,一次访问各个服务实例。而Ribbon给我们提供的负载均衡策略不止轮询这一种,还有一些其他的策略:
SpringCloud--OpenFeign--服务调用_第1张图片

SpringCloud--OpenFeign--服务调用_第2张图片
​ 我们可以通过下面的步骤修改默认的轮询策略:

​ 第一步:创建配置类MySelfRuler

@Configuration
public class MySelfRuler {
    @Bean
    public IRule mySelfRule(){
        //将默认的轮询算法替换成随机算法
        //此处可以使用其他官方提供的算法,也可以自定义算法
        return new RandomRule();
    }
}

​ 第二步:在服务消费者主配置类上使用@RibbonClient注解

@SpringBootApplication
@EnableEurekaClient
//指明本服务是一个消费者,消费CLOUD-PAYMENT-SERVICE
//使用的配置为自定义配置MySelfRuler
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRuler.class)
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class,args);
    }
}

​ 但是要注意的是:

​ 官方给出明确警告,自定义的规则配置类不能@ComponentScan注解所在包及其子包下,否则自定义的配置类会被所有的Ribbon客户端共享,不能够起到服务特殊化定制的目的。对于单个的SpringBoot程序来讲,MySelfRuler不能放在主启动类所在包及其子包下。

5、OpenFeign的超时设置

​ 默认情况下,Feign发送的请求超时时间为1s,但是我们在实际开发中,可能有一些服务本身正常的调用时间就比较长,为了防止程序报错,针对这些这些服务的消费者,我们需要修改feign默认的超时时间,因为feign默认集成了Ribbon,我们可以通过设置Ribbon的超时时间来进行Feign的超时设置。如下:

ribbon:
	#连接成功后读取资源的超时时间(ms)
	ReadTimeout:  5000
	#建立连接的超时时间(ms)
	ConnectTimeout: 5000

6、OpenFeign的日志功能

​ Feign与RestTemplate不同的是,http请求详细信息封装的更深了,为了方便我们查看每一次发送的http请求信息详细信息,Feign给我们提供了日志功能。说白了就是对Feign接口的调用情况进行监控和输出。

日志级别

​ 指http请求信息的详细程度,分为四个等级:

​ NONE:默认,不显示任何日志

​ BASIC:仅记录请求方法、URL、响应状态码及执行时间

​ HEADERS:除了BASIC的内容之外,还有请求和响应的头信息

​ FULL:除了HEADERS的内容外,还有请求和响应的正文以及元数据。

​ OpenFeign使用的是slf4j作为日志门面,日志的实现根据整个项目确定。不同的日志级别底层采用的都是debug级别的输出,只不过不同的日志级别对应的输出内容数量不同。

如何修改Feign的日志级别:

​ 第一步:书写一个配置类,向容器中注入日志级别的bean

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignConfig {
    @Bean
    Logger.Level feignLoggerLevel(){
        //将默认的日志级别改为FULL
        return Logger.Level.FULL;
    }
}

​ 第二步:在配置文件中指明Feign接口日志的输出级别,必须为debug,因为Feign底层使用的是debug进行的日志输出。如果不指定,将使用全局统一的日志级别。

logging:
  level:
    com.ly.springcloud.service.PaymentFeignService: debug

​ 第三步:测试,使用Feign完成服务调用,控制台得到如下日志:(也可以根据日志配置,将此内容输出到配置文件中去)

[PaymentFeignService#getPaymentById] <--- HTTP/1.1 200 (291ms)
[PaymentFeignService#getPaymentById] connection: keep-alive
[PaymentFeignService#getPaymentById] content-type: application/json
[PaymentFeignService#getPaymentById] date: Fri, 31 Jul 2020 03:49:36 GMT
[PaymentFeignService#getPaymentById] keep-alive: timeout=60
[PaymentFeignService#getPaymentById] transfer-encoding: chunked
[PaymentFeignService#getPaymentById] 
[PaymentFeignService#getPaymentById] {"code":200,"message":"查询成功,port: 8001","data":{"id":2,"serial":"AAAAAAAAA"}}
[PaymentFeignService#getPaymentById] <--- END HTTP (85-byte body)

你可能感兴趣的:(分布式,微服务,SpringCloud,java,spring,spring,boot)