行百里er 行百里er
首页
  • 分类
  • 标签
  • 归档
设计模式
  • JVM
  • Java基础
MySQL
Elastic Stack
Redis
  • Kafka
  • RocketMQ
分布式
Spring Cloud Alibaba
云原生
数据结构与算法
关于
GitHub (opens new window)

行百里er

Java程序员一枚
首页
  • 分类
  • 标签
  • 归档
设计模式
  • JVM
  • Java基础
MySQL
Elastic Stack
Redis
  • Kafka
  • RocketMQ
分布式
Spring Cloud Alibaba
云原生
数据结构与算法
关于
GitHub (opens new window)
  • 系统架构演进与Spring Cloud Alibaba简介
  • 万字长文:Spring Cloud Alibaba组件之Nacos实战及Nacos客户端服务注册源码解析
  • 服务容错的必要性与Spring Cloud Alibaba Sentinel 限流配置实战
  • Spring Cloud Alibaba Sentinel 熔断降级策略实战
  • Spring Cloud Alibaba:将 Sentinel 熔断限流规则持久化到 Nacos 配置中心
  • Sentinel限流降级如何优雅的返回?SentinelResource注解之blockHander和fallback
  • 微服务间的远程接口调用:OpenFeign 的使用
    • 操练:欲善其事,先利其器
      • 创建 FeignClient 接口
      • 验证
    • 优化:事无巨细,极致体验
      • 日志
      • 关于超时时间
  • 强强联合:OpenFeign 整合 Sentinel
  • 网关 Spring Cloud Gateway - API 调用的组织者
  • Spring Cloud Gateway 网关限流
  • Spring Cloud Sleuth 整合 Zipkin 进行服务链路追踪
  • 高级版的 jvisualvm :Spring Boot Admin 监控 Spring Boot 微服务项目
  • 分布式事务解决方案之 Seata(一):分布式事务的常见解决方案及 Seata 简介
  • Seata 番外篇:使用 docker-compose 部署 Seata Server(TC)及 K8S 部署 Seata 高可用
  • 分布式事务解决方案之 Seata(二):Seata AT 模式
  • Spring Cloud Alibaba
行百里er
2022-08-18
目录

微服务间的远程接口调用:OpenFeign 的使用

作者:行百里er

博客:https://chendapeng.cn (opens new window)

提示

这里是 行百里er 的博客:行百里者半九十,凡事善始善终,吾将上下而求索!

OpenFeign 是一种声明式、模板化的 HTTP 客户端。在 Spring Cloud 中使用 OpenFeign ,可以做到使用 HTTP 请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访问 HTTP 请求。

其用法就是编写一个接口,在接口上添加注解。如此就能轻而易举的调用远程服务。

有如此强大的东西,我们肯定不能放过使用的机会,就像有时你有特殊的要求必须拉别的女孩的手,而此时有个中间人能帮你实现这个愿望,你拉别的女孩子的手就像拉自己女朋友的手一样方便!

image-20220817171359983.png

OpenFeign 在微服务中的作用就像中间方一样,当你需要调用另一个微服务的接口时,使用 OpenFeign 就像调用本服务的接口一样丝滑。

# 操练:欲善其事,先利其器

既然是远程调用,那肯定至少得有2个微服务,本系列文章已经前面已经有了几个服务,我们就调用 nacos-provider 这个服务提供者的接口。

这里新建一个 open-feign-service 子模块服务,引入 spring-cloud-starter-loadbalancer 和 spring-cloud-starter-openfeign 两个依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
1
2
3
4
5
6
7
8

父模块中添加子模块,现有模块如下:

<modules>
    <module>internal-common</module>
    <module>nacos-provider</module>
    <module>nacos-consumer</module>
    <module>nacos-config</module>
    <module>sentinel-service</module>
    <module>open-feign-service</module>
</modules>
1
2
3
4
5
6
7
8

如何在 open-feign-service 服务中调用 nacos-provider 服务的接口呢?前面 nacos-consumer 服务使用了 loadbalancer 和 RestTemplate 进行了调用,现在我们在 open-feign-service 服务使用 OpenFeign 来进行调用。

# 创建 FeignClient 接口

要将 Feign 引入到到项目中:

1. 首先需要在启动类上添加 @EnableFeignClients 注解:

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OpenFeignServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(OpenFeignServiceApplication.class, args);
    }

}
1
2
3
4
5
6
7
8
9
10

2. 创建一个 Service 接口,添加 @FeignClient 注解:

@Service
@FeignClient(name = "nacos-provider")
public interface ProductService {

    /**
     * 调用远程服务 nacos-provider 的 product/{id} 接口
     * @param id 参数 id
     * @return 返回
     */
    @GetMapping("/product/{id}")
    String getProductById(@PathVariable("id") Long id);
}
1
2
3
4
5
6
7
8
9
10
11
12

关于 FeignClient 注解,需要知道:

  • name : 是一个任意的客户端名称,用于创 Spring Cloud LoadBalancer 客户端;
  • url :url一般用于调试,可以手动指定 @FeignClient 调用的地址;
  • configuration :Feigin 配置类,可自定义 Feign 的 Encode,Decode,LogLevel,Contract;
  • fallback :定义 容错 的类,当远程调用的接口失败或者超时的时候,会调用对应接口的容错逻辑,fallback 执行的类必须实现@FeignClient 标记的接口;
  • fallbackFactory :工厂类,用于生成 fallback 类实例,通过此属性可以实现每个接口通用的容错逻辑,以达到减少重复的代码;
  • path :定义当前 FeignClient 的统一前缀。

