[SpringCloud] Feign 与 Gateway 简介

目录

一、Feign 简介

1、RestTemplate 远程调用中存在的问题

2、定义和使用 Feign 客户端

3、Feign 自定义配置

4、Feign 性能优化

5、Feign 最佳实践

6、Feign 使用问题汇总

二、Gateway 网关简介

1、搭建网关服务

2、路由断言工厂

3、路由的过滤器配置

4、全局过滤器

5、过滤器链执行顺序

6、网关的 cors 跨域配置

7、Gateway 网关使用问题汇总


一、Feign 简介

Feign 是 Netflix 开发的声明式、模板化的 Http 客户端,Feign 可以帮助我们更快捷、优雅地调用Http API。

  • Feign 是在 Ribbon 的基础上进行了一次改进,是一个使用起来更加方便的 HTTP 客户端。
  • SpringCloud 对 Feign 进行了增强,使 Feign 支持了 Spring MVC 注解,并整合了 Ribbon 和 Eureka,集成了服务发现和负载均衡,从而让 Feign 的使用更加方便。

1、RestTemplate 远程调用中存在的问题

该远程调用的代码有以下问题:

  • 代码可读性差,编程体验不统一;
  • 参数复杂,URL 难以维护;

2、定义和使用 Feign 客户端

在 SpringCloud 中,使用 Feign 非常简单,创建一个 Interface,并在接口上添加一些注解,代码就完成了。 

(1)引入依赖

  • 给需要远程调用的模块,引入 openfeign 起步依赖;

(2)添加 @EnableFeignClients 注解

  • 给需要远程调用的启动类,添加 @EnableFeignClients 注解;

(3)编写 Feign 客户端

  • 添加 @FeignClient 和 @GetMapping 注解; 

上述注解声明了如下信息:

  • 服务名称:user-service;
  • 请求方式:get;
  • 请求路径:/user/{userId};
  • 请求参数:String userId;
  • 返回值类型:User;

(4)OrderService 远程调用过程

该远程调用过程,就好像平常处理请求的逆过程:

  • OrderService 将 userId 传递给接口中的方法;
  • queryUserById 方法再将参数赋值给请求路径中的占位符 {userId};
  • 然后再通过 get 请求向 UserController 发送请求;
  • 最终获得 User 对象信息;

3、Feign 自定义配置

Spring 虽然帮我们做好了配置,但是也允许我们修改默认配置。

配置 Feign 日志有 2 种方式:

(1)application/bootstrap 配置文件方式

  • 注意:logging.level 属性值需要改为 trace; 

(2)Java 代码方式

4、Feign 性能优化

Feign 底层客户端实现:

  • URLConnection:默认使用,java 原生 jdk,性能较差,不支持连接池;
  • Apache HttpClient:支持连接池;(推荐)
  • OKHttp:支持连接池;(推荐)

对 Feign 的性能优化,最重要的一点就是对底层实现的改变。

因此优化 Feign 的性能主要包括:

  • 使用连接池代替默认的 URLConnection;
  • 日志级别,最好用 basic 或 none;(因为开启日志也需要占用较多资源)

下面以 HttpClient 为例子,说明性能优化的步骤:

(1)引入依赖

  • httpClient 已经被 Spring 管理好版本了,不需要指定版本;

(2)修改 application 配置文件

  • 将 feign.httpclient.enabled 的属性值改为 true,表明底层使用 httpclient;

5、Feign 最佳实践

最佳实践是指,企业开发过程中,总结设计缺点,得出的一种相对比较好的使用方式。

通常会用到 2 种方式,各有利弊,按自己的需求使用:

  • 继承:给消费者的 FeignClient 和提供者的 controller 定义统一的父接口,然后实现接口;
  • 比如 order 模块要调用 user 模块的服务,就定义 UserClient 接口,继承 UserAPI;
  • 缺点:耦合度高;
  • 优点:遵从了契约;

  • 抽取:将 FeignClient 抽取为独立模块,并且把接口有关的 POJO、默认的 Feign 配置都放到这个模块中,提供给所有消费者使用;
  • 缺点:消费者可能会引入很多用不到的 api;
  • 优点:耦合度低,层次分明;

我个人更喜欢第二种抽取的方式,下面使用这种方式做一个例子。

(1)创建 feign-api 模块

  • 在 feign-api 模块中引入 feign 的起步依赖;

  • 将消费者模块中对提供者模块所需的 Client、Pojo,以及 Config 类都移动到 feign-api 中;

(2)引入 feign-api 模块

  • 在消费者 order-service 模块中,引入 feign-api 模块;

