【Spring Cloud】声明性REST客户端:Feign

news2024/11/17 7:46:07

Spring Cloud Feign ——fallback 服务降级

  • 1. Feign 简介
  • 2. Feign 的基础使用
    • 2.1 普通 HTTP 请求
    • 2.2 Feign 远程调用上传文件接口

1. Feign 简介

Feign 是一个声明式的 HTTP 客户端,它简化了编写基于 REST 的服务间通信代码的过程。在 Spring Cloud 中,Feign 扮演着重要的角色,它具有可插入注释支持,包括Feign注释和JAX-RS注释。Feign还支持可插拔编码器解码器Spring Cloud增加了对Spring MVC注释的支持,并使用Spring Web中默认使用的HttpMessageConverters。Spring Cloud 集成RibbonEureka或者Nacos 注册中心 以在使用 Feign 时提供负载均衡的http 客户端。

Feign 特性介绍:

  • 声明式 REST 客户端
    Feign 允许开发者使用接口和注解的方式定义对远程 REST 服务的调用,而不需要关心底层的 HTTP 请求和响应处理。在 Feign 中,可以通过接口方法的定义来描述远程服务的各种操作,包括 URL、请求方法、参数等信息。
  • 集成负载均衡
    通过整合 Ribbon 负载均衡器,Feign 可以自动实现对指定服务的负载均衡调用。这使得在服务提供者有多个实例的情况下,Feign 可以根据负载均衡策略选择合适的服务实例进行调用。
  • 支持多种请求方法
    Feign 支持各种 HTTP 请求方法,如 GETPOSTPUTDELETE 等,从而使得对远程服务的调用变得非常灵活。
  • 动态 URL 和参数绑定
    使用 Feign,可以将参数绑定到 URL 模板中,并将动态的数据传递给远程服务。同时,Feign 也支持将参数绑定到请求体中,以便进行 POSTPUT 请求。
  • 集成 Hystrix 容错机制
    结合 Spring Cloud 中的 Hystrix 断路器,Feign 可以提供对远程服务调用的容错能力,包括超时、断路器等功能,从而增强了服务调用的可靠性。
  • 易于集成
    在 Spring Cloud 应用程序中,Feign 与其他组件(如 EurekaZuul 等)无缝集成,通过简单的依赖配置和注解即可快速启用,并且无需额外的繁琐配置。

总之,Spring Cloud Feign 提供了一种简洁而优雅的方式来定义和调用 REST 服务,它简化了服务间通信的过程,提高了开发效率,为构建微服务架构的应用程序提供了便利的支持。

2. Feign 的基础使用

搭建一个 SpringCloud 的 Demo,包含生产者和消费者。 都是普通的 web 服务,其中 消费者 比生产者多了 Feign 的依赖。

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

并且在启动类上添加注解:@EnableFeignClients
如果配置了fallbackFactory降级,则还需要引入依赖:

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

然后在启动类上添加注解:@EnableHystrix,并且添加开启服务降级的配置:

feign:
  hystrix:
    enabled: true

2.1 普通 HTTP 请求

其中生产者提供一个POST 的接口:/student/queryList 查询数据库中 student 表的数据。

@RestController
@RequestMapping("/student")
public class StudentController {

    @Resource
    private IStudentService studentService;

    @GetMapping("/queryList")
    public ApiR queryList(){
        List<Student> studentList = studentService.list();
        return ApiR.ok().data(studentList);
    }
}

消费者使用 Feign 远程调用这个查询列表的接口:

首先新建一个 @FeignClient 注解的接口

import com.lin.common.config.FeignSupportConfig;
import com.lin.common.constant.ServiceNameConstants;
import com.lin.common.vo.ApiR;
import com.lin.consumer.feign.fallback.RemoteStudentServiceFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author linmengmeng
 * @since 2023/11/12 14:12
 */
@FeignClient(contextId = "RemoteStudentService", name = ServiceNameConstants.PROVIDER_SERVICE
        , configuration = FeignSupportConfig.class, fallbackFactory = RemoteStudentServiceFallback.class)
public interface RemoteStudentService {

    @GetMapping ("/student/queryList")
    ApiR queryList();
}

我这里将生产者和消费者都注册到 Nacos 上,所以这里可以直接配置name = ServiceNameConstants.PROVIDER_SERVICE 通过生产者的服务名,直接调用对方的接口。

