路由是构建网关的基本模块,它有ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由.
开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改.
核心逻辑: 路由转发+执行过滤器链
注意网关作为微服务也需要注册到服务中心,所以导入一来是也需要注册中心的相关项.; 同时gateway不需要引入web的相关依赖,否则启动会报错;
网关就是看门的,没有业务类
网关的理解:保护一些服务地址端口不暴露给外部,对外暴露网关端口; 外部想访问某个服务访问网关端口,由网关调用响应的服务; 网关好比看门的保安,对外阻止攻击等; 在application.yml中添加网关的配置:
spring: application: name: cloud-gateway cloud: gateway: routes: - id: payment_routh #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名 uri: http:localhost:8001 #匹配后提供服务的路由地址 predicates: - Path=/payment/get/** #断言,路径相匹配的进行路由 - id: payemnt_routh2 #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名 uri: http://localhost:8001 #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** #断言,路径相匹配的进行路由通过以上配置,平时访问服务提供者需要访问:localhost:8001/payment/get/**; 配置网关后可以访问localhost:9527/payment/get/**也可以访问服务提供者
在入门配置中用的就是yml配置方式,此种方式会随着网关的配置种类增加文件会很长
多数情况下客户端访问服务提供者时是通过ribbon实现负载均衡的,又ribbon通过某种机制调用服务提供者;现在我们通过网关实现负载均衡的功能(动态路由); 默认情况下GateWay会根据注册中心注册的服务列表.以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能;
Predicate就是为了实现一组匹配规则,让请求过来找对应的Route进行处理.
①After Route Predicate
获取时间格式:
public class T1 { public static void main(String[] args) { ZonedDateTime zonedDateTime = ZonedDateTime.now(); System.out.println(zonedDateTime); } }②Before Route Predicate ③Between Route Predicate 以上三个是时间级别的
④Cookie Route Predicate Cookie级别的
用curl发送请求: 带cookie
curl http://localhost:9527/payment/discovery 不带cookie⑤Header Route Predicate
⑥Host Route Predicate
⑦Method Route Predicate
⑧Path Route Predicate ⑨Query Route Predicate
路由过滤器可以用于修改进入HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用. Spring Cloud Gateway 内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生. 他的生命周期只有两个:pro 和post(业务逻辑之前和之后)。有点像spring的前置通知和后置通知. 他的种类分为:GatewayFilter和GlobalFilter(单一的和全局的);
自定义全局GlobalFilter 主要实现两个接口:
@Component @Slf4j public class MyLogGateWayFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { log.info("************come in MyLogGateWayFilter: "+new Date()); String uname = exchange.getRequest().getQueryParams().getFirst("uname"); if(uname==null){ log.info("*************用户名为null,非法用户"); exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE); return exchange.getResponse().setComplete(); } return chain.filter(exchange);//执行下一个过滤器链 } @Override public int getOrder() { return 0; //设置优先级 } }此时,再次访问就必须带上uname参数才能正常访问了