(3)消除报错

  • 将 order-service 模块内原来依赖 pojo、config、client 的类,修改为 feign-api 模块内的类;

  • 由于 order-service 模块的 application 启动类无法扫描到 feign-api 模块下的 Client 的 Bean 对象,因此会出现如下报错:

  • 需要在 @EnableFeignClients 中加入 clients 属性;

6、Feign 使用问题汇总

(1)Did you forget to include spring-cloud-starter-loadbalancer?

出错原因: 

  • SpringCloud Feign 在 Hoxton.M2 RELEASED 版本之后不再使用 Ribbon,而是使用 spring-cloud-loadbalancer,所以在不引入 spring-cloud-loadbalancer 的情况下会报错。

参考了很多解决方法,主要是要区别版本问题:

包含 RELEASE 关键字的版本中,只有下面这样操作才能使用:

  • 首先排除 ribbon 的起步依赖,排除位置在消费者依赖的服务提供者的 dependency;
  • 添加 loadBalancer 依赖;

而在 2021 及更新版本中(也就是没有 RELEASE 关键字的版本),只需要如下操作:

  • 引入 loadBalancer 依赖;
  • 不需要排除 ribbon 的起步依赖;

二、Gateway 网关简介

为什么需要网关?

  • 如果没有网关,那么所有人都可以访问我们所有的服务,但是有很多服务其实是不能对外公开的。
  • 需要使用网关进行身份验证,通过后才能访问敏感服务。
  • 一切请求需要先通过网关,才能到微服务。

因此,网关有如下功能:

  • 身份认证和权限校验;
  • 服务路由、负载均衡;(也就是能知道将请求送到哪个微服务)
  • 限制请求流量;

SpringCloud 提供了 2 个组件实现网关功能:

  • gateway;(新版本)
  • zuul;(早期版本)

Zuul 是基于 Servlet 的实现,属于阻塞式编程。

而 SpringCloudGateway 则是基于 Spring5 中提供的 WebFlux,属于响应式编程的实现,具备更好的性能。

1、搭建网关服务

(1)创建 gateway 模块

  • 创建一个新的模块专门用于网关:gateway-module,需要 SpringBoot 启动类;
  • 引入 SpringCloudGateway 起步依赖;
  • 引入 Nacos 服务发现依赖;

(2)编写路由配置以及 Nacos 地址

  • gateway 中的 routes 属性之前的配置,目的是为了让 gateway 将服务注册到 nacos;
  • gateway 中的 routes 属性之后的配置,指明了可以使用的 service 路由;
  • id:表示这个路由的名字,与其他属性无关;
  • uri:表示路由目标地址,其中 lb 表示负载均衡,后面跟着服务的 name;
  • predicates:指定路由规则,符合规则就可以放行;

(3)测试网关功能

  • 启动 gateway 的 application;
  • 发起请求:localhost:10010/order/queryOrderById/1;
  • 这个请求中,order-service 模块会调用 user-service 的服务;

  • 访问失败,说明我们的网关起作用了,因为我们没有为网关配置 order-service 的路由;

  • 添加对 order-service 的服务的路由后,就可以从 gateway 访问 order 的服务了;

2、路由断言工厂

路由断言工厂 Route Predicate Factory,作用是:

  • 我们在配置文件中写的 predicates 断言规则只是字符串,这些字符串会被 Predicate Factory 读取并解析为路由判断的条件。
  • 每种规则都有各自的断言工厂去解析,比如 Path 有 PathRoutePredicateFactory 断言工厂;

下面以 After 举一个例子:

(1)添加断言规则 After

  • After 断言规则,规定在这个时间之后,才能进行访问; 

(2)访问 order 的服务

  • 发送请求 /order/queryOrderById/1;
  • 理向情况应该是:无法访问;

  • 修改断言规则的时间为:2020-12-31,重启 gateway 模块;

  • 再次发起请求,就可以访问了;

3、路由的过滤器配置

路由过滤器是:GatewayFilter。

  • GatewayFilter 是网关中提供的一种过滤器,可以对进入网关的请求微服务返回的响应做处理。

在这个过程中,过滤器就可对请求和响应做出各种各样的处理,这样往下游传递的数据中,就包含了修改后的信息。

具体有什么样的操作,就要看使用哪个过滤器工厂:

下面我们以添加一个请求头为例子:

(1)修改 application 配置文件

  • 给 routes 中的一个路由添加 filters 属性;
  • filters 中添加:- AddRequestHeader=[key],[value];

