SpringCloud系列之Zuul路由网关【待完善】

1.简介

Zuul包含了对请求的路由和过滤两个最主要的功能:

其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础,类似于保安的职能,而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验,服务聚合等功能的基础,Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获取其他的微服务消息,也即以后访问微服务是通过Zuul跳转后获得,最终Zuul服务还是会注册进Eureka。提供 服务代理 ,路由,过滤三大功能。
  在这里插入图片描述
从以上这张架构图中,我们可以看到所有的请求都必须通过API GateWay服务才能到达后面的服务,这就是Zuul所需要承担起来的责任。可见他的存在是很重要的。

为什么需要zuul或者说zuul承担的功能是什么?
zuul作为路由网关组件,在微服务架构中有着非常重要的作用,主要体现在如下六个方面:
1)zuul,ribbon以及eureka相结合,可以实现智能路由及负载均衡的作用,zuul可以将请求流量按某种策略分发到集群状态的多个服务实例。
2)网关将所有服务的API接口统一聚合,并且统一对外暴露。外界系统调用API接口时候,都是由网关对外暴露的API接口,外界系统不需要知道微服务系统中各个服务湘湖调用的复杂性。微服务系统也保护了其内部微服务单元的API接口,防止被外界直接调用,导致服务的敏感信息对外暴露。
3)网关服务可以做用户身份认证和权限认证,房子非法请求操作API接口,对服务器气到保护作用
4)网关可以实现监控功能,实时日志输出,对请求进行记录
5)网关可以用来实现流量监控,在高流量情况下,对服务进行降级
6)API接口从内部服务分离出来,方便做测试

2. 实例

2.1 快速入门

新建一个名为eureka-zuul-client的项目
引入pom

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
    </dependencies>

在程序的启动类中打上@EnableZuulProxy注解

@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class EurekaZuulClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaZuulClientApplication.class, args);
    }
}

新增application.yml配置文件

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

server:
  port: 8766

spring:
  application:
    name: eureka-zuul-client

zuul:
  routes:
    hiapi:
      path: /hiapi/**
      serviceId: eureka-client
    ribbonapi:
      path: /ribbonapi/**
      serviceId: eureka-ribbon-client
    feignapi:
      path: /feignapi/**
      serviceId: eureka-feign-client

这边注意看下配置
依次启动 server client ribbon fegin 及zuul

localhost:8766/hiapi/hello?name=llf
localhost:8766/ribbonapi/hi?name=llf
localhost:8766/feignapi/hi?name=llf

即可调用成功。

此时如果想使用指定服务的url可以修改配置文件application.yml指定zuul调用的服务

zuul:
  routes:
    hiapi:
      path: /hiapi/**
      url: http://localhost:8762

这样再请求的话就只会请求到8762的服务了

如果又想指定url又想搞负载均衡的话,那么就需要自己维护负载均衡的服务注册列表。
首先把ribbon.eureka.enabled改为false。即ribbon负载均衡客户端不想eurekaclient获取服务注册列表。然后我们自己维护一份注册列表,改注册列表对应服务名为hiapi-vi(可自定义),通过配置hiapi-v1.ribbon.listOfServers来配置多个负载均衡的URL。

zuul:
  routes:
    hiapi:
      path: /hiapi/**
      serviceId: hiapi-v1
ribbon:
  eureka:
    enabled: false
hiapi-v1:
  ribbon:
    listOfServers: http://localhost:8762,http://localhost:8763

2.2 在Zuul上配置API接口版本号

如果想给每个接口加前缀 比如:

http://localhost:8766/v1/hiapi/hello?name=llf

即在所有的接口前加一个v1的版本号,所以此时需要用到zuul.prefix配置
示例如下:

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

server:
  port: 8766

spring:
  application:
    name: eureka-zuul-client

zuul:
  routes:
    hiapi:
      path: /hiapi/**
      serviceId: eureka-client
    ribbonapi:
      path: /ribbonapi/**
      serviceId: eureka-ribbon-client
    feignapi:
      path: /feignapi/**
      serviceId: eureka-feign-client
  prefix: /v1

重启zuul即可实现。

2.3 在Zuul上配置熔断器

实现一个针对eureka-client的熔断器,当eureka-client服务出现故障时候,进入熔断器逻辑,向浏览器输入一句错误提示
最主要是继承实现FallbackProvider 接口

@Component
public class MyFallbackProvider implements FallbackProvider {


    @Override
    public String getRoute() {
        return "eureka-client";
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                return headers;
            }

            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream("error,im the fallback".getBytes());
            }

            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK;
            }

            @Override
            public int getRawStatusCode() throws IOException {
                return 200;
            }

            @Override
            public String getStatusText() throws IOException {
                return "OK";
            }

            @Override
            public void close() {
            }
        };
    }
}

然后关闭eureka-client实例,再次调用即进入fallback逻辑,如果需要所有的路由服务都加熔断功能,只需要在getRoute方法返回通配符*即可
如下:

@Override
    public String getRoute() {
        return "*";
    }

2.4 在Zuul上使用过滤器

采取自定义过滤器,只需要继承ZuulFilter,并且实现ZuulFilter中的抽象方法,包括filterType和filterOrder以及shouldFilter和Object的run方法。
其中filterType即过滤器的类型,分别有四种类型 pre post routing和error,
filterOrder是过滤顺序,它作为int类型的值,值越小,越早执行这个过滤器。
shoulderFilter表示该过滤器是否过滤逻辑,如果是true,则执行run方法,如果false,则不执行run方法。run方法写具体的过滤逻辑,我们这边实例是检查请求参数中是否传了token这个参数,如果没有传,则请求不被路由到具体的服务实例,直接返回响应状态码。

@Component
public class MyFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        Object accessToken = request.getParameter("token");
        if (accessToken == null) {
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            try {
                ctx.getResponse().getWriter().write("token is empty");
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        return null;
    }
}

启动服务

http://localhost:8766/v1/hiapi/hello?name=llf

浏览器显示token is empty
再次输入

http://localhost:8766/v1/hiapi/hello?name=llf&token=xsddd

就可以正确调用到eureka-client了

3. 源码解析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值