本案例只是用 name 属性指定调用的服务名称,容错属性后续可与 Sentinel 整合再说。

3. 控制层通过 FeignClient 远程调用

@RestController
public class TestController {

    private ProductService productService;

    @GetMapping("/product/{id}")
    public String getProduct(@PathVariable("id") Long id) {
        return productService.getProductById(id);
    }

    @Autowired
    public void setProductService(ProductService productService) {
        this.productService = productService;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

控制层引入被 FeighClient 标记的接口 ProductService ,直接调用接口的 getProductById 方法即可实现远程调用 nacos-provider 服务的 getProduct ,这里看一下远程服务的处理逻辑:

@RestController
public class TestController {

    private final static Map<Long, String> PRODUCT_MAP = new HashMap<>();

    static {
        PRODUCT_MAP.put(1L, "香飘飘奶茶");
        PRODUCT_MAP.put(2L, "雀巢咖啡");
        PRODUCT_MAP.put(3L, "百事可乐");
    }

    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/product/{id}")
    public String getProduct(@PathVariable Long id) {
        return serverPort + ":" + PRODUCT_MAP.get(id);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 验证

直接访问本服务:http://localhost:6061/product/3 ,可以看到调用了远程服务 nacos-provider 的接口:

screenshots.gif

从结果看,还实现了访问服务的负载均衡!

# 优化:事无巨细,极致体验

# 日志

OpenFeign 提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解 OpenFeign 中 Http 请求的细节。 通过设置日志,可以对 Feign 接口的调用情况进行监控和输出。

OpenFeign 的日志级别主要有以下几种:

  • NONE:默认的,不显示任何日志;

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

  • HEADERS :除了 BASIC 中定义的信息之外,还有请求和响应的头信息;

  • FULL :除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据。

使用步骤:

1. 设置 Feign Logger Level:

@Bean
Logger.Level feignLoggerLevel() {
    // 开启详细日志
    return Logger.Level.FULL;
}
1
2
3
4
5

设置什么级别,根据情况而定。

2. 在配置文件中给指定的 FeignClient 接口加指定的日志级别

logging:
  level:
    # 给指定的 FeignClient 接口加指定的日志级别
    cn.chendapeng.springcloud.openfeignservice.service.ProductService: debug
1
2
3
4

使用效果:

image-20220818102526106.png

请求的详细情况就以日志的形式打印出来了。

# 关于超时时间

spring-cloud-starter-openfeign 支持 spring-cloud-starter-loadbalancer 。我们在项目中已经添加了 spring-cloud-starter-loadbalancer依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
1
2
3
4

这样在 @FeignClient 注解中,当设定了 name = "nacos-provider" 客户端名称后,便默认使用了 Spring Cloud LoadBalancer 进行负载均衡访问 nacos-provider ,在老版本中,集成的是 Ribbon ,它默认的响应时间是 1 s,可以通过 ribbon.ReadTimeout 和 ribbon.ConnectTimeout 来设置客户端超时时间。

Spring Cloud Loadbalancer 默认没有超时时间的限制。

但是我们依然可以在默认客户端(default)和命名客户端上(注解 FeignClient 设置的 name,比如本demo中的 nacos-provider)配置超时。

OpenFeign 使用两个超时参数:

  • connectTimeout 防止由于服务器处理时间长而阻塞调用者。
  • readTimeout 从连接建立时开始,在返回响应时间过长时触发。

具体设置方式:

feign:
  client:
    config:
      # 默认的超时时间设置
      default:
        connectTimeout: 5000
        readTimeout: 5000
      # 在指定的 FeignClient 设置超时时间,覆盖默认的设置
      nacos-provider:
        connectTimeout: 1000
        readTimeout: 1000
        loggerLevel: full
1
2
3
4
5
6
7
8
9
10
11
12

假如设置 nacos-provider 的超时时间为 1s ,我们通过在 nacos-provider 设置一个延迟 3 秒执行的方法,来模仿长业务线调用。

nacos-provider 的 cn.chendapeng.springcloud.nacosprovider.controller.TestController :

@GetMapping("/product/{id}")
public String getProduct(@PathVariable Long id) {
    // 添加 sleep 时间,模拟超时连接
    try {
        TimeUnit.SECONDS.sleep(3);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return serverPort + ":" + PRODUCT_MAP.get(id);
}
1
2
3
4
5
6
7
8
9
10

调用效果:

image-20220818105255846.png

image-20220818105237237.png

本系列文章代码仓库:https://github.com/ChenDapengJava/SpringCloudAlibabaDemo (opens new window)


以上就是本文的全部内容了,本次导航结束。


首发公众号 行百里er ,欢迎老铁们关注阅读指正。

#Spring Cloud Alibaba#微服务
上次更新: 2022/10/04, 18:14:30
Sentinel限流降级如何优雅的返回?SentinelResource注解之blockHander和fallback
强强联合:OpenFeign 整合 Sentinel

← Sentinel限流降级如何优雅的返回?SentinelResource注解之blockHander和fallback 强强联合:OpenFeign 整合 Sentinel→

最近更新
01
重要数据不能丢!MySQL数据库定期备份保驾护航!
05-22
02
分布式事务解决方案之 Seata(二):Seata AT 模式
09-09
03
Seata 番外篇:使用 docker-compose 部署 Seata Server(TC)及 K8S 部署 Seata 高可用
09-05
更多文章>
Theme by Vdoing | Copyright © 2020-2023 行百里er | MIT License | 豫ICP备2022020385号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式