springcloud:微服务如何通信?组件通信组件:feign详解(六)

0. 引言

上一期我们搭建了网关和配置中心、注册中心。如果还没有看过往期文章的可以先了解:
springcloud:什么是分布式微服务,如何学习微服务(一)
springcloud:微服务涉及哪些技术、有哪些核心组件(二)
springcloud:网关组件gateway详解(三)
springcloud:注册中心、配置中心组件nacos详解(四)
springcloud:保姆式教程-从零搭建微服务(五)

但是还有一个核心问题没有解决,那就是微服务间的通信问题。比如我们订单服务中需要调用商品列表数据,而商品列表数据是在商品服务中获取的,那么我们就需要在订单服务中调用商品服务的接口。这种服务间调用,就称为组间通信

目前常用的组件通信有RestTemplate和feign。RestTemplate的使用相对比较麻烦,需要写上服务IP等比较底层的信息,而feign则不需要,更加符合本地调用的方式。

本着最核心技术快速上手的理念,我们先针对更加常用的feign组件进行讲解。后续再详谈RestTemplate

1. Feign简介

Feign是声明式的web service客户端,它让服务间的调用更加简单。使得整个调用变得像本地调用一样简单。

Feign中包含了Hystrix和ribbon。所以feign支持接口负载均衡,以及接口的熔断、降级、限流等处理。并且支持Http请求和响应的压缩。
在这里插入图片描述

2. Feign使用

1、要使用feign,我们需要引入feign的依赖

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

需要注意的是,Feign默认是POST请求,如果要支持带参数的GET请求,那么还需要引入feign-httpclient依赖

<dependency>
     <groupId>io.github.openfeign</groupId>
     <artifactId>feign-httpclient</artifactId>
</dependency>

同时因为是web api,那么肯定还要引入Spring web依赖,已经引入过就不用重复引用了

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId> 
</dependency>

2、在调用方服务的启动类中添加注解@EnableFeignClients

2.1 通过IP直接调用服务

直接通过IP来调用的话只需要在调用方的服务中创建Feign接口类。其中name是服务名,url是实际的接口地址,如果有多个可以用逗号隔开

扫描二维码关注公众号,回复: 13824938 查看本文章

接口中书写的是对应到controller的URL地址。比如说用户controller中有一个list接口,url是list。那么Feign接口类中对应的方法也要和controller中的接口地址保持一致

@FeignClient(name = "order-server",url = "localhost:8081")
public interface OrderApi {
    
    @GetMapping("list")
    public List<Order> list();
    
}

有一个注意的点,如果controller中统一的接口前缀,比如说/user。在feign接口类中是不能通过@RequestMapping来申明的,而是必须在每个方法中添加上这个前缀,如下所示:

@FeignClient(name = "order-server",url = "localhost:8081")
public interface OrderApi {

    String PREFIX = "order";
    String LIST = PREFIX + "/list";
    String PAGE = PREFIX + "/page";

    @GetMapping(LIST)
    public List<Order> list();

    @GetMapping(PAGE)
    public List<Order> page();
    
}

2.2 通过nacos调用

直接使用服务名即可,无需定义url。在调用方中创建该接口即可

@FeignClient(name = "product-server",url = "localhost:9091")
public interface ProductApi {

    @GetMapping("list")
    public List<Product> list();
}

测试

我们基于上节课搭建的springcloud项目来进行测试,为了不影响上节课的代码,单独创建一个springcloud2用于本章测试

1、在order-server服务中引入依赖

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.2.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
            <version>10.10.1</version>
        </dependency>
        <-- 因为要使用Product实体类,所以需要引入product-server -->
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>product-server-feign</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>

2、在order-server中创建ProductApi接口类

@FeignClient(name = "product-server",url = "localhost:9091")
public interface ProductApi {

    @GetMapping("list")
    public List<Product> list();
}

3、在order-server启动类中添加@EnableFeignClients注解

4、在在order-server的OrderController中创建接口用于调用feign接口类中的方法

@RestController
@AllArgsConstructor
public class OrderController {
    private final IOrderService orderService;
    private final ProductApi productApi;

    @GetMapping("list")
    public List<Order> list(){
        return orderService.list();
    }

    @GetMapping("listProduct")
    public List<Product> listProduct(){
        return productApi.list();
    }

}

5、测试访问http://localhost/order-server/listProduct

可以看到我们在order服务用调用了product服务的list接口,其结果返回来商品列表信息
在这里插入图片描述

2.3 重试与超时

feign包含了ribbon,因此可以使用ribbon的重试、超时机制,只需要在配置文件中修改:

  • 重试配置
#同一台实例最大重试次数,不包括首次调用
ribbon.MaxAutoRetries=1
#重试负载均衡其他的实例最大重试次数,不包括首次调用
ribbon.MaxAutoRetriesNextServer=1
#是否所有操作都重试
ribbon.OkToRetryOnAllOperations=false
  • 超时配置:这里的连接超时指的是连接接口的时间,而业务逻辑超时时间指的是连接成功后业务逻辑的执行时间
#连接超时时间(ms)
ribbon.ConnectTimeout=1000
#业务逻辑超时时间(ms)
ribbon.ReadTimeout=6000

2.4 服务熔断、降级

在配置熔断降级之前我们需要理解什么是服务熔断?什么是服务降级?

服务熔断:当连续连接失败次数达到阈值后,直接报错,之后的相同请求也直接报错,这个措施称为熔断。相当于我们常见的保险丝,当确定了服务不能访问时,就直接断开后续的连接

服务降级:当连续连接失败次数达到阈值或者超时后,给请求方一个保底信息,这个保底信息可以是:
(1)返回友好性的页面,比如重试按钮、联系邮箱或者一些基础的静态页面
(2)返回提示信息,并把数据写入到MQ中,后续通过MQ来重试
(3)返回友好性的提示信息,比如“稍后再来”、“服务忙,请稍后重试”等,不做其他处理
我们把以上这样的措施称为降级。

默认feign是不会用Hytrix来做服务降级等处理的,所以要使用的话需要在配置文件中开启:

feign.hystrix.enabled=true

熔断、降级配置

feign利用fallback类来实现请求失败后的回调方法
1、创建回调类

@Component
public class UserProviderBack implements UserApi {

    @Override
	public Map findById(@RequestParam("id") Integer id){
	// 降级,给出友好性提示
        return "服务走远了,请稍后重试";
    }
    
    @Override
	public Map getMap(@RequestParam Map<String,Object> map){
	// 熔断,直接返回空数据
       return null;
   }	
 
}

2、声明回调类

@FeignClient(name="user-provider",fallback= UserProviderBack.class)
public interface UserApi {

    @GetMapping("/findById")
	public Map findById(@RequestParam("id") Integer id);
    
    @GetMapping("/getMap")
	public Map getMap(@RequestParam Map<String,Object> map);	
 
}

好了,本期我们针对feign组件的讲解就到这里了,针对限流的配置我们并不推荐使用feign来实现,如果要做也是在fallback做处理,后续会详细讲解微服务中的限流措施。文中的测试代码也已经放到了git项目中,欢迎大家下载体验

下期预告

1、微服务框架进阶讲解

关注公众号,了解更多新鲜内容

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_24950043/article/details/123947704