OpenFeign

OpenFeign

一、基本使用

1、引入依赖

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

对于loadbalancer做一个解释,开始用的是Ribbon,2020年之后开始使用loadbalancer代替它,两者最主要的区别是,Ribbon是一个较为底层的负载均衡器,需要开发人员手动配置均衡策略和服务发现机制,但是loadbalancer提供了更高层次的抽象,将负载均衡策略和服务发现机制实现了封装,更加容易使用。

2、启动类上添加@EnableFeignClients注解,表示开启OpenFeign

3、编写接口,看代码:

@FeignClient(value = "item-service")
public interface ItemClient {@GetMapping("item/{id}")ResponseEntity<Item> queryById(@PathVariable("id") Integer id);
}

@FeignClient括号里面value对应的值是被请求的服务的名称,接口中的方法就跟在controller里面写的一样,只是不需要实现,需要提供请求方式和路径,例如:@GetMapping("item/{id}"),还需要提供返回值,请求参数,请求参数的注解,都不能少,例如:ResponseEntity<Item> queryById(@PathVariable("id") Integer id),需要将返回值的类从其他服务复制一份过来。

二、原理

1、OpenFeign调用接口没有具体实现,是因为使用了代理,代理类是FeignInvocationHandler实现了InvocationHandler

static class FeignInvocationHandler implements InvocationHandler 

2、FeignInvocationHandler类的主要方法是invoke

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 

 下面是方法的一部分:

     if (!"equals".equals(method.getName())) {if ("hashCode".equals(method.getName())) {return this.hashCode();} else {return "toString".equals(method.getName()) ? this.toString() : ((MethodHandler)this.dispatch.get(method)).invoke(args);}} else {try {Object otherHandler = args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;return this.equals(otherHandler);} catch (IllegalArgumentException var5) {return false;}}}

除了基本的hashCode这样的方法之外,都要走代理invoke方法。代理的过程:

(1)首先根据接口定义的信息创建一个RequestTemplate对象,这个对象从接口获取到请求方法,请求路径,请求参数,服务名称,模板创建完成之后是这样:GET /item/2 HTTP/1.1

 RequestTemplate template = this.buildTemplateFromArgs.create(argv);

(2)根据模板创建一个请求对象Request,此时请求的路径基本成型,只是还有获取到服务的ip和端口,暂时用服务名代替,例如:GET http://item-service/item/2,通过Request对象可以获取到被请求服务的服务列表

Request request = this.targetRequest(template);

(3)通过loadBalancerClient.choose负载均衡,从实例列表中选出一个实例,获取该实例的ip和端口

ServiceInstance instance = this.loadBalancerClient.choose(serviceId, lbRequest);
ServiceInstance是一个实例,大概信息是:

最后拼接成url:

 (4)使用client 类型的delegate发送http请求,但是这里的发送可以优化,使用连接池技术,避免每次创建和销毁链接导致的系统性能开销,推荐使用OKHttp。

优化:

添加依赖

<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>

配置applicaton.yml

feign:okhttp:enabled: true

避坑:

遇到过两个错误

(1)feign/Request$ProtocolVersion

(2)feign.Request$HttpMethod.isWithBody()Z

原因是因为OKHttp依赖的版本和cloud不匹配导致的,我这里用的是这一组,可以参考下:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><version>3.1.0</version>
</dependency>
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId><version>3.1.0</version>
</dependency>
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-okhttp</artifactId><version>10.12</version>
</dependency>

 springboot的版本是:

<version>2.6.13</version>

 三、最佳实践

如果说大量使用到服务之间的通信调用,那么可以将Client单独抽离到一个模块,实现统一维护。

四、OpenFeign日志开启

1、首先是client所在的包的日志级别必须是debug,yml文件的配置如下,包名自己换:

logging:level:com.cart.cartservice: debugpattern:dateformat: HH:mm:ss:SSS

2、编写配置类

public class DefaultFeignConfig {@Beanpublic Logger.Level feignLoggerLevel(){return Logger.Level.BASIC;}
}

Logger.Level.BASIC是日志级别:

  • NONE:不记录,这是默认值

  • BASIC:仅记录请求的方法,URL以及响应状态码和执行时间。

  • HEADERS:在BASIC的基础上额外的记录了请求和响应的头

  • FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

 3、在启动类的注解上添加扫描的包和配置类

@EnableFeignClients(basePackages = "com.cart.cartservice",defaultConfiguration = DefaultFeignConfig.class)

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

lwip发送组播数据问题

1、今天测试组播包发现&#xff0c;组播数据只能在默认网卡发送成功&#xff0c;多次交叉测试依然这样&#xff0c;所以和网卡的配置无关 &#xff08;我的是双网卡&#xff09; 2、最后搜源码看&#xff0c;才发现有一段代码如下&#xff1a; struct netif * ip4_route(cons…

