Gateway网关

目录

作用:

搭建网关

路由断言

Gateway中的路由过滤器配置

全局过滤器

 案例:定义全局过滤器,拦截用户判断身份

过滤器执行顺序

跨域请求处理


作用:

身份认证:用户能不能访问

服务路由:用户访问到那个服务中去

负载均衡:一个服务可能有多个实例,甚至集群,负载均衡就是你的请求到哪一个实例上去

Gateway网关_第1张图片

 还一个请求限流功能:对请求进行流量限制,对服务进行请求限制;

两种网关实现:

Gateway网关_第2张图片


搭建网关

Gateway网关_第3张图片

 流程:

1.首先咱们先将服务以及网关注册到Nacos注册中心;2.然后用户请求,网关路由进行判断地址是不是以/user或者/order开头的,如果是,则跳转路由目标地址uri,然后请求地址则会代理到userservice或者是orderservice,3.然后再从Nacos注册中心里根据服务orderservice或者是xxxservice找到对应的地址,4.最后根据负载均衡找到实例

Gateway网关_第4张图片

1.创建gateway网关模块

Gateway网关_第5张图片

 2.导入nacos服务发现依赖和gateway依赖,说明是个网关

     
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
            2.2.5.RELEASE
        

        
        
            org.springframework.cloud
            spring-cloud-starter-gateway
        

3.然后进行配置文件的配置,配置服务的信息以及地址将其注册到Nacos中还有路由的信息(1.路由标示2.目标地址3.路由断言)

server:
  port: 10010
spring:
  application:
    name: gateway
  cloud:
    nacos:
      server-addr: localhost:8848 #nacos地址
    gateway:
      routes:
        - id: user-service # 路由标示,必须唯一
          uri: lb://userservice # 路由的目标地址
          predicates: # 路由断言,判断请求是否符合规则
            - Path=/user/** # 路径断言,判断路径是否以/user开头,如果是则符合,跳转路由

        - id: order-service
          uri: lb://orderservice
          predicates:
            - Path=/order/**

Gateway网关_第6张图片

然后我们访问10010端口,断言predicate设置的path路径正确即可访问

Gateway网关_第7张图片


路由断言

Predicate作用:将断言规则解析成条件作为请求过来的判断 

Gateway网关_第8张图片

 11种Predicate路由断言工厂:Gateway网关_第9张图片

 配置:

server:
  port: 10010
spring:
  application:
    name: gateway
  cloud:
    nacos:
      server-addr: localhost:8848 #nacos地址
    gateway:
      routes:
        - id: user-service # 路由标示,必须唯一
          uri: lb://userservice # 路由的目标地址
          predicates: # 路由断言,判断请求是否符合规则
            - Path=/user/** # 路径断言,判断路径是否以/user开头,如果是则符合,跳转路由
        - id: order-service
          uri: lb://orderservice
          predicates:
            - Path=/order/**
            - After=2022-05-14T15:14:47.433+08:00[Asia/Shanghai]

Gateway中的路由过滤器配置

Gateway网关_第10张图片

 过滤器可以对于请求进行过滤:比如请求头请求体请求参数....

 也可以对响应进行过滤,给到用户服务想给的内容

Gateway网关_第11张图片

过滤器案例 :加请求头

1.我们直接在配置文件中进行配置即可:

第一种:在路由中配置(这是一个服务的范围,对于访问这个服务会有过滤)

第二种:与routes范围一样,是对于整个全局的,所有服务;

 gateway:
      routes:
        - id: user-service # 路由标示,必须唯一
          uri: lb://userservice # 路由的目标地址
          predicates: # 路由断言,判断请求是否符合规则
            - Path=/user/** # 路径断言,判断路径是否以/user开头,如果是则符合,跳转路由

        - id: order-service
          uri: lb://orderservice
          predicates:
            - Path=/order/**
          filters: # 过滤器添加一个请求头
            - AddRequestHeader=Truth,Itcast is freaking aowsome!
      default-filters: # 对所有路由生效
        - AddRequestHeader=Truth,Itcast is freaking awesome!

这里我们对用户服务增加一个请求头信息,访问localhost:10010/user/1,服务器就会打印过滤器中的信息;

  @GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id,
                          @RequestHeader(value="Truth",required = false) String truth) {
        System.out.println("truth:"+truth);
        return userService.queryById(id);
    }

  

Gateway网关_第12张图片


全局过滤器

作用:处理一切进入网关的请求和微服务的响应,与GatewayFilter的作用一样

与GatewayFilter区别:前者通过自定义配置可以处理逻辑,后者的逻辑需要自己写代码实现;

Gateway网关_第13张图片

 案例:定义全局过滤器,拦截用户判断身份

Gateway网关_第14张图片

 步骤:

我们直接定义一个全局过滤器即可,实现GlobalFilter

package cn.itcast.gateway;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @author diao 2022/5/9
 */
