SpringCloudGateway网关 学习记录
作者:互联网
微服务网关的概念:
什么是微服务网关: 现在流行的微服务架构中,对大多数的服务进行指量上的拓展增多以应对服务的工作量需求。对此每个微服务都会有对应的ip端口。 在大型的项目中可能这种对外的访问ip端口是成百上千的。对访问与管理是很不方便的。对这种情况应对的方案就是配置一个微服务 网关。让所有的请求访问到微服务网关中再由网关进行同一的管理(权监、负载均衡、日志等等..)。这样对我们的维护与使用也是 极大的遍历。 作用和应用场景: 网关的作业:负载均衡、监控、用户权限鉴定、缓存等等... 其中最主要的就是与外界取得联系对服务暴露进行统一管理 常见的API网关实现方式: SpringCloudGateway: SpringCloud提供的网关服务 Nginx:使用Nginx的反向代理和负载均衡可实现对api服务器的负载均衡及高可用 问题:自注册的问题和网关本身的扩展性 Zuul:Netflflix开源,功能丰富,使用JAVA开发,易于二次开发;需要运行在web容器中,如Tomcat。 问题:缺乏管控,无法动态配置;依赖组件较多;处理Http请求依赖的是Web容器,性能不如Nginx;
微服务网关GateWay
ZUUL是一个基于阻塞IO的微服务网关。其内在原理也依赖Servlet。所以其整体的性能并不是很良好。
对于JAVA项目来说SpringCloudGateWay是主场作战。在Spring大家庭中融入的比较好。所以使用起来相对方便。
在SpringCloudGateWay中有三个比较核心的概念:
1. 路由(route) 路由是网关最基础的部分,路由信息由一个ID、一个目的URL、一组断言工厂和一 组Filter组成。如果断言为真,则说明请求URL和配置的路由匹配。 2. 断言(predicates) Java8中的断言函数,Spring Cloud Gateway中的断言函数输入类型是 Spring5.0框架中的ServerWebExchange。Spring Cloud Gateway中的断言函数允许开发者去定 义匹配来自Http Request中的任何信息,比如请求头和参数等。 3. 过滤器(fifilter) 一个标准的Spring webFilter,Spring Cloud Gateway中的Filter分为两种类型, 分别是Gateway Filter和Global Filter。过滤器Filter可以对请求和响应进行处理
SpringCloud Gateway的使用:
(1)导入依赖
<!-- 网关依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
(2)配置启动类
package com.kerry.gateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class GatewayServerApplication { public static void main(String[] args) { SpringApplication.run(GatewayServerApplication.class, args); } }
(3)编写application.yml配置文件
server: port: 8001 spring: application: name: server-gateway #服务名称 cloud: gateway: routes: - id: category-service #自定义的路由id,保持唯一 uri: http://127.0.0.1:9001 #目标服务地址 predicates: #路由条件 可于网上搜索更多 - Path=/category/**,/admin/category/** - id: headline-service uri: http://127.0.0.1:9002 predicates: - Path=/headline/**,/admin/headline/**
到此简简单单的路由功能已经实现了,但是我们可以注意到在目标服务地址上我们填写的对应的ip端口,这样写死的话
明显是不够完善的。对此我们可以引入动态路由
动态路由
(1)添加注册中心依赖<!-- eureka网关--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
(2)修改application.yml配置文件
server: port: 8001 spring: application: name: server-gateway #服务名称 cloud: gateway: routes: - id: category-service uri: lb://service-category predicates: - Path=/category/**,/admin/category/** - id: headline-service uri: lb://service-headline predicates: - Path=/headline/**,/admin/headline/** eureka: client: service-url: defaultZone: http://127.0.0.1:8000/eureka #,http://127.0.0.1:8999/eureka/ registry-fetch-interval-seconds: 5 # 获取服务列表的周期:5s instance: prefer-ip-address: true #使用ip注册 ip-address: 127.0.0.1uri : uri以 lb: //开头(lb代表从注册中心获取服务),后面接的就是你需要转发到的服务名称
重写转发路径
在SpringCloud Gateway中,路由转发是直接将匹配的路由path直接拼接到映射路径(URI)之后,那么在微服务开发中往往没有那么便利。 这里就可以通过RewritePath机制来进行路径重写。 (1)案例改造 修改 application.yml ,将匹配路径改为 /product-service/** 重新启动网关,我们在浏览器访问http://127.0.0.1:8080/product-service/product/1,会抛出404。这是由于路由转发规则默认转发到商品微服务 ( http://127.0.0.1:9002/product-service/product/1 )路径上,而商品微服务又没有 product-service 对应的映射配置。 (2)添加RewritePath重写转发路径spring: application: name: api-gateway #指定服务名 cloud: gateway: routes: - id: product-service uri: lb://shop-service-product predicates: - Path=/product-service/** filters: - RewritePath=/product-service/(?<segment>.*), /$\{segment}通过RewritePath配置重写转发的url,将/product-service/(?.*),重写为{segment},然后转发到订单 微服务。比如在网页上请求http://localhost:8080/product-service/product,此时会将请求转发到 http://127.0.0.1:9002/product/1( 值得注意的是在yml文档中 $ 要写成 $\ )
过滤器
SpringCloudGateway中不仅有路由功能还支持对请求的过滤。相比Zuul网关,SpringCloudGateway的过滤器功能就相对较少 只有:"pre"和"post"两个。 pre:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。 post:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTPHeader、收集统计信息和指标、将响应从微服务发送给客户端等。 SpringCloudGateway的过滤器类型有两种:GatewayFilter:应用到单个路由或者一个分组的路由上 GlobalFilter:应用到所有的路由上。
我们可以通过GlobalFilter类来实现统一鉴权:
开发中的鉴权逻辑: 1.当客户端第一次请求服务时,服务端对用户进行信息认证(登录) 2.认证通过,将用户信息进行加密形成token,返回给客户端,作为登录凭证 3.以后每次请求,客户端都携带认证的token 4.服务端对token进行解密,判断是否有效。
代码实现:
package com.kerry.gateway.filter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; /* * 该类为用户登录权监过滤器 todo:后期将token参数改到session或者是redis中。 * 目前的代码效果为:当请求链接来到网关的时候会判断请求参数中是否有token参数,如果无的话则视为没有权限,如果有则视为有权限 * 例子: * http://localhost:8001/admin/category/demo.do/1 效果:访问失败 * http://localhost:8001/admin/category/demo.do/1?token=1 效果:访问成功 * */ @Slf4j @Component public class LoginFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { log.info("执行了自定义的登录权监全局过滤器"); //String url = exchange.getRequest().getURI().getPath(); // 忽略以下url请求 // if(url.indexOf("/login") >= 0){ // return chain.filter(exchange); // } String token = exchange.getRequest().getQueryParams().getFirst("token"); if (StringUtils.isBlank(token)) { log.info( "token is empty ..." ); exchange.getResponse().setStatusCode( HttpStatus.UNAUTHORIZED ); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } @Override public int getOrder() { return 0; } }
学习小记:
SpringCloud Gateway底层使用的web框架是webflux和SpringMVC不兼容引入的限流组件是hystrix。redis底层不再使用jedis,而是lettuce。
由于SpringCloud Gateway在SpringCloud上是主场作战,所以在进行网关上的使用上相对于ZUUL等其他技术上更为简单有效。它是基于Nttey的响应式开发模式
SpringCloud Gateway的核心概念有路由(route)断言(predicates)过滤器(filter)
Gateway的路由功能上很强大,支持各种各样的条件匹配同时也支持动态路由【动态路由需引入Eureka服务】。
Gateway在过滤器的功能上比不上ZUUL那么丰富,只要'pre'和'post'。一个是请求被路由之前调用,一个是路由到微服务之后调用。
过滤器的类型有GatewayFilter(局部)和 GlobalFilter(全局)。全局过滤器较为常用,可作用于用户信息认证校验token。
SpringCloud Gateway过滤器不止可以用作用户信息校验,还可以作为网关限流
限流算法:计数器、漏桶算法、令牌桶算法
计算器算法:规定时间内只能访问到最大阈值,到时间会重置累计数重新增加
漏桶算法:这个算法跟线程池隔离类似,规定一个容量池的大小,限制住访问量
令牌桶算法:是漏桶算法的一种改进更好的控制访问量的灵活度。
网关限流中
1.基于Filter的限流,是Gateway官方提供的基于令牌桶的限流法,需要引入
redis依赖,在配置中可以调整令牌桶的容量与数度还有对象来源
2.基于Sentinel的限流,也是需要引入依赖,编写配置类,网关配置。基于Sentinel
的Gateway限流底层也是依靠Filter功能,只需要在配置类中注入实例定义好限流方法
即可实习限流功能。
在分布式架构体系中,高可用是非常关键的存在。网关统一了服务的对外访问。那如
果说是单一的网关服务万一宕机,那对整个项目的影响是巨大的。所以我们应该
对网关也进行高可用的部署。然后将网关交给nginx进行统一管理,还能进行负载均衡
这样就可以大大的降低网关服务层的错误率。
标签:网关,服务,service,记录,SpringCloudGateway,product,Gateway,路由 来源: https://www.cnblogs.com/zcl1116/p/16168594.html