Vivado JESD204B与AD9162建立通信实战总结

一、FPGA与AD9162的JESD204B接口 FPGA作为JESD204B接口的发送端&#xff0c;AD9162作为JESD204B接口的接收端。FPGA和AD9162的device clk、SYSREF由同源时钟芯片产生。其中&#xff0c;FPGA和AD9162的divice clk时钟不同&#xff0c;并且FPGA的decive clk等同于JESD204B IP的co…

Ubuntu 22.04/20.04 安装 SSH

OpenSSH 是安全远程通信的重要工具&#xff0c;提供了一种安全的方式来访问和管理服务器。对于那些计划在 Ubuntu 22.04 Jammy Jellyfish 或其较旧的稳定版本的 Ubuntu 20.04 Focal Fossa 上安装 SSH 并启用它的人来说&#xff0c;了解其功能和优势至关重要。 OpenSSH的主要特…

x-cmd pkg | zellij - 比 tmux 更容易上手的终端多路复用器

简介 zellij 是一个面向开发、运营以及任何热爱终端的人的终端多路复用器 &#xff08;Terminal Multiplexers&#xff09;&#xff0c;类似于 tmux 和 screen&#xff0c;内置许多功能&#xff0c;允许用户扩展并创建自己的个性化环境。 zellij 的设计理念是不牺牲简单性来换…

Excel·VBA二维数组组合函数的应用实例之概率计算

看到一个视频《李永乐老师的抖音 - 骰子概率问题》&#xff0c;计算投出6个骰子恰好出现1、2、3、4、5、6这6个点数的概率 李永乐老师的计算方法是&#xff0c;第1个概率为1即6/6&#xff0c;第2个不与之前相同的概率为5/6&#xff0c;第3个同理概率为4/6&#xff0c;因此该问…

【WPF.NET开发】WPF中的输入

本文内容 输入 API事件路由处理输入事件文本输入触摸和操作侧重点鼠标位置鼠标捕获命令输入系统和基元素 Windows Presentation Foundation (WPF) 子系统提供了一个功能强大的 API&#xff0c;用于从各种设备&#xff08;包括鼠标、键盘、触摸和触笔&#xff09;获取输入。 本…

【随手查】TINA-TI

快速导航 一、如何导入TI中的器件1、如果TI官网直接给了TSM文件2、如果官网没有直接给TSM文件 一、如何导入TI中的器件 1、如果TI官网直接给了TSM文件 以芯片THS4303为例&#xff0c;在TI中搜索元器件THS4303后 然后可以看到&#xff0c;这里直接给出了TINA的模型&#xf…

JAVA对象、List、Map和JSON之间的相互转换

JAVA对象、List、Map和JSON之间的相互转换 1.Java中对象和json互转2.Java中list和json互转3.Java中map和json互转 1.Java中对象和json互转 Object obj new Object(); String objJson JSONObject.toJSONString(obj);//java对象转json Object newObj JSONObject.parseObject(…

用户管理第2节课 -- idea 2023.2 创建表--鱼皮

二、【先确定idea版本&鱼皮是否一致&#xff0c;再决定看不看这行】建表 2.1 idea 里连接数据库&#xff0c;通过可视化建表 2.1.1 清空表中数据 的 命令 truncate 清空 2.1.2 先输入删除表&#xff0c;的命令&#xff0c;再选中这行命令&#xff0c;执行&#xff0c;…

平安人寿新疆分公司:深化消费帮扶,为乡村振兴注入平安力量

为深入贯彻关于“三农”工作的重要论述&#xff0c;落实自治区乡村振兴局的指导部署&#xff0c;近日&#xff0c;平安人寿新疆分公司一把手刘湑杰总一行赴和田县访惠聚驻村工作队走访&#xff0c;慰问了驻村工作队、五老人员及困难村民。 期间&#xff0c;刘湑杰总一行调研了…

解决burpsuite代理8080端口无法勾选以及卸载NI系列软件的方法

使用burpsuite中遇到这样一个问题 默认的8080端口无法绑定 提示端口已经被占用 尝试绑定其他端口&#xff0c;是可行的&#xff0c;也可以正常抓包 但是总感觉每次进来都设置添加一次&#xff0c;有点麻烦不舒服 那么我们来看一下8080端口到底被什么进程占用了 使用如下命令…

实验三-HBase数据库操作

第一步&#xff1a;首先登陆ssh&#xff0c;之前设置了无密码登陆&#xff0c;因此这里不需要密码&#xff1b;再切换目录至/usr/local/hadoop &#xff1b;再启动hadoop ssh localhost cd /usr/local/hadoop ./sbin/start-dfs.sh 输入命令jps&#xff0c;能看到NameNode,Data…