SpringCloud之Zuul网关使用篇

1. 环境准备

推荐本篇文章在《SpringCloud之Gateway使用篇》读,因为我们要使用它之前或者之后的环境。
当然可以到github上面访问项目代码:链接,直接拉下来使用。
这里我们介绍下环境
spring-cloud-parent (父工程,定义了springcloud的版本以及通用依赖)
----spring-cloud-eureka-server (Eureka Server 集群,端口9090,9091)
----spring-cloud-order-service-provider(订单服务,也是服务提供者,端口7070,7071)
----spring-cloud-user-service-consumer(用户服务,调用订单服务,端口8080,8081)
----spring-cloud-zuul-server(zuul网关服务,端口8030)

2.使用

2.1 最基础使用

2.1.1 新建zuul服务

在父工程spring-cloud-parent 新创建module spring-cloud-zuul-server

2.1.1.1 pom文件

添加eureka 客户端依赖 与zuul网关依赖

<dependencies>
    <!--eureka 客户端依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <!--zuul 网关-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>
</dependencies>

zuul其实使用的springmvc ,而不像gateway一样使用webflux
在这里插入图片描述

2.1.1.2 application配置文件

这里暂时只是配置了Eureka。

server:
  port: 8030
spring:
  application:
    name: spring-cloud-zuul-server
#eureka 配置
eureka:
  client:
    service-url:
      # eureka server url
      defaultZone: http://EurekaServerA:9090/eureka,http://EurekaServerB:9091/eureka
    register-with-eureka: true
    fetch-registry: true
  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
2.1.1.3 主启动类

需要在主启动类上面添加@EnableZuulProxy 注解,表示启用zuul
在这里插入图片描述

2.1.1.4 启动测试

分别启动Eureka Server 集群端口9090与9091,订单服务两个实例端口7070与7071,用户服务 一个实例8080,最后启动咱们这个zuul网关服务8030
postman或者浏览器访问:
http://127.0.0.1:8030/spring-cloud-user-service-consumer/user/data/getTodayStatistic/100
*** 注意:咱们在url中添加了用户服务服务名,因为咱们并没有在配置文件中配置路由规则***
在这里插入图片描述
多访问几次,发现有hystrix 的timeout
在这里插入图片描述
这个是因为我们没有配置这个hystrix熔断器,这我们后面再配置。

2.2 路由介绍

1.URL 路由,是直接写死在配置上的,不能进行负载均衡,可以是ip,也可以是域名,例如下面这种配置:

zuul:
  routes:
    baidu-router:
      path: /baidu
      url: http://www.baidu.com

在这里插入图片描述
2.第二种就是基于ribbon实现配置多个url来进行负载均衡,我们需要在url配置一个serivecId,然后使用这个serivceId配置ribbon的servers,这个servers可以配置多个,实际上还是使用了ribbon来做的负载均衡,就像下面这种配置

zuul:
  routes:
    baidu-router:
      path: /user/**
      url: spring-cloud-user-service-consumer
spring-cloud-user-service-consumer:
  ribbon:
    list-of-servers: http://127.0.0.1:8080

3.这种就是基于Eureka 来做的动态路由,我们需要在 Zuul 中集成 Eureka,在路由转发时可以转发到 Eureka 中注册的服务上,这样就很方便了,不需要我们去关心服务的上下线,我们只需要在router中配置serviceId与path就可以了,这种方式是使用最多的。
就像这种方式:

zuul:
  routes:
    user-service-consumer-router:
      path: /user/**
      service-id: spring-cloud-user-service-consumer

这个service-id就是这个注册到Eureka server 中的服务名,而这个path就是头匹配的。这种方式会默认给你去掉这个path,也就是去掉这个前缀,所以我请求的时候需要加个前缀,然后按照前缀匹配。比如说我这里请求spring-cloud-user-service-consumer的某个接口,/user/data/getTodayStatistic/100,然后我在使用zuul来路由的时候就需要就需要加上path里面这个user前缀,/user/user/data/getTodayStatistic/100,就变成这个样子了,当然你可以不开启这种去掉前缀的操作。使用配置 strip-prefix: false就可以了,例如下面这段配置:

zuul:
  routes:
    user-service-consumer-router:
      path: /user/**
      service-id: spring-cloud-user-service-consumer
      strip-prefix: false

这里我请求的时候就不需要加前缀了。

现在还有个问题就是 使用service-id这个前缀还是能访问到的
在这里插入图片描述
这里我们就需要配置一个ignored-services,例如下面的配置,这样配置只是单个的,如果想把所有服务的名字都屏蔽掉就要使用“*”号了。

zuul:
  routes:
    user-service-consumer-router:
      path: /user/**
      service-id: spring-cloud-user-service-consumer
      strip-prefix: false
  ignored-services: spring-cloud-user-service-consumer

在这里插入图片描述
配置好了就ok了,不可以访问了。
我们还有一个配置,就是在所有的router前面添加一个前缀,可以使用zuul.prefix来配置

zuul:
  routes:
    user-service-consumer-router:
      path: /user/**
      service-id: spring-cloud-user-service-consumer
      strip-prefix: false
  ignored-services: spring-cloud-user-service-consumer
  prefix: /beijing

在这里插入图片描述

2.3 过滤器介绍

我们可以先来看下这个zuul的过滤器一个生命周期图,然后咱们再来说这个zuul过滤器的分类
在这里插入图片描述
我们可以很清晰的看到,当我们请求来的时候,先到pre 类型的过滤器,接着就是routing过滤器,接着就是到了我们真实的服务器,真实服务器处理完成,响应返回到网关的时候 就到了post 类型的过滤器。

过滤器类型 解释
pre 在请求 被路由前调用,适用于身份认证的场景,ip黑白名单等等
route 在请求被调用时执行,这个可以通过自定义一些规则进行灰度发布
post 这个是真实服务器响应回来的时候或者error过滤器执行完的时候调用,添加响应头,记录响应日志等应用场景
error 这个是请求过程中异常的时候调用,可以用来统一记录错误信息

我这里定义一个pre的过滤器,来模拟一下黑白名单

@Component
public class BlackListFilter extends ZuulFilter {


    private static List<String> blackList;



    static {

        // 模拟黑名单
        blackList=new ArrayList<>();
        blackList.add("127.0.0.1");
    }


    // filter 类型
    @Override
    public String filterType() {
        return "pre";
    }
    // filter排序
    @Override
    public int filterOrder() {
        return 0;
    }
    // 是否启用filter
    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
    	// 获取context
        RequestContext currentContext = RequestContext.getCurrentContext();
		// 获取requst
        HttpServletRequest request = currentContext.getRequest();
        // 客户端地址
        String remoteHost = request.getRemoteHost();
        if (blackList.contains(remoteHost)){
            currentContext.set("isSuccess", false);
            currentContext.setSendZuulResponse(false);
            currentContext.setResponseBody("非法请求");
            currentContext.getResponse().setContentType("application/json; charset=utf-8");
        }

        return null;
    }
}

我们请求一下,可以看到被拦截下了:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/yuanshangshenghuo/article/details/107289572