@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter {

    /**
     *
     * @param exchange:里面有request和response
     * @param chain:过滤器链
     * @return
     */
    @Override
    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        //1.得到request中的所有参数
        MultiValueMap params = request.getQueryParams();

        //2.获取里面含有authorization的参数
        String auth = params.getFirst("authorization");

        //3.判断参数是否符合:authorization==admin
        if("admin".equals(auth)){
            return chain.filter(exchange);
        }

        //4.进行拦截,并且设置响应状态码
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        return exchange.getResponse().setComplete();
    }
}

当request请求参数authorization!=admin,被拦截的情况

Gateway网关_第15张图片

 当加上请求参数,并且值符合

Gateway网关_第16张图片

 总结:

跟Gateway过滤器最大的区别就是,它可以自定义

Gateway网关_第17张图片


过滤器执行顺序

Gateway网关_第18张图片

  可以发现GlobalFilter和DefaultFilter、当前路由器是同一种

Gateway网关_第19张图片

 执行顺序注意事项:

1.order值越小优先级越高,优先看order值

2.当order值一样时,顺序好似defaultFilter优先,因为它是排在路由routes​​​​​​

Gateway网关_第20张图片


跨域请求处理

跨域:域名不一致

端口不一致:8080与8081

跨域问题:浏览器禁止请求的发起者与服务端发生跨域的ajax请求,请求被浏览器拦截的问题——>像我们之前的订单服务调用用户服务就不属于跨域问题;

CORS方案:

Gateway网关_第21张图片

 跨域模板:

  globalcors: # 全局的跨域处理
        add-to-simple-url-handler-mapping: true # 网关放行请求
        cors-configurations:
          '[/**]':
            allowedOrigins: # 允许哪些网站跨域请求
              - "http://localhost:8090"
              - "http://www.leyou.com"
            allowedMethods: #运行跨域ajax的请求方式
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
            allowedHeaders: "*" #允许在请求中有头信息
            allowCredentials: true # 是否允许携带cookie
            maxAge: 3600

项目实践

对比于寻常的nginx,除了负载均衡之外,我们的gateway可以对异常进行统一处理,包括权限设置,跨域等等;

主要是通过nacos中拉去服务,通过服务名称进行拉取

Gateway网关_第22张图片

 Gateway网关_第23张图片

网关相关配置

package com.atguigu.gateway.filter;

import com.google.gson.JsonObject;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 

* 全局Filter,统一处理会员登录与外部不允许访问的服务 *

*/ @Component public class AuthGlobalFilter implements GlobalFilter, Ordered { private AntPathMatcher antPathMatcher = new AntPathMatcher(); @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); String path = request.getURI().getPath(); //谷粒学院api接口,校验用户必须登录 if(antPathMatcher.match("/api/**/auth/**", path)) { List tokenList = request.getHeaders().get("token"); if(null == tokenList) { ServerHttpResponse response = exchange.getResponse(); return out(response); } else { // Boolean isCheck = JwtUtils.checkToken(tokenList.get(0)); // if(!isCheck) { ServerHttpResponse response = exchange.getResponse(); return out(response); // } } } //内部服务接口,不允许外部访问 if(antPathMatcher.match("/**/inner/**", path)) { ServerHttpResponse response = exchange.getResponse(); return out(response); } return chain.filter(exchange); } @Override public int getOrder() { return 0; } private Mono out(ServerHttpResponse response) { JsonObject message = new JsonObject(); message.addProperty("success", false); message.addProperty("code", 28004); message.addProperty("data", "鉴权失败"); byte[] bits = message.toString().getBytes(StandardCharsets.UTF_8); DataBuffer buffer = response.bufferFactory().wrap(bits); //response.setStatusCode(HttpStatus.UNAUTHORIZED); //指定编码,否则在浏览器中会中文乱码 response.getHeaders().add("Content-Type", "application/json;charset=UTF-8"); return response.writeWith(Mono.just(buffer)); } }

你可能感兴趣的:(微服务,gateway,java,开发语言)