欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringCloud Zuul基于Consul配置及详解

程序员文章站 2023-04-07 09:08:15
一.构建工程 1.引入依赖 2.创建主类 3.配置application.properties 这里存在 api-a 和 api-b 两个微服务应用, 当请求http://localhost:port/api-a/helloWorld, 会被路由转发至 api-a 服务的 /helloWorld 接 ......

一.构建工程

  1.引入依赖

        <!--springboot2.0以上版本需引入该依赖-->
        <dependency>
            <groupid>org.springframework.cloud</groupid>
            <artifactid>spring-cloud-starter-netflix-zuul</artifactid>
        </dependency>
        <dependency>
            <groupid>org.springframework.cloud</groupid>
            <artifactid>spring-cloud-starter-consul-discovery</artifactid>
        </dependency>

 

  2.创建主类

@springbootapplication
@enablediscoveryclient
@enablezuulproxy
@restcontroller
public class application {
    public static void main(string[] args) {
        springapplication.run(application.class, args);
    }

}

  3.配置application.properties

zuul.routes.api-a.path=/api-a/**
zuul.routes.api-a.service-id=api-a

zuul.routes.api-b.path=/api-b/**
zuul.routes.api-b.service-id=api-b

  这里存在 api-a 和 api-b 两个微服务应用, 当请求http://localhost:port/api-a/helloworld, 会被路由转发至 api-a 服务的 /helloworld 接口, 当请求http://localhost:port/api-b/helloworld, 会被路由转发至 api-b 服务的 /helloworld 接口. 当请求 url 符合配置规则时, 就会被转发至 service-id 对应的微服务应用接口.

 

  4.配置请求过滤

  springcloud zuul 还有另一个和核心功能: 请求过滤. zuul 允许开发者在 api 网关上通过定义过滤器来实现对请求的拦截与过滤, 实现方法非常简单, 只需继承 zuulfilter 抽象类并实现它定义的4个抽象函数就可以完成对请求的拦截和过滤.

public class mygatewayfilter extends zuulfilter {

  /*4种过滤器类型,
  pre:可以在请求被路由之前调用,
  route:在路由请求时候被调用,
  post:在route和error过滤器之后被调用, 
  error:处理请求时发生错误时被调用*/
  @override 
  public string filtertype() {
    return "pre";
  }
    @override
    public int filterorder() {
        return 0;  //优先级为0,数字越大,优先级越低
    }

    @override
    public boolean shouldfilter() {
        return true;  // 是否执行该过滤器,此处为true,说明需要过滤
    }

    @override
    public object run() {
        requestcontext ctx = requestcontext.getcurrentcontext();
        httpservletrequest request = ctx.getrequest();

        log.info(string.format("%s request to %s", request.getmethod(), request.getrequesturl().tostring()));

        object accesstoken = request.getparameter("token");  //获取token参数
        if (accesstoken == null) {
            log.warn("token is empty");
            ctx.setsendzuulresponse(false);  //过滤该请求, 不对其进行路由
            ctx.setresponsestatuscode(401);  //返回错误码
            ctx.setresponsebody("token is null!");  //返回错误内容
            return null;   //zuul还未对返回数据做处理
        }
    return null; } }

  

  创建过滤器后,它并不会直接生效, 我们还需为其创建具体的 bean 才能启动该过滤器.

@springbootapplication
@enablediscoveryclient
@enablezuulproxy
@restcontroller
public class lixjapplication {

    public static void main(string[] args) {
        springapplication.run(lixjapplication.class, args);
    }

    @bean
    public mygatewayfilter mygatewayfilter(){
        return new mygatewayfilter();
    }
}

 

二. 路由详解

  1.路径匹配规则  

    /api-a/?    可以匹配 /api-a/ 之后拼接一个任务字符的路径 , 比如 /api-a/a , /api-a/b , /api-a/c

    /api-a/*    可以匹配 /api-a/ 之后拼接任意字符的路径, 比如 /api-a/a, /api-a/aaa, /api-a/bbb . 但它无法匹配 /api-a/a/b 这种多级目录路径

    /api-a/**   可以匹配 /api-a/* 包含的内容之外, 还可以匹配形如 /api-a/a/b 的多级目录路径

 

  2.路由匹配顺序

    随着版本的迭代, 我们需要对一个服务做一些功能拆分, 将原属于 api-a 服务的某些功能拆分到另一个全新的服务 api-a-part 中, 而这些拆分的外部调用 url 路径希望能够符合规则 /api-a/part/** .

    zuul.routes.api-a.path=/api-a/**
    zuul.routes.api-a.service-id=api-a

    zuul.routes.api-a-part.path=/api-a/part/**
    zuul.routes.api-a-part.service-id=api-a-part

    在源码中, 路由规则是通过 linkedhashmap 保存的, 也就是说, 路由规则的保存时有序的, 而内容的加载是通过遍历配置文件中路由规则依次加入的, 所以导致问题的根本原因是对配置文件中内容的读取, 但上述properties配置无法保证路由规则加载顺序, 我们需要使用 yml 文件来配置, 以实现有序的路由规则. 

zuul:
    routes:
        api-a-part:
            path=/api-a/part/**
            service-id=api-a-part 
        api-a:
            path=/api-a/**
            service-id=api-a        

 

  3.本地跳转 

zuul.routes.api-c.path=/api-c/**
zuul.routes.api-c.url=forward:/api-c

 

    以上配置使用了本地跳转,当 url 符合 /api-c/** 规则时,会被网关转发到 自己本身 服务的对应接口.