并配置了降级回调 fallbackFactory = RemoteStudentServiceFallback.class,降级操作是实现了上面定义的接口,并输出具体的异常信息;

import com.lin.common.vo.ApiR;
import com.lin.consumer.feign.RemoteStudentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;

/**
 * @author linmengmeng
 * @since 2023/11/12 14:22
 */
@Slf4j
@Component
public class RemoteStudentServiceFallback implements FallbackFactory<RemoteStudentService> {
    @Override
    public RemoteStudentService create(Throwable cause) {
        log.error("RemoteStudentServiceFallback error : {}", cause.getMessage());
        return () -> {
            log.error("sayHello error 接口调用异常");
            return ApiR.fail();
        };
    }
}

添加一个测试请求接口,调用上面的 feign 接口:

import cn.hutool.json.JSONUtil;
import com.lin.common.vo.ApiR;
import com.lin.common.vo.R;
import com.lin.consumer.feign.RemoteStudentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * 测试
 * @author linmengmeng
 * @since 2023/11/8 14:18
 */
@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {

    @Resource
    private RemoteStudentService remoteStudentService;

    @GetMapping("/sayHello")
    public R sayHello() {
        log.info("sayHello。。。。。。");
        ApiR apiR = remoteStudentService.queryList();
        log.info("接口调用结果-apiR:{}", JSONUtil.toJsonStr(apiR));
        return R.ok();
    }
}

先启动消费者,然后使用 Postman 调用消费者的 sayHello接口,可以看到,这个接口里面调用了Feign的远程接口,这时候生产者没启动,服务接口queryList肯定会掉不通的,按照原来 OkHTTP 的调用,远程接口异常,会将异常传递到接口调用方。经过上面的配置,我们来调用接口看下:
在这里插入图片描述
可以看到,接口正常响应了,接着看下消费者的日志:

2023-11-12 22:18:11.504  INFO [io-37002-exec-1] [] c.l.consumer.controller.TestController   [29] : sayHello。。。。。。
2023-11-12 22:18:12.030  WARN [reakerFactory-1] [] o.s.c.l.core.RoundRobinLoadBalancer      [97] : No servers available for service: cloud-feign-provider
2023-11-12 22:18:12.033  WARN [reakerFactory-1] [] .s.c.o.l.FeignBlockingLoadBalancerClient [103] : Load balancer does not contain an instance for the service cloud-feign-provider
2023-11-12 22:18:12.065 ERROR [reakerFactory-1] [] c.l.c.f.f.RemoteStudentServiceFallback   [18] : RemoteStudentServiceFallback error : [503] during [POST] to [http://cloud-feign-provider/student/queryList] [RemoteStudentService#queryList()]: [Load balancer does not contain an instance for the service cloud-feign-provider]
2023-11-12 22:18:12.072 ERROR [reakerFactory-1] [] c.l.c.f.f.RemoteStudentServiceFallback   [20] : sayHello error 接口调用异常
2023-11-12 22:18:12.204  INFO [io-37002-exec-1] [] c.l.consumer.controller.TestController   [31] : 接口调用结果-apiR:{"code":500,"message":"系统繁忙,请稍后再试!","data":{"changeLog":"","detail":{},"releaseTime":"2023-11-12 22:18:12"}}

可以看到,在接口调用成功后,调用Feign远程接口时,打印了两行 Warn 日志,提示我们生产者服务未找到,然后打印了我们的降级服务里面的error日志,并且我们用postman请求的接口正常响应了。

这就跟我们之前使用 OkHttp 远程调用接口有区别了,这里虽然上游服务异常,但是并不影响我们这边的调用,对于消费者来说,自身有个闭环的逻辑,不会将异常传递到本身,我们的业务逻辑中可以正常获取到降级服务的结果及日志。

接着分别启动生产者的服务,再次调用消费者的接口:

2023-11-12 22:31:50.722  INFO [io-37002-exec-2] [] c.l.consumer.controller.TestController   [29] : sayHello。。。。。。
2023-11-12 22:31:51.312  INFO [io-37002-exec-2] [] c.l.consumer.controller.TestController   [31] : 接口调用结果-apiR:{"code":200,"message":"成功","data":[{"id":"001","name":"Tom","age":19,"createTime":"2023-11-12T21:19:15"},{"id":"002","name":"Mary","age":18,"createTime":"2023-11-12T21:19:39"}]}

可以看到,接口正常响应了,数据也拿到了。

2.2 Feign 远程调用上传文件接口

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1200690.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

你一定要学会的Java语法 -- 【继承】

书接上回&#xff0c;我们已经学完了类和对象&#xff0c;今天内容可能有一点难&#xff0c;相信自己能跨过这道坎。 目录 一. 继承 1.什么是继承 2. 继承的概念 3. 继承的语法 4.父类成员访问 子类和父类成员变量同名 子类和父类成员方法同名 5.super关键字 6.子类构…

POJ 3254 Corn Fields 状态压缩DP(铺砖问题)

一、题目大意 我们要在N * M的田地里种植玉米&#xff0c;有如下限制条件&#xff1a; 1、对已经种植了玉米的位置&#xff0c;它的四个相邻位置都无法继续种植玉米。 2、题目中有说一些块无论如何&#xff0c;都无法种植玉米。 求所有种植玉米的方案数&#xff08;不种植也…

Vector - CANoe - Vector Hardware Manager基础介绍

经常使用CANoe的人都知道&#xff0c;我们之前使用配置VN系列硬件通道的时候使用的是Vector Hardware Config&#xff0c;非常的方便&#xff0c;不过在Vector Driver Setup驱动版本大于22.14后&#xff0c;为了更好的适用车载以太网相关的配置&#xff0c;以及各个配置之间继承…

kubenetes-kubelet组件

一、kubelet架构 每个节点都运行一个kubelet进程&#xff0c;默认监听10250端口&#xff0c;kubelet作用非常重要&#xff0c;是节点的守护神。 接收并执行 master发来的指令。管理Pod及Pod中的容器。每个kubelet进程会在API Server 上注册节点自身信息&#xff0c;定期向mast…

Java学习_对象

对象在计算机中的执行原理 类和对象的一些注意事项 this关键字 构造器 构造器是一种特殊的方法 : 特殊之处在于&#xff0c;名字必须与所在类的名字一样&#xff0c;而且不能写返回值类型 封装 封装的设计规范&#xff1a;合理隐藏、合理暴露 实体类 成员变量和局部变量的区别 …

程序员的护城河:职业发展的关键元素

目录 1. 技术深度与广度 2. 项目经验与实际操作 3. 沟通与团队协作 4. 持续学习与自我更新 5. 社区参与与开源贡献 6. 创新思维与解决问题的能力 7. 职业规划与自我管理 结语 在科技日新月异的今天&#xff0c;程序员的竞争已经不再仅仅依赖于技术水平&#xff0c;而是…

Citespace的使用

CiteSpace CiteSpace的相关介绍运行CiteSpace CiteSpace的相关介绍 CiteSpace作为一款优秀的文献计量学软件&#xff0c;能够将文献之间的关系以科学知识图谱的方式可视化地展现在我们面前。简单来说&#xff0c;面对海量的文献&#xff0c;CiteSpace能够迅速锁定自己需要关注…

使用openvc进行人脸检测:Haar级联分类器

1 人脸检测介绍 1.1 什么是人脸检测 人脸检测的目标是确定图像或视频中是否存在人脸。如果存在多个面&#xff0c;则每个面都被一个边界框包围&#xff0c;因此我们知道这些面的位置 人脸检测算法的主要目标是准确有效地确定图像或视频中人脸的存在和位置。这些算法分析数据…

如何从零开始手写一个消息中间件(从宏观角度理解消息中间件的技术原理)

如何从零开始手写一个消息中间件&#xff08;从宏观角度理解消息中间件的技术原理&#xff09; 什么是消息中间件消息中间件的作用逐一拆解消息中间件的核心技术消息中间件核心技术总览IOBIONIOIO多路复用AIOIO多路复用详细分析selectpollepoll Java中的IO多路复用 协议序列化消…

阿里云严重故障,影响阿里系、淘宝、饿了么、语雀等都崩了...

作者&#xff1a;JavaPub 编程学习一条龙&#xff1a;http://luxian.javapub.net.cn 就在一年一度的双十一剁手节火热进行时&#xff0c;阿里云服务出现了严重故障。 关键是前不久刚发生了语雀事件&#xff0c;不了解的朋友阅读这里 阿里语雀突发P0级事故&#xff0c;一度崩溃…

ASP.NETWeb开发(C#版)-day1-C#基础+实操

目录 .NET实操&#xff1a;创建项目执行 C#基础语法数据类型变量实操001_变量如何在一个解决方案 中创建另一个项目实操002结构实操003-if else实操004-多分支多行注释按钮实操&#xff1a;循环 面向对象基础如何在同一个项目下创建新的.cs文件实操-类的定义与访问实操-练习实操…

基于springboot实现驾校管理系统项目【项目源码】

基于springboot实现驾校管理系统演示 JAVA简介 JavaScript是一种网络脚本语言&#xff0c;广泛运用于web应用开发&#xff0c;可以用来添加网页的格式动态效果&#xff0c;该语言不用进行预编译就直接运行&#xff0c;可以直接嵌入HTML语言中&#xff0c;写成js语言&#xff0…

加班把数据库重构完毕

加班把数据库重构完毕 本文的数据库重构是基于 clickhouse 时序非关系型的数据库。该数据库适合存储股票数据&#xff0c;速度快&#xff0c;一般查询都是 ms 级别&#xff0c;不需要异步查询更新界面 ui。 达到目标效果&#xff1a;数据表随便删除&#xff0c;重新拉数据以及指…

基于C#+WPF编写的调用讯飞星火大模型工具

工具源码&#xff1a;https://github.com/lishuangquan1987/XFYun.SparkChat 工具效果截图&#xff1a; 支持流式输出: 其中ApiKey/ApiSecret/AppId需要自己到讯飞星火大模型官网去注册账号申请&#xff0c;免费的。 申请地址&#xff1a;https://xinghuo.xfyun.cn/ 注册之…

NetSuite 固定资产报表自定义原理及应用

NetSuite固定资产模块一直处于功能迭代更新中&#xff0c;目前23.2的版本能够支持报表的局部自定义&#xff0c;比如增加原值或已折旧期间&#xff0c;甚至固定资产自定义字段等。但是当我们在实际项目中&#xff0c;会遇到一些挑战&#xff0c;例如&#xff1a; 固定资产原值…

Java Web——前端HTML入门

目录 HTML&CSS3&JavaScript简述 1. HTML概念 2. 超文本 3. 标记语言 4. HTML基础结构 5. HTML基础词汇 6. HTML语法规则 7. VS Code 推荐使用的插件 8. 在线帮助文档 HTML&CSS3&JavaScript简述 HTML 主要用于网页主体结构的搭建&#xff0c;像一个毛坯…

【FAQ】Gradle开发问题汇总

1. buildSrc依赖Spring Denpendency时报错 来自预编译脚本的插件请求不能包含版本号。请从有问题的请求中删除该版本&#xff0c;并确保包含所请求插件io.spring.dependency-management的模块是一个实现依赖项 解决方案 https://www.5axxw.com/questions/content/uqw0grhttps:/…

怎么做到高性能网络IO?

为什么要做高性能网络IO。主要是解决c10&#xff0c;c10M问题 最开始的时候我们走的内核协议栈&#xff0c;走内核协议栈其实性能比较低&#xff0c;因为我们之前介绍的时候需要拷贝两次 但是我们采用用户态协议栈可以少拷贝一次&#xff0c;可以大大提高效率&#xff0c; 步骤…

阿里系APP崩了?回应来了!

最近&#xff0c;阿里云遭遇了一场可怕的疑似故障&#xff0c;引起了广泛的关注和热议。各种消息纷传&#xff0c;阿里云盘崩了&#xff0c;淘宝又崩了&#xff0c;闲鱼也崩了&#xff0c;连钉钉也不幸中招。这一系列故障让人不禁发问&#xff1a;阿里系的APP都崩了&#xff0c…

计算机中丢失msvcr120.dll文件怎么修复?找不到msvcr120.dll五种完美修复方案

今天我想和大家分享的是关于“msvcr120.dll丢失的问题的5个解决方法”。在我们日常的工作生活中&#xff0c;或许大家都曾遇到过这样的问题&#xff0c;那么&#xff0c;了解它的解决方法是非常必要的。 首先&#xff0c;让我们来了解一下msvcr120.dll是什么文件。简单来说&am…