(2)编写 Controller,获取请求头信息

  • 既然在 filter 中设置了 header:orderStatus=001;
  • 那么请求传递到 Controller 后,一定可以获取到这个头信息;

  • 访问 /order/queryOrderById/1,查看控制台输出;

(3)编写默认过滤器 default-filter

如果我们想为所有的请求都添加 header 信息,也不需要给每一个路由都写上 filters。

  • 只需要在 routes 同级下,添加 default-filter 属性;
  • 给 default-filter 属性添加:- AddRequestHeader=[key],[value] 等属性值;

  • 访问 /order/queryOrderById/1,查看控制台输出;

4、全局过滤器

全局过滤器是:GlobalFilter。

  • 全局过滤器的作用:处理一切进入网关的请求和微服务响应,与 GatewayFilter 的作用一样,只是作用范围不同。
  • 其中,GatewayFilter 通过配置定义,运行逻辑是固定的。(官方定义)
  • 而 GlobalFilter 的运行逻辑需要自己写代码实现。(自定义)

需求

定义全局过滤器,拦截请求,判断请求的参数是否满足下面条件:

  • 参数中是否有 authorization;
  • authorization 参数值是否为 admin;
  • 如果同时满足则放行,否则拦截;

(1)定义实现类

  • 创建 AuthorFilter 实现类,实现 GlobalFilter 接口;
  • exchange:请求上下文,里面可以获取Request. Response等信息;
  • chain:用来把请求委托给下一个过滤器;
  •  Nono<Void>:返回表示当前过滤器业务结束

(2)定义 filter 方法的运行逻辑

  • 添加 @Component;
  • 添加 @Order,方便多过滤器时指定顺序;
  • 网关中采用的都是基于 WebFlux(响应式编程)的 API,因此使用上与 ServletAPI 不同;
@Order(-1)
@Component
public class AuthorFilter implements GlobalFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 1.获取请求参数ServerHttpRequest request = exchange.getRequest();MultiValueMap<String, String> params = request.getQueryParams();// 2.获取请求参数中的 author 参数值String author = params.getFirst("author");// 3.判断是否等于 adminif (author.equalsIgnoreCase("admin")) {// 放行return chain.filter(exchange);}// 4.不相等,获取响应ServerHttpResponse response = exchange.getResponse();// 4.1.设置状态码,401表示未登录response.setStatusCode(HttpStatus.UNAUTHORIZED);// 4.2.拦截请求return response.setComplete();}
}

(3)启动 gateway 的 application

  • 访问 /order/queryOrderById/1/author=admin111,先使用错误的 authon 参数值;
  • 发现返回了 401;

  • 访问 /order/queryOrderById/1/author=admin,使用正确的 authon 参数值;
  • 可以正常访问

5、过滤器链执行顺序

请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter。

请求路由后,会将当前路由过滤器DefaultFilterGlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器。

过滤器执行顺序:

  • 每一个过滤器都必须指定一个 int 类型的 order 值:order 值越小,优先级越高,执行顺序越靠前;
  • GlobalFilter 通过实现 Ordered 接口,或者添加 @Order 注解来指定 order 值,由我们自己指定;
  • 路由过滤器和 defaultFilter 的 order 由 Spring 官方指定,默认是按照声明顺序从 1 递增;
  • 当过滤器的 order 值一样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter 的顺序执行;

6、网关的 cors 跨域配置

由于一些页面可能需要从微服务中获取某些数据,此时需要发起 AJAX 请求,那么这就可能属于跨域请求的范畴。(一般我们的 web 页面端口都不会与微服务的相同,所以请求基本上都是跨域请求)

跨域请求不需要在微服务中处理,只需要在网关中处理即可。

跨域:域名不一致就是跨域,主要包括:

  • 域名不同:www.taobao.com 和 www.taobao.org 和 www.jd.com 和 miaosha.jd.com;
  • 域名相同,端口不同:localhost:8080 和 localhost:8081

跨域问题的 2 个要素:

  • 浏览器、服务端:浏览器禁止请求向服务端发起跨域 ajax 请求,请求会被拦截;
  • 解决方案:CORS;

需求:

  • 使用 localhost:8090 发起请求,8090 发送的是 AJAX 的 GET 请求。
  • 8090 发起的 AJAX 请求需要通过网关,在 AJAX 的目标地址中要用 10010 端口;

(1)编写 gateway 的配置文件

  • 各个属性的作用都写在注释中了;

(2)端口 8090 的 AJAX 请求

  • 这里使用 JQuery 发起 AJAX 请求,传递参数为 author=admin;
  • 这里参数是必须传递的,因为发起的请求目标地址是要通过网关的,需要鉴权;
<head><meta charset="UTF-8"><title>Title</title><script type="text/javascript" src="JQuery-3.7.0.js"></script><script type="text/javascript">$(function() {$("#ajaxButton").click(function() {$.ajax({url:"http://localhost:10010/order/queryOrderById/1",data: {author : "admin"},type: "get",dataType: "json",success: function(data) {console.log(data);}});});});</script>
</head>
<body><a href="http://localhost:10010/order/queryOrderById/1?author=admin"> 发起普通GET请求 </a><input id="ajaxButton" type="button" value="发起 ajax 请求"/>
</body>
  • 发起请求,可以在控制台看到返回的数据;

  • 而如果我们用 <a> 来请求,是会跳转到 10010 得页面的,这就不算跨域请求了;

7、Gateway 网关使用问题汇总

(1)搭建网关服务时,报错 503

这是因为在 Spring Cloud 2020 版本以后,默认移除了对 Netflix 的依赖,其中就包括 Ribbon,官方默认推荐使用 Spring Cloud Loadbalancer 正式替换 Ribbon,并成为了 Spring Cloud 负载均衡器的唯一实现。

Loadbalancer 依赖:

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

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

相关文章

钢琴培训答题服务预约小程序的效果怎样

很多家长都会从小培养孩子的兴趣&#xff0c;钢琴便是其中热度较高的一种&#xff0c;而各城市也不乏线下教育培训机构&#xff0c;除了青少年也有成年人参加培训&#xff0c;市场教育高需求下&#xff0c;需要商家不断拓展客户和转化。 那么通过【雨科】平台制作钢琴培训服务…

协程框架nty_co

一、为什么要有协程&#xff1f; 以DNS请求为例子&#xff0c;客户端向服务器发送域名&#xff0c;服务器回复该域名对应得IP地址。 我们想要以同步的编程方式获得异步的性能&#xff01;&#xff01;&#xff01; 在Linux下&#xff0c;常使用IO多路复用器epoll来管理客户端…

英语——歌曲篇——500 Miles(离家五百里)

乡村音乐&#xff08;country music&#xff09;《500 Miles(离家五百里)》以一种怀乡、寻根 的意识&#xff0c;用思念留住时光还有一点哲理的味道&#xff0c;乡村音乐多年以来都不曾淡出大家的视野&#xff0c;确实有值得留恋的情怀。 500 Miles [The Brothers Four离家五…

用前端框架Bootstrap和Django实现用户注册页面

01-新建一个名为“mall_backend”的Project 命令如下&#xff1a; CD E:\Python_project\P_001\myshop-test E: django-admin startproject mall_backend02-新建应用并注册应用 执行下面条命令依次创建需要的应用&#xff1a; CD E:\Python_project\P_001\myshop-test\mall…

【计算机视觉】相机

文章目录 一、原始的相机&#xff1a;针孔相机&#xff08;Pinhole Camera&#xff09;二、针孔相机的数学模型三、真实相机四、透镜的缺陷 我的《计算机视觉》系列参考UC Berkeley的CS180课程&#xff0c;PPT可以在课程主页看到。 成像原理 一、原始的相机&#xff1a;针孔相机…

信息安全与网络安全的关系

前言 说说信息安全与网络安全的关系 如果你对网络安全入门感兴趣&#xff0c;那么你需要的话可以点击这里&#x1f449;【入门&进阶全套282G学习资源包免费分享&#xff01;】 一、包含和被包含的关系 信息安全包括网络安全&#xff0c;信息安全还包括操作系统安全&…

云计算的基本概念

目录 云计算基本概念 什么是云计算 云计算的优势&#xff08;关键特征&#xff09; 云计算发展历程 云计算发展阶段 云计算的三种服务模式 云计算的四类部署模式 云计算的应用 云计算基本概念 什么是云计算 云计算的基本概念 云计算&#xff08;Cloud Computing&…

J2EE项目部署与发布(Linux版本)

目录 一.jdk&tomcat安装 1.jdk的安装 1.2解压对应的安装包 1.3配置环境变量 2.tomcat的安装 二.mysql的安装 三.后端接口部署 后端部署 导入war包 修改端口 开启访问 一.jdk&tomcat安装 1.jdk的安装 登录VMware Workstation Pro 然后连接MobaXterm 将 jd…

BI零售数据分析,告别拖延症,及时掌握一线信息

在日常的零售数据分析中&#xff0c;经常会因为数据量太大&#xff0c;分析指标太多且计算组合多变而导致数据分析报表难产&#xff0c;零售运营决策被迫拖延症。随着BI数据可视化分析技术的发展&#xff0c;智能化、可视化、自助分析的BI数据分析逐渐成熟&#xff0c;形成一套…

