微服务外交官-Feign

news2024/11/24 4:31:45

引言

书接上篇 负载均衡组件Ribbon核心-@LoadBalanced-下 我们讲完了Ribbon负载均衡原理之后,接下讲一个SpringCloud Alibaba新的组件:Fegin

前面章节我们使用Ribbon方式实现负载均衡版的远程调用,

//方案4:使用Ribbon方式--带负载均衡
String url =  "http://product-service/products/" + pid;
Product product = restTemplate.getForObject(url, Product.class);
order.setPid(pid);
order.setProductName(product.getName());
order.setProductPrice(product.getPrice());

从实现效果上看没有任何问题,但每次都需要手动拼接URL,有点小麻烦,有没有更加优雅的方式呢?答案是yes:Feign

什么是Feign

Feign是啥?如果我们将所有为微服务比作国家,那Feign就是各国杰出的外交家

Feign是Spring Cloud提供的一个声明式的伪Http客户端, 它使得调用远程服务就像调用本地服务一样简单, 只需要创建一个接口并添加一个注解即可。

Nacos很好的兼容了Feign, Feign默认集成了 Ribbon, 所以在Nacos下使用Fegin默认就实现了负载均衡的效果。

实现案例

还是之前的订单服务调用商品服务,此处使用Feign组件发起远程调用。

步骤1:在shop-order-server项目的pom文件加入Fegin的依赖 

<!--fegin组件-->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

注意:哪一方需要发起远程调用,Feign依赖就加在哪一方

步骤2:启动类OrderServer.java上添加Fegin的扫描注解,注意扫描路径

@SpringBootApplication
@MapperScan("cn.wolfcode.mapper")
@EnableDiscoveryClient
@EnableFeignClients
public class OrderServer {
    public static void main(String[] args) {
        SpringApplication.run(OrderServer.class,args);
    }
}

@EnableFeignClients 注解用于扫描后续定义Feign接口,代理生产接口实现类

步骤3:在shop-order-server项目中新增接口IProductFeignService

@FeignClient(name = "product-service")
public interface IProductFeginService {
    @GetMapping("/products/{pid}")
    Product get(@PathVariable("pid") Long pid);
}

注意1:@FeignClient 指向要调用服务名

注意2:接口方法定义跟被调用服务接口定义一模一样,只是少了实现

步骤4:修改OrderServiceImpl.java的远程调用方法

@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private IProductFeginService productFeginService;

    @Override
    public Order createOrder(Long pid, Long uid) {
        Order order = new Order();
        //商品
        //方案1:通过restTemplate方式
        //String url  = "http://localhost:8081/products/" + pid;
        //Product product = restTemplate.getForObject(url, Product.class);


        //方案2:使用注册中心api方式-discoveryClient
        //List<ServiceInstance> instances = discoveryClient.getInstances("product-service");
        //ServiceInstance instance = instances.get(0);  //当前只有一个
        //String host = instance.getHost();
        //int port = instance.getPort();
        //String url = "http://" + host + ":" + port + "/products/" + pid;
        //Product product = restTemplate.getForObject(url, Product.class);

        //方案3:使用注册中心api方式-discoveryClient--带负载均衡
        //List<ServiceInstance> instances = discoveryClient.getInstances("product-service");
        //int index = new Random().nextInt(instances.size());
        //ServiceInstance instance = instances.get(index);
        //String host = instance.getHost();
        //int port = instance.getPort();
        //String url = "http://" + host + ":" + port + "/products/" + pid;
        //System.out.println("从nacos中获取的url地址:" + url);
        //Product product = restTemplate.getForObject(url, Product.class);

        //方案4:使用Ribbon方式--带负载均衡
        //String url =  "http://product-service/products/" + pid;
        //Product product = restTemplate.getForObject(url, Product.class);

        //方案5:使用fegin接口--带负载均衡
        Product product = productFeginService.get(pid);

        order.setPid(pid);
        order.setProductName(product.getName());
        order.setProductPrice(product.getPrice());

        //用户
        order.setUid(1L);
        order.setUsername("dafei");
        order.setNumber(1);
        System.out.println(order);
        super.save(order);
        return order;
    }
}

Feign接口定义成功之后,后续调用跟普通的本地服务层接口一样。

步骤5:重启订单服务,并验证

Feign接口使用原理

看到这,肯定有小伙伴觉得好神奇啊,就定义一个接口就能发起远程访问了,牛逼!其实,细心的朋友应该能看出端倪,Feign接口定义与配置内容都涵盖远程调用所有的参数:

服务名:结合nacos 注册中心可以获取到 ip 与 端口

接口路径:请求路径

接口参数:请求参数

这些参数一组装,不就是完整的服务接口url么~

 

Feign接口定义注意要点

@FeignClient(name = "product-service")
public interface IProductFeginService {
    @GetMapping("/products/{pid}")
    Product get(@PathVariable("pid") Long pid);
}

1>@FeignClient 中name为服务提供者在nacos上注册的服务名, 否则报错

Load balancer does not have available server for client:xxxx-service

