建设一个手机网站首页,微商怎么做推广加好友,淄博云天网站建设推广,缅甸做网站#x1f680; 优质资源分享 #x1f680;
学习路线指引#xff08;点击解锁#xff09;知识定位人群定位#x1f9e1; Python实战微信订餐小程序 #x1f9e1;进阶级本课程是python flask微信小程序的完美结合#xff0c;从项目搭建到腾讯云部署上线#xff0c;打造一… 优质资源分享
学习路线指引点击解锁知识定位人群定位 Python实战微信订餐小程序 进阶级本课程是python flask微信小程序的完美结合从项目搭建到腾讯云部署上线打造一个全栈订餐系统。Python量化交易实战入门级手把手带你打造一个易扩展、更安全、效率更高的量化交易系统
背景
在微服务架构中通常一个系统会被拆分为多个微服务面对这么多微服务客户端应该如何去调用呢如果没有其他更优方法我们只能记录每个微服务对应的地址分别去调用但是这样会有很多的问题和潜在因素。
客户端多次请求不同的微服务会增加客户端代码和配置的复杂性维护成本比价高。认证复杂每个微服务可能存在不同的认证方式客户端去调用要去适配不同的认证存在跨域的请求调用链有一定的相对复杂性防火墙 / 浏览器不友好的协议。难以重构随着项目的迭代可能需要重新划分微服务
为了解决上面的问题微服务引入了 网关 的概念网关为微服务架构的系统提供简单、有效且统一的API路由管理作为系统的统一入口提供内部服务的路由中转给客户端提供统一的服务可以实现一些和业务没有耦合的公用逻辑主要功能包含认证、鉴权、路由转发、安全策略、防刷、流量控制、监控日志等。
网关在微服务中的位置: 网关对比
Zuul 1.0 : Netflix开源的网关使用Java开发基于Servlet架构构建便于二次开发。因为基于Servlet内部延迟严重并发场景不友好一个线程只能处理一次连接请求。Zuul 2.0 : 采用Netty实现异步非阻塞编程模型一个CPU一个线程能够处理所有的请求和响应请求响应的生命周期通过事件和回调进行处理减少线程数量开销较小 GateWay : 是Spring Cloud的一个全新的API网关项目替换Zuul开发的网关服务基于Spring5.0 SpringBoot2.0 WebFlux基于⾼性能的Reactor模式响应式通信框架Netty异步⾮阻塞模型等技术开发性能高于ZuulNginxlua : 性能要比上面的强很多使用Nginx的反向代码和负载均衡实现对API服务器的负载均衡以及高可用lua作为一款脚本语言可以编写一些简单的逻辑但是无法嵌入到微服务架构中Kong : 基于OpenRestyNginx Lua模块编写的高可用、易扩展的性能高效且稳定支持多个可用插件限流、鉴权等开箱即可用只支持HTTP协议且二次开发扩展难缺乏更易用的管理和配置方式
GateWay
官方文档https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-starter
Spring Cloud Gateway 是Spring Cloud的一个全新的API网关项目目的是为了替换掉Zuul1它基于Spring5.0 SpringBoot2.0 WebFlux基于⾼性能的Reactor模式响应式通信框架Netty异步⾮阻塞模型等技术开发性能⾼于Zuul官⽅测试Spring Cloud GateWay是Zuul的1.6倍 旨在为微服务架构提供⼀种简单有效的统⼀的API路由管理⽅式。
可以与Spring Cloud Discovery Client如Eureka、Ribbon、Hystrix等组件配合使用实现路由转发、负载均衡、熔断、鉴权、路径重写、⽇志监控等Gateway还内置了限流过滤器实现了限流的功能。设计优雅容易拓展
基本概念
路由Route是GateWay中最基本的组件之一表示一个具体的路由信息载体主要由下面几个部分组成
id路由唯一标识区别于其他的routeurl 路由指向的目的地URL客户端请求最终被转发到的微服务order 用于多个Route之间的排序数值越小越靠前匹配优先级越高predicate断言的作用是进行条件判断只有断言为true才执行路由filter: 过滤器用于修改请求和响应信息
核心流程 核心概念
Gateway Client 向 Spring Cloud Gateway 发送请求请求首先会被 HttpWebHandlerAdapter 进行提取组装成网关上下文然后网关的上下文会传递到 DispatcherHandler 它负责将请求分发给 RoutePredicateHandlerMappingRoutePredicateHandlerMapping 负责路由查找并根据路由断言判断路由是否可用如果过断言成功由 FilteringWebHandler 创建过滤器链并调用通过特定于请求的 Fliter 链运行请求Filter 被虚线分隔的原因是Filter可以在发送代理请求之前pre和之后post运行逻辑执行所有pre过滤器逻辑。然后进行代理请求。发出代理请求后将运行“post”过滤器逻辑。处理完毕之后将 Response 返回到 Gateway 客户端
Filter过滤器
Filter在pre类型的过滤器可以做参数效验、权限效验、流量监控、日志输出、协议转换等。Filter在post类型的过滤器可以做响应内容、响应头的修改、日志输出、流量监控等
核心思想
当用户发出请求达到 GateWay 之后会通过一些匹配条件定位到真正的服务节点并且在这个转发过程前后进行一些细粒度的控制其中 Predicate断言 是我们的匹配条件Filter 是一个拦截器有了这两点再加上URL就可以实现一个具体的路由核心思想路由转发执行过滤器链
这个过程就好比考试我们考试首先要找到对应的考场我们需要知道考场的地址和名称(id和url)然后我们进入考场之前会有考官查看我们的准考证是否匹配断言如果匹配才会进入考场我们进入考场之后路由之前会进行身份的登记和考试的科目填写考试信息当我们考试完成之后路由之后会进行签字交卷走出考场这个就类似我们的过滤器 Route(路由) 构建网关的基础模块由ID、目标URL、过滤器等组成
Predicate断言 开发人员可以匹配HTTP请求中的内容请求头和请求参数如果请求断言匹配贼进行路由
Filter过滤 GateWayFilter的实例使用过滤器可以在请求被路由之前或者之后对请求进行修改
框架搭建
通过上述讲解已经了解了基础概念我们来动手搭建一个GateWay项目来看看它到底是如何运行的 新建项目cloud-alibaba-gateway-9006
版本对应
GateWay属于SprinigCloud且有web依赖在我们导入对应依赖时要注意版本关系我们这里使用的版本是 2.2.x的版本所以配合使用的Hoxton.SR5版本 在这里我们要注意的是引入GateWay一定要删除spring-boot-starter-web依赖否则会有冲突无法启动 父类pom引用
Hoxton.SR5org.springframework.cloudspring-cloud-dependencies${spring-cloud-gateway-varsion}pomimport
子类POM引用
com.alibaba.cloudspring-cloud-starter-alibaba-nacos-discoveryorg.springframework.cloudspring-cloud-starter-gateway2.2.5.RELEASEorg.projectlomboklombok
yml配置
server:port: 9006
spring:application:name: cloud-gateway-servicecloud:nacos:discovery:server-addr: localhost:8848gateway:discovery:locator:enabled: false #开启注册中心路由功能routes: # 路由- id: nacos-provider #路由ID没有固定要求但是要保证唯一建议配合服务名uri: http://localhost:9001/nacos-provider # 匹配提供服务的路由地址 lb://表示开启负载均衡predicates: # 断言- Path/mxn/** # 断言路径相匹配进行路由
我们在之前的cloud-alibaba-nacos-9001项目中添加下面测试代码
RestController
RequestMapping(/mxn)
public class DemoController {Value(${server.port})private String serverPort;GetMapping(value /hello)public String hello(){return hello world my port is serverPort;}}
启动Nacos、cloud-alibaba-nacos-9001、cloud-alibaba-gateway-9006通过gateway网关去访问9001的mxn/order看看。
首先我们在Nacos中看到我们服务是注册到Nacos中了 然后我们访问http://localhost:9001/mxn/hello确保是成功的在通过http://localhost:9006/mxn/hello去访问也是OK说明我们GateWay搭建成功我们进入下一步 在上述方法中我们是通过YML去完成的配置GateWay还提供了另外一种配置方式就是通过代码的方式进行配置Bean 注入一个 RouteLocator
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;Configuration
public class GateWayConfig {/*配置了一个id为path\_mxn的路由规则当访问地址http://localhost:9999/mxn/**就会转发到http://localhost:9001/nacos-provider/mxn/任何地址*/Beanpublic RouteLocator gateWayConfigInfo(RouteLocatorBuilder routeLocatorBuilder){// 构建多个路由routesRouteLocatorBuilder.Builder routes routeLocatorBuilder.routes();// 具体路由地址routes.route(path\_mxn,r - r.path(/mxn/**).uri(http://localhost:9001/nacos-provider)).build();// 返回所有路由规则return routes.build();}
}
我们可以将路由注释掉之后看一下重启9006服务访问地址http://localhost:9006/mxn/hello 就可以转发到9001中具体的接口中 这里并不推荐使用代码的方式来进行配置gateWay大家有个了解就可以因为代码的配置维护的成本比较高而且对于一些需要修改的项需要改代码才可以完成这样不利于维护和拓展所以还是推荐大家使用yml进行配置。
GateWay负载均衡
在上述的讲解中我们已经掌握了 GateWay 的一些基本配置和两种使用方式下面我们就来讲解一下 GateWay 如何实现负载均衡
我们只需要在9006中添加lb://nacos-provider就可以显示负载均衡。 当我们去访问http://localhost:9006/mxn/hello的时候就可以看到9001和9002不停的切换 Predicate 断言
在这一篇中我们来研究一下 断言 我们可以理解为当满足条件后才会进行转发路由如果是多个那么多个条件需要同时满足
在官方提供的断言种类有11种(最新的有12种类型)
具体地址https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories After匹配在指定日期时间之后发生的请求。Before匹配在指定日期之前发生的请求。Between需要指定两个日期参数设定一个时间区间匹配此时间区间内的请求。Cookie需要指定两个参数分别为name和regexp正则表达式也可以理解Key和Value匹配具有给定名称且其值与正则表达式匹配的Cookie。Header需要两个参数header和regexp正则表达式也可以理解为Key和Value匹配请求携带信息。Host匹配当前请求是否来自于设置的主机。Method可以设置一个或多个参数匹配HTTP请求比如GET、POSTPath匹配指定路径下的请求可以是多个用逗号分隔Query需要指定一个或者多个参数一个必须参数和一个可选的正则表达式匹配请求中是否包含第一个参数如果有两个参数则匹配请求中第一个参数的值是否符合正则表达式。RemoteAddr匹配指定IP或IP段符合条件转发。Weight需要两个参数group和weightint实现了路由权重功能按照路由权重选择同一个分组中的路由
1. After 表示配置时间之后才进行转发
时间戳获取代码,用于时间代码的获取 public static void main(String[] args) {ZonedDateTime zbj ZonedDateTime.now();//默认时区System.out.println(zbj);}
spring:application:name: cloud-gateway-servicecloud:nacos:discovery:server-addr: localhost:8848gateway:discovery:locator:enabled: true #开启注册中心路由功能routes: # 路由- id: nacos-provider #路由ID没有固定要求但是要保证唯一建议配合服务名uri: lb://nacos-provider # 匹配提供服务的路由地址 lb://表示开启负载均衡predicates: # 断言- Path/mxn/** # 断言路径相匹配进行路由- After2022-06-11T16:30:40.78508:00[Asia/Shanghai] #在这个时间之后的请求够可以进行通过之前的则不能进行访问
如果在时间段之前访问则404
Before
匹配ZonedDateTime类型的时间表示匹配在指定日期时间之前的请求之后的请求则拒绝404错误
predicates: # 断言- Path/mxn/** # 断言路径相匹配进行路由
# - After2022-06-11T16:30:40.78508:00[Asia/Shanghai] #在这个时间之后的请求够可以进行通过之前的则不能进行访问- Before2022-06-11T15:30:40.78508:00[Asia/Shanghai]
Between
Between 可以匹配ZonedDateTime类型的时间由两个ZonedDateTime参数组成第一个参数为开始时间第二参数为结束时间逗号进行分隔匹配在指定的开始时间与结束时间之内的请求配置如下
predicates: # 断言- Path/mxn/** # 断言路径相匹配进行路由
# - After2022-06-11T16:30:40.78508:00[Asia/Shanghai] #在这个时间之后的请求够可以进行通过之前的则不能进行访问
# - Before2022-06-11T15:30:40.78508:00[Asia/Shanghai]- Between2022-06-11T15:30:40.78508:00[Asia/Shanghai],2022-06-11T16:30:40.78508:00[Asia/Shanghai]
Cookie
由两个参数组成分别为nameKey和regexp正则表达式Value匹配具有给定名称且其值与正则表达式匹配的Cookie。
路由规则会通过获取Cookie name值和正则表达式去匹配如果匹配上就会执行路由如果匹配不上则不执行。
predicates: # 断言- Path/mxn/** # 断言路径相匹配进行路由
# - After2022-06-11T16:30:40.78508:00[Asia/Shanghai] #在这个时间之后的请求够可以进行通过之前的则不能进行访问
# - Before2022-06-11T15:30:40.78508:00[Asia/Shanghai]
# - Between2022-06-11T15:30:40.78508:00[Asia/Shanghai],2022-06-11T16:30:40.78508:00[Asia/Shanghai]- Cookiemuxiaonong,[a-z] # 匹配Cookie的key和value正则表达式表示任意字母
小写字母匹配成功 数字匹配不成功 Header
由两个参数组成第一个参数为Header名称第二参数为Header的Value值,指定名称的其值和正则表达式相匹配的Header的请求
predicates: # 断言- Path/mxn/** # 断言路径相匹配进行路由
# - After2022-06-11T16:30:40.78508:00[Asia/Shanghai] #在这个时间之后的请求够可以进行通过之前的则不能进行访问
# - Before2022-06-11T15:30:40.78508:00[Asia/Shanghai]
# - Between2022-06-11T15:30:40.78508:00[Asia/Shanghai],2022-06-11T16:30:40.78508:00[Asia/Shanghai]
# - Cookiemuxiaonong,[a-z] # 匹配Cookie的key和value正则表达式表示任意字母- HeaderheaderName, \d # \d表示数字
请求头携带数字断言请求成功 断言字母匹配失败 Host
匹配当前请求是否来自于设置的主机。
predicates: # 断言- Path/mxn/** # 断言路径相匹配进行路由
# - After2022-06-11T16:30:40.78508:00[Asia/Shanghai] #在这个时间之后的请求够可以进行通过之前的则不能进行访问
# - Before2022-06-11T15:30:40.78508:00[Asia/Shanghai]
# - Between2022-06-11T15:30:40.78508:00[Asia/Shanghai],2022-06-11T16:30:40.78508:00[Asia/Shanghai]
# - Cookiemuxiaonong,[a-z] # 匹配Cookie的key和value正则表达式表示任意字母
# - HeaderheaderName, \d # \d表示数字- Host**.muxiaonong.com #匹配当前的主机地址发出的请求
满足Host断言请求成功 不满足Host断言失败 **Method **
可以设置一个或多个参数匹配HTTP请求比如POST,PUT,GET,DELETE
predicates: # 断言- Path/mxn/** # 断言路径相匹配进行路由
# - After2022-06-11T16:30:40.78508:00[Asia/Shanghai] #在这个时间之后的请求够可以进行通过之前的则不能进行访问
# - Before2022-06-11T15:30:40.78508:00[Asia/Shanghai]
# - Between2022-06-11T15:30:40.78508:00[Asia/Shanghai],2022-06-11T16:30:40.78508:00[Asia/Shanghai]
# - Cookiemuxiaonong,[a-z] # 匹配Cookie的key和value正则表达式表示任意字母
# - HeaderheaderName, \d # \d表示数字
# - Host**.muxiaonong.com #匹配当前的主机地址发出的请求- MethodPOST,GET
GET断言成功 PUT断言请求失败 Query
由两个参数组成第一个为参数名称(必须)第二个为参数值(可选-正则表达式)匹配请求中是否包含第一个参数如果有两个参数则匹配请求中第一个参数的值是否符合第二个正则表达式。
predicates: # 断言- Path/mxn/** # 断言路径相匹配进行路由
# - After2022-06-11T16:30:40.78508:00[Asia/Shanghai] #在这个时间之后的请求够可以进行通过之前的则不能进行访问
# - Before2022-06-11T15:30:40.78508:00[Asia/Shanghai]
# - Between2022-06-11T15:30:40.78508:00[Asia/Shanghai],2022-06-11T16:30:40.78508:00[Asia/Shanghai]
# - Cookiemuxiaonong,[a-z] # 匹配Cookie的key和value正则表达式表示任意字母
# - HeaderheaderName, \d # \d表示数字
# - Host**.muxiaonong.com #匹配当前的主机地址发出的请求
# - MethodPOST,GET- Queryid,. # 匹配任意请求参数这里如果需要匹配多个参数可以写多个- Query
断言匹配 请求成功
RemoteAddr
参数由CIDR 表示法IPv4 或 IPv6字符串组成也就是匹配的ID地址配置如下
predicates: # 断言- Path/mxn/** # 断言路径相匹配进行路由
# - After2022-06-11T16:30:40.78508:00[Asia/Shanghai] #在这个时间之后的请求够可以进行通过之前的则不能进行访问
# - Before2022-06-11T15:30:40.78508:00[Asia/Shanghai]
# - Between2022-06-11T15:30:40.78508:00[Asia/Shanghai],2022-06-11T16:30:40.78508:00[Asia/Shanghai]
# - Cookiemuxiaonong,[a-z] # 匹配Cookie的key和value正则表达式表示任意字母
# - HeaderheaderName, \d # \d表示数字
# - Host**.muxiaonong.com #匹配当前的主机地址发出的请求
# - MethodPOST,GET
# - Queryid,. # 匹配任意请求参数这里如果需要匹配多个参数可以写多个Query- RemoteAddr192.168.1.1/24
RemoteAddr
需要两个参数group和weightint权重数值实现了路由权重功能表示将相同的请求根据权重跳转到不同的uri地址要求group的名称必须一致
routes: # 路由- id: weight_high #路由ID没有固定要求但是要保证唯一建议配合服务名uri: https://blog.csdn.net/qq\_14996421predicates: # 断言- WeightgroupName,8- id: weight_low #路由ID没有固定要求但是要保证唯一建议配合服务名uri: https://juejin.cn/user/2700056290405815predicates: # 断言- WeightgroupName,2
直接访问http://localhost:9006/可以看到我们请求的地址成8/2比例交替显示 80% 的流量转发到https://blog.csdn.net/qq_14996421将约 20% 的流量转发到https://juejin.cn/user/2700056290405815
Predicate就是为了实现一组匹配规则让请求过来找到对应的Route进行处理。如果有多个断言则全部命中后进行处理
GateWay Filter
路由过滤器允许修改传入的HTTP请求或者返回的HTTP响应路由过滤器的范围是特定的路由.
Spring Cloud GateWay 内置的Filter生命周期有两种pre业务逻辑之前、post业务逻辑之后
GateWay本身自带的Filter分为两种 GateWayFilter单一、GlobalFilter全局
GateWay Filter提供了丰富的过滤器的使用单一的有32种全局的有9种有兴趣的小伙伴可以了解一下。
官方参考网址https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#global-filters
StripPrefix
StripPrefix 在我们当前请求中通过规则值去掉某一部分地址比如我们有一台服务中加入了一个前端nacos-provider想要通过这个去访问我们在项目cloud-alibaba-nacos-9001中加入 context-path
server:port: 9001servlet:context-path: /nacos-provider
现在9001的访问路径变为http://localhost:9001/nacos-provider/mxn/hello但是如果我们通过网关去访问路径就会变成http://localhost:9006/mxn/nacos-provider/mxn/hello 这个时候我们通过这个路径去访问是访问不成功的想要解决这个方法这个就用到了我们FIlter 中的 StripPrefix
routes: # 路由- id: nacos-provider #路由ID没有固定要求但是要保证唯一建议配合服务名uri: lb://nacos-providerpredicates: # 断言- Path/mxn/** # 匹配对应地址filters:- StripPrefix1 # 去掉地址中的第一部分
我们重新启动9006项目再去访问 自定义Filter
虽然Gateway给我们提供了丰富的内置Filter但是实际项目中自定义Filter的场景非常常见因此单独介绍下自定义FIlter的使用。
想要实现GateWay自定义过滤器那么我们需要实现GatewayFilter接口和Ordered接口
Slf4j
Component
public class MyFilter implements Ordered, GlobalFilter {/*** param exchange 可以拿到对应的request和response* param chain 过滤器链* return 是否放行*/Overridepublic Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {//获取第一个参数String id exchange.getRequest().getQueryParams().getFirst(id);//打印当前时间log.info(MyFilter 当前请求时间为:new Date());//判断用户是否存在if(StringUtils.isEmpty(id)){log.info(用户名不存在非法请求);//如果username为空返回状态码为407需要代理身份验证exchange.getResponse().setStatusCode(HttpStatus.PROXY\_AUTHENTICATION\_REQUIRED);// 后置过滤器return exchange.getResponse().setComplete();}return chain.filter(exchange);}/*** 设定过滤器的优先级值越小则优先级越高* return*/Overridepublic int getOrder() {return 0;}
}
当我们访问http://localhost:9006/mxn/nacos-provider/mxn/hello请求没有携带ID参数请求失败 当我们访问http://localhost:9006/mxn/nacos-provider/mxn/hello?id1请求请求成功 总结
到这里我们的GateWay就讲解完了对于GateWay的核心点主要有三个Route\Predicate\Filter我们搞懂了这三点基本上对于GateWay的知识就掌握的差不多了GateWay核心的流程就是路由转发执行过滤器链如果对文中有疑问的小伙伴欢迎留言讨论。
创作不易如果文中对你有帮助记得点赞关注您的支持是我创作的最大动力。
我是牧小农怕什么真理无穷进一步有进一步的欢喜~ 点赞再看养成习惯微信搜索【牧小农】关注我获取更多资讯风里雨里小农等你很高兴能够成为你的朋友。 项目源码地址公众号回复 sentinel即可免费获取源码