精品站长网交易系统源码/虚拟交易网站程序源码/虚拟交易平台带店铺处罚商品处罚

精品站长网交易系统源码&#xff0c;虚拟交易网站程序源码&#xff0c;虚拟交易平台带店铺处罚商品处罚。带申诉功能&#xff0c; 带提现通知功能&#xff0c; 带熊掌号推送功能&#xff0c; 带站内信息功能。 下载地址&#xff1a;https://bbs.csdn.net/topics/617494651

C++学习笔记之四(标准库、标准模板库、vector类)

C 1、C标准库2、C标准模板库2.1、vector2.1.1、vector与array2.1.2、vector与函数对象2.1.3、vector与迭代器2.1.4、vector与算法 1、C标准库 C C C标准库指的是标准程序库( S t a n d a r d Standard Standard L i b a r a y Libaray Libaray)&#xff0c;它定义了十个大类…

如何使用IP归属地查询API加强网络安全

引言 在当今数字化时代&#xff0c;网络安全对于个人和组织来说至关重要。恶意网络活动的威胁不断增加&#xff0c;因此采取有效的措施来加强网络安全至关重要。其中之一是利用IP归属地查询API。这个工具可以为您的网络安全策略提供宝贵的信息&#xff0c;帮助您更好地保护自己…

huggingface离线模式及默认保存路径

T5Tokenizer.from_pretrained()函数会在线下载huggingface上的模型&#xff0c;并自动保存在C盘的.cache路径下&#xff1a; C:\Users\xxxxx\.cache\huggingface\hub\models--google--t5-v1_1-base # 这里xxxxx代表自己电脑用户名huggingface离线下载 以google/t5-v1_1-base为…

win10 下编译ffmpeg3.36.tar.gz

所需工具&#xff1a; win10 ffmpeg3.36.tar.gz。 或其他版本&#xff0c;下载地址&#xff1a;Index of /releases msys2。 下载地址&#xff1a;http://www.msys2.org。 Visual Studio 2017。 1. 安装MSYS MSYS2像是windows下的一个子系统&#xff0c;…

hadoop权威指南第四版

第一部分 HaDOOP基础知识 1.1 面临的问题 存储越来越大&#xff0c;读写跟不上。 并行读多个磁盘。 问题1 磁盘损坏 – 备份数据HDFS 问题2 读取多个磁盘用于分析&#xff0c;数据容易出错 --MR 编程模型 1.2 衍生品 1 在线访问的组件是hbase 。一种使用hdfs底层存储的模型。…

CSS3盒模型

CSS3盒模型规定了网页元素的显示方式&#xff0c;包括大小、边框、边界和补白等概念。2015年4月&#xff0c;W3C的CSS工作组发布了CSS3基本用户接口模块&#xff0c;该模块负责控制与用户接口界面相关效果的呈现方式。 1、盒模型基础 在网页设计中&#xff0c;经常会听到内容…

DSP 开发例程(5): tcp_server

目录 DSP 开发例程(5): tcp_server创建工程源码编辑tcp_echo.chelloWorld.c 调试说明 DSP 开发例程(5): tcp_server 此例程实现在 EVM6678L 开发板上创建 TCP Server进程, 完成计算机与开发板之间的 TCP/IP 通信. 例程源码可从我的 gitee 仓库上克隆或下载. 点击 DSP 开发教程…

组件化npm包打包和使用

背景&#xff1a;本地环境对功能组件提取&#xff0c;开发环境下通过本地路径引用&#xff0c;发布模式下走npm包引用 1、项目下新建packages/HelloWorld文件夹&#xff0c;在此文件夹下运行终端 npm init 新建packages/HelloWorld/index.vue文件 新建packages/HelloWorld/ind…

「完美修复」concrt140.dll丢失的修复方法

concrt140.dll是一个动态链接库文件&#xff0c;它是Microsoft Visual C 2015 Redistributable的一部分。这个文件通常位于Windows系统的System32文件夹中&#xff0c;它提供了一些用于多线程编程的函数和类。当你在运行某些程序时&#xff0c;系统会调用这个文件中的函数来执行…

VR全景图片如何制作?揭秘VR全景图片制作全流程

引言&#xff1a; VR全景图片是一种以全景视角为基础的图片制作技术&#xff0c;能够呈现出更为真实、立体的视觉体验。通过VR全景图片&#xff0c;观众可以360环顾四周&#xff0c;仿佛身临其境&#xff0c;提供了一种全新的感官体验&#xff0c;那么如何制作出令人满意的全景…