SpringCloud的Gateway网关
1. 网关做什么使用的?
不同的微服务有不同的接口地址,我们目前开发都是前后端分离的项目,我们后端开发了很多的服务,没用网关的时候,对前端就不太友好了,因为我们不同服务的接口地址都不一样,前端调用起来就很麻烦,所以这个时候我们就需要使用API网关统一代理,有API网关转发到不同的服务
为什么不使用nginx呢?
如果你是同一个项目部署了两份可以用nginx来做负载均衡,但是我们现在是微服务,是不同的项目,如果我们使用nginx的话,总不能一会请求这个服务,一会请求另外一个服务吧,所以这个时候使用nginx是不现实的,nginx的使用场景是对于同一个项目来说一台服务器顶不住了所以需要配置来用nginx做负载均衡,并不适用于我们现在的微服务
nginx对于同一个项目可以做负载均衡,而API网关也可以,对于同一个项目做负载均衡,对于不同的项目可以做路由,而且,对于不同的服务间如果需要登录才能访问,网关可以写过滤器进行过滤,这些都是就是网关的强大之处
2. GateWay三大功能
路由 + 过滤 + 断言
3. GateWay怎么使用
1)创建网关服务:springcloud_gateway_service
2)导入网关依赖:注意,在网关微服务中就不能导入spring-cloud-start-web依赖了,这两个之间会产生冲突
3)网关也可以整合到nacos上
在application.yml文件中配置网关信息:网关是怎么路由服务的呢?首先通过访问网关服务,那么在我们找到我们path路径,然后就去找id上的服务,然后通过访问对应url的地址,就路由到我们真正的服务上去了server:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | port: 7001 spring: application: name: springcloud-gateway-service cloud: gateway: # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务 discovery: locator: enabled: true lower- case -service-id: true # 服务名称转成小写 routes: #配置网关的路由服务,如果想要路由多个服务,就继续追加 - id: order-service #路由的id 一般是服务名 uri: http: //127.0.0.1:8080 predicates: - Path=/order/**,/ts/** # 如果有多个controller就配置多个,如果匹配所有路径那就/**<br> |
http://127.0.0.1:7001/order-service/order/12
4)如果我们想上面访问的时候需要手动写死url的地址,如果服务地址发生更改,然后我们还需要来网关中作修改,显然这样是不方便的,所以,网关需要和nacos注册中心结合时候,如下
当然,在网关服务中还是需要导入nacos对应的依赖包的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | spring: cloud: gateway: # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务 discovery: locator: enabled: true lower- case -service-id: true # 服务名称转成小写 routes: - id: babytree-admin-service #文件微服务 uri: lb: //babytree-admin-service predicates: - Path=/babytree/**,/tCookbooks/**,/tDish/** ,/tIngredien/**,/tInStep/** ,/tClass/** # 如果有多个controller就配置多个,如果匹配所有路径 - id: babytree-file-service #文件微服务 uri: lb: //babytree-file-service predicates: - Path=/file/** |
小知识:为什么nacos没有负载均衡?
nacos不仅仅支持springcloud组件,还支持其他的组件,所以就没有集成
5)将网关服务配置到nacos上,导入nacos配置中心对应的依赖包
注意:在网关配置中,path中的路径不允许出现重名的情况,否则会导致404找不到
6)关于网关配置的其他信息
表示请求中是否包含我们指定的参数
注:多个路由规则可以一起使用
此时如果在路径上不加orderName就会报404错误
1 2 3 4 5 6 | routes: - id: springcloud-order-service #路由的id 一般是服务名 uri: lb: //springcloud-order-service predicates: #表示判断条件 - Path=/order/**,/ts/** - Query=orderName #匹配请求的参数中必须包含orderName参数 |
匹配请求方式
如果请求方式不是get,delete就会报405
1 2 3 4 5 6 7 | routes: - id: springcloud-order-service #路由的id 一般是服务名 uri: lb: //springcloud-order-service predicates: #表示判断条件 - Path=/order/**,/ts/** # - Query=orderName #匹配请求的参数中必须包含orderName参数 - Method=GET,DELETE #匹配所有GET、delete请求 |
可以实现秒杀的网关过滤
1 2 3 4 5 6 7 8 | routes: - id: order-service #路由的id 一般是服务名 uri: http: //127.0.0.1:8080 predicates: - Path=/order/**,/ts/** # 如果匹配所有路径那就/** # - Query=orderName #匹配请求的参数中必须包含orderName参数 - Method=GET,DELETE #匹配所有GET、delete请求 - After= 2022 - 03 -17T20: 42 : 47.789 - 07 : 00 [Asia/Shanghai] # 匹配Shanghai时间 2022 年 03 月 17 号以后的请求 |
匹配请求头
1 2 3 4 5 6 7 | - id: order-service #路由的id 一般是服务名 uri: http: //127.0.0.1:8080 predicates: # - Query=orderName #匹配请求的参数中必须包含orderName参数 - Method=GET,DELETE #匹配所有GET、delete请求 - After= 2022 - 03 -17T20: 42 : 47.789 - 07 : 00 [Asia/Shanghai] # 匹配Shanghai时间 2022 年 03 月 17 号以后的请求 - Header=AuthToken #匹配规则是请求头必须携带名字叫AuthToken的值才可以访问 |
远程ip地址 ip白名单
1 2 3 4 5 6 7 8 9 10 | routes: - id: order-service #路由的id 一般是服务名 uri: http: //127.0.0.1:8080 predicates: - Path=/order/**,/ts/** # 如果匹配所有路径那就/** # - Query=orderName #匹配请求的参数中必须包含orderName参数 - Method=GET,DELETE #匹配所有GET、delete请求 - After= 2022 - 03 -17T20: 42 : 47.789 - 07 : 00 [Asia/Shanghai] # 匹配Shanghai时间 2022 年 03 月 17 号以后的请求 - Header=AuthToken #匹配规则是请求头必须携带名字叫AuthToken的值才可以访问 - RemoteAddr= 10.112 . 3.147 , 192.168 . 56.1 , 192.168 . 142.1 # 只允许访问此ip才可以访问到 |
GateWay的过滤功能:单点登录
在网关中做登录之后,其他需要登录的服务就不需要登录了
单点登录是使用shrio + jwt来实现的,就是前端发送请求将用户名密码提交给后端,通过网关进行校验,网关中校验账号密码信息是否正确,如果正确的话就使用jwt将用户信息进行加密,然后将加密后的密文返回给前端,也叫做令牌,然后前端的业务请求里面就可以携带着这个令牌发送到后端,后端过滤校验token是否正确,正确的话就直接放过,我们也可以对这个令牌配置时效性,超过一定的时间的话这个令牌就失效了,需要重新登录生成令牌信息
Token的设计思想:
以JSON Web Token(JWT)为例,Token有三部分组成:
head头部信息:记录了使用的加密算法信息
Payload净荷信息:记录了用户信息和过期时间等
Signature签名信息:根据Header中的加密算法和palyload中的用户信息以及密钥key来生成,是服务端验证服务端的重要依据
1. 使用jwt需要导入相关依赖
1 2 3 4 5 | <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version> 0.9 . 0 </version> </dependency> |
2) 我们需要在登录接口中,也就是当前端传递用户名和密码之后我们需要在该接口中使用shrio校验用户信息,如果校验通过,在返回前端之前将用户信息进行加密,然后封装成token返回给前端这个token,也就是令牌
注意:在封装token的时候不要将一些敏感信息封装进去,比如说密码 和 盐
3)封装好了token返回给前端之后,那么当我们需要访问其他服务的时候,就可以通过请求头的方式携带到其他服务中去,然后使用JWTUtil工具类解析Token就可以拿到我们的用户信息了
4)针对于不同的服务里面我们可能都需要校验是否登录,所以单独在每个服务中我们进行解析校验就太冗余了,此时我们就需要在网关中对做统一校验,使用网关过滤器
4)针对上述采用网关过滤器的方式来实现单点登录,就可以控制需要登录的服务都必须登录才可以访问了,但是还存在一个问题,那就是在我们的项目中还有一些服务是不需要登录也能访问的,但是现在是在网关中都限制了,那么我们可以在网关配置文件中对一些不需要登录的服务接口进行放行
然后在网关过滤器接口中取出需要放过的路径:
当然,我们也可以在配置文件中将放过的路径写成数组的形式:
那么,针对于数组形式,在网关中取出配置文件中的放过路径的时候,需要采用以下方式:
5)获取到网关中需要放过的路径之后,那么我们就可以在重写的过滤方法中写放过逻辑了:
此时我们需要一个spring提供给我们的路径匹配器类,来帮我们判断当前路径是否在放过的路径中
private PathMatcher pathMatcher = new AntPathMatcher();
这样,就实现了我们网关对于不同的服务请求接口的拦截和放过了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了