gateway网关使用

准备

搭建一个eureka服务器和一个普通web模块,然后搭建网关模块。。

测试用的普通接口
@GetMapping(value = "/payment/get/{id}")
    public Result<Payment> getPaymentById(@PathVariable("id") Long id) {
        Payment payment = paymentService.getPaymentById(id);
        if(payment != null) {
            return new Result<>(200,"查询成功,serverPort:  "+8081,payment);
        }else{
            return new Result<>(444,"没有对应记录,查询ID: "+ id,null);
        }
    }

依赖:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

使用很方便,有两种配置方式,一种是配置文件,一种是注入Bean

简单入门

server:
  port: 9527

spring:
  application:
    name: gateway
  cloud:
    gateway:
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001          #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由
eureka:
  instance:
    instance-id: gateway
    prefer-ip-address: true #显示ip地址
  client:
    #表示是否将自己注册进Eurekaserver默认为true。
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetchRegistry: true
    service-url:
      defaultZone: http://localhost:7001/eureka

打开浏览器http://localhost:9527/payment/get/1可以查询到结果

相同功能的bean配置也非常简单

@Bean
    public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder){
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        return routes.route("paymentRouter",
                r->r.path("/payment/get/**")
                        .uri("http://localhost:8001")).build();
    }

动态路由配置

将测试结构变成一个服务集群,一个eureka7001+服务提供者8000+服务提供者8001。默认情况下Gateway会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能(不写死地址)。

修改yml文件开启动态路由

      discovery:
        locator:
          enabled: true # 开启动态路由

全部yml

server:
  port: 9527

spring:
  application:
    name: gateway
  cloud:
    gateway:
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: lb://payment # payment是微服务名
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由
      discovery:
        locator:
          enabled: true # 开启动态路由
eureka:
  instance:
    instance-id: gateway
    prefer-ip-address: true #显示ip地址
  client:
    #表示是否将自己注册进Eurekaserver默认为true。
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetchRegistry: true
    service-url:
      defaultZone: http://localhost:7001/eureka

等价于yml开启动态路由后

 @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder){
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        return routes.route("paymentRouter",
                r->r.path("/payment/get/**")
                        .uri("lb://payment")).build();
    }

访问http://localhost:9527/payment/get/1,发现可以实现基本的轮询负载均衡8000/8001
注意
Gateway的负载均衡依然使用的是ribbon,按照ribbon的加@RibbonClient注解的配置就好

常用的predicate

bean中多个predicate可以用and方法连接

  • The After Route Predicate Factory
  • The Before Route Predicate Factory
  • The Between Route Predicate Factory 请求时间的限制
  • The Cookie Route Predicate Factory 请求cookie的限制
  • The Header Route Predicate Factory 请求头的限制
  • The Host Route Predicate Factory
  • The Method Route Predicate Factory 请求方法的限制 get、post。。。
  • The Path Route Predicate Factory (上边使用的)
  • The Query Route Predicate Factory 查询条件限制
  • The RemoteAddr Route Predicate Factory
  • The weight Route Predicate Factory
  //before、between也一样
    public RouteLocator after(RouteLocatorBuilder routeLocatorBuilder){
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        //这个时间段后会被匹配
        ZonedDateTime zonedDateTime = ZonedDateTime.now();
        
        return routes.route("paymentRouter",
                r->r.after(zonedDateTime)
                        .uri("lb://payment")).build();
    }

 //header请求匹配也是一样的
public RouteLocator cookie(RouteLocatorBuilder routeLocatorBuilder){
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();

        return routes.route("paymentRouter",
                //一个是cookie的名字,一个是正则表达式,合适才会执行
                r->r.cookie("key","regex")
                        .uri("lb://payment")).build();
    }

过滤器

@Component
public class LogFilter implements GlobalFilter , Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("我是全局过滤器   " + new Date());
        String username = exchange.getRequest().getQueryParams().getFirst("username");
        if (username==null){
            System.out.println("用户名不存在o(╥﹏╥)o  " + new Date());
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    //数字越小,优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容