2>@GetMapping("/products/{pid}") 指定接口路径,必须跟服务提供者提供接口url一样,否则报错

feign.FeignException$NotFound: [404] during [GET] to [http://xxx-service/xxx] 

3> 定义接口参数:如果使用了参数路径方式访问,需要使用@PathVariable("pid") 明确指定路径参数,否则报错

feign.FeignException$NotFound: [404] during [GET] to [http://xxx-service/xxx] 

4>定义接口参数:如果使用普通方式访问,参数需要使用@RequestParam标记,否则报错

@FeignClient(name = "product-service")
public interface IProductFeginService {
    @GetMapping("/products")
    Product get(@RequestParam("pid") Long pid);
}
feign.FeignException$MethodNotAllowed: [405] during [GET] to [http://xxxx-service/xxxx?xxx=1]

5>定义接口参数:如果是对象参数,参数需要使用@RequestBody标记(注意fegin接口,controler接口都要),否则报错

@FeignClient(name = "product-service")
public interface IProductFeginService {
    @GetMapping("/products")
    Product get(@RequestBody Product product);
}
参数无法获取

6>定义接口参数:如果是对象,可以使用@SpringQueryMap替换上面的@RequestBody

@FeignClient(name = "product-service")
public interface IProductFeginService {
    @GetMapping("/products")
    Product get(@SpringQueryMap Product product);
}

7>定义接口参数:如果需要进行文件上传,需要使用@RequestPart注解标记

@FeignClient(name = "product-service")
public interface IProductFeginService {
    @PostMapping("/upload")
    void upload(MultipartFile file);
}

8>Feign接口调用默认连接时间是1s,如果电脑较慢,开发中可以配置长一点时间

注意:后面学sentinel 时候,不要配置,会影响观测效果

feign:
  client:
    config:
      default:
        connectTimeout: 5000  #连接时间,单位毫秒
        readTimeout: 5000     #操作时间

到这,Feign简单介绍就结束啦,如果有小伙伴想了解Feign源码怎么玩的,那请期待下回分解啦~

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

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

相关文章

不知道10年老电脑如何重装系统?其实很简单

肯定很多朋友家里都有一两台吃灰的10年老电脑了&#xff0c;当我们有空可以把它拿出来耍耍的时候&#xff0c;却发现电脑无法开机了&#xff0c;想拿去修又觉得不太值得。其实我们可以先试着给电脑重装系统&#xff0c;这样也能先排查系统是否有问题。如果你不知道这台10年老电…

【Linux】Linux编译器-gcc/g++使用

大家好我是沐曦希&#x1f495; 文章目录1.背景知识1.1 预处理1.2 编译&#xff08;生成汇编&#xff09;1.3 汇编&#xff08;生成机器可识别代码&#xff09;1.4 链接接(生成可执行文件或库文件&#xff09;1.5 习题习题一习题二2.函数库2.1 动态库2.2 静态库3.g的基本使用4.…

数据结构之二叉树

数据结构之二叉树什么是二叉树二叉树的特殊类型二叉树的遍历方式二叉树的叶子结点求法二叉树的高度求法什么是二叉树 二叉树&#xff08;Binary tree&#xff09;是树形结构的一个重要数据类型&#xff0c;想要成为二叉树必须满足两个条件。1、本身是有序树。2、树中包含的各个…

【小程序】导航栏和内容页面联动效果实现

&#x1f4ad;&#x1f4ad; ✨&#xff1a; 微信小程序导航栏和页面联动   &#x1f49f;&#xff1a;东非不开森的主页   &#x1f49c;: 因为很多东西来不及去做去看可是时间很快总是赶不上&#xff0c;所以要去成长呀&#x1f49c;&#x1f49c;   &#x1f338;: 如有错…

React—— HelloWorld

React 学习笔记Hello WorldJSX (JavaScript XML) 语法规则JavaScript 语法函数组件、类组件 & 属性 props组合组件生命周期函数 & 状态 state事件处理refs受控组件、非受控组件 & 高阶函数、函数的柯里化npm参考Hello World <!DOCTYPE html> <html lang&…

Request请求转发与Respones请求重定向有什么区别?

目录&#xff1a; 1.Request请求转发 2.Respones请求重定向 3.关于转发和重定向的路径问题 1.Request请求转发 请求转发(forward)是一种在服务器内部的资源跳转方式。 (1)浏览器发送请求给服务器&#xff0c;服务器中对应的资源A接收到请求 (2)资源A处理完请求后将请求发…

在html中使用js实现图片的无缝滚动(四种状态)

文章目录js原理实施任务1.从左往右无缝滚动代码示例运行效果2.从右往左无缝滚动代码示例运行效果3.从上往下无缝滚动代码示例运行效果4.从下往上无缝滚动代码示例运行效果js原理 获取整个ul和ul下面的所有li&#xff0c; 把ul里面的li内容添加一份&#xff0c;因为需要完成图片…

【加油站会员管理小程序】01需求分析

随着这两年微搭产品的迭代,目前组件基本够用,像常用的支付这种功能也是有的,因此我们就可以结合现有功能来完成一个实际使用的小程序的开发。 我们本次的实战课,是以加油站的业务场景为出发点,涵盖会员的开通、充值、消费、积分兑换等常用场景。结合实战案例,我们完整的…

12月2日:thinkphp中的链式操作

补充内容&#xff1a; 今天我们就来聊聊limit和page的区别以及group by需要注意的点&#xff0c;where和having的区别 limit和page 区别 Limit 限制查询数量&#xff0c;在进行分页查询的时候用的最多&#xff0c;但是limit在查询限制中的索引值是从0开始的&#xff0c;lim…

基于Java+Springboot+Vue+elememt疫情返乡人员管控系统设计实现

博主介绍&#xff1a;✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取联系&#x1f345;精彩专栏推荐订阅收藏&#x1f447;&…

一文搞懂如何学习Android内部命令行工具集合

目录 1.安卓命令工具集 2.命令如何使用&#xff08;举例&#xff09; 2.1 am命令使用 2.2 dumpsys 命令使用 2.3 wm命令用法 2.4 rm命令的用法 2.5 logcat 命令的用法 2.6 cat 命令的用法 3.个人如何学习 3.1 推荐学习方法一 3.2 方法二 1.安卓命令工具集 安卓支持…

JMeter入门教程(7) --思考时间

1.人物背景 在JMeter脚本中&#xff0c;思考时间使用定时器模拟实现的 2.任务目标 掌握基于JMeter性能测试脚本开发——思考时间 3.任务实操 3.1 固定定时器 右击取样器&#xff0c;选择“添加 > 定时器 > 固定定时器&#xff0c;如图示&#xff1a; 2.固定定时器页…

手机无线耳机什么牌子的好用?2022好用的无线蓝牙耳机排行榜

现如今的蓝牙耳机市场中有着多种机型&#xff0c;不同功能&#xff0c;不同价格的蓝牙耳机数不胜数&#xff0c;一部手机、一副耳机似乎已经成为了人们外出的搭配。那么手机无线耳机什么牌子的好用呢&#xff1f;下面我来给大家推荐几款好用的无线蓝牙耳机&#xff0c;大家可以…

团队协作利器----API接口Eolink

本文目录&#xff1a;一、初识Eolink1.什么是Eolink2.我与Eolink的故事二、Eolink突出特点----团队协作协同工作分享协作支持所有类型API文档、测试方便导出接口文档方便查看历史记录三、Eolink优势总结前言&#xff1a; hello大家好&#xff0c;我是Dream&#xff0c;在我们的…

安卓中adb命令工作的底层原理及使用举例

目录 1. adb安卓调试桥 2.adb的组成 3.adb命令的使用举例: 3.1什么是应用包?什么是应用界面? 3.2 adb 命令如何获取应用应用包名和应用界面名? 1. adb安卓调试桥 adb的全称为Android Debug Bridge&#xff0c;就是起到调试桥的作用。通过adb我们可以在Eclipse中方便通过…

c程序从编译开始到运行结束的过程

重温c语言 我们在linux平台下建立一个a.c文件,程序很简单&#xff0c;显示输出Please input your name:&#xff0c;然后让我们输入名字&#xff0c;最后调用了一个子函数输出hello,我们的名字 #include<stdio.h>void hello(char * name);int main(){char name[16]{0};p…

(4E)-TCO-PEG4-acid,1802913-21-8物理性质分享

(4E)-TCO-PEG4-acid物理数据&#xff1a; CAS&#xff1a;1802913-21-8| 中文名&#xff1a;(4E)-反式环辛烯-四聚乙二醇-羧酸 | 英文名&#xff1a; (4E)-TCO-PEG4-acid 结构式&#xff1a; 英文别名&#xff1a; (4E)-TCO-PEG4-COOH TCO4-PEG4-COOH 中文别名&#xff1a…

【Flink】一文解析Flink如何实现状态管理和容错机制

文章目录一 Flink中的状态管理1 有状态的算子和应用程序&#xff08;1&#xff09;算子状态&#xff08;operator state&#xff09;&#xff08;2&#xff09;键控状态&#xff08;keyed state&#xff09;2 状态后端3 选择一个状态后端二 Flink中的容错机制1 一致性检查点&am…

自建传奇2服务器,分享自己架设传奇服务器的详细介绍

我们在经历了太多的传奇私服之后就会有人想要自己搞一个来看看&#xff0c;其实有这样想法的人其实还是很多的&#xff0c;毕竟当一个玩家总没有当一个GM来的实在。于是就有人选择自己去架设传奇私服的服务器&#xff0c;而这个时候我们的信息就能够给这些想要自己当GM的人一个…

uniapp多端问题总结

页面跳转相关 1、页面跳转传参报错 问题&#xff1a; 小程序报错 SyntaxError: Unexpected end of JSON inputat JSON.parse () 原因&#xff1a;是由于JSON.parse无法识别某些url中的特殊字符比如&等特殊符号。解决办法&#xff1a; 原来代码&#xff1a; // 跳转所属专…