八、微服务网关之Zuul


为什么要用微服务网关

如下图,外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与微服务通信会产生以下的问题:

  • 客户端会多次请求不同的微服务,增加了客户端的复杂性。
  • 存在跨域请求,在一定场景下处理比较复杂。
  • 认证复杂,每个服务都需要单独认证。
  • 难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通信,那么重构将很难实施。
  • 某些微服务可能使用了防火墙/浏览器不友好的协议,直接访问会有一定的困难。

用户请求多个微服务

以上问题可借助微服务网关解决。微服务网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过微服务网关。
如图,微服务网关封装了应用程序的内部结构,客户端只须跟网关交互,而无须直接调用特定微服务的接口,这样,开发就可以得到简化。不仅如此,使用微服务网关还有以下优点:

  • 易于监控。可在微服务网关收集监控数据并将其推送到外部系统进行分析;
  • 易于认证。可在微服务网关上进行认证,然后再将请求转发到后端的微服务,而无须再每个微服务中进行认证;
  • 减少了客户端与各个微服务之间的交互次数

使用微服务网关


Zuul简介

ZuulNetflix开源的微服务网关,它可以和EurekaRibbonHystrix等组件配合使用。

Zuul的核心是一系列的过滤器,这些过滤器可以完成以下功能:

  • 身份认证与安全:识别每个资源的验证要求,并拒绝那些与要求不符的请求;
  • 审查与监控:在边缘位置追踪有意义的数据和统计结果,从而带来精确的生产视图;
  • 动态路由:动态地将请求路由到不同的后端集群;
  • 压力测试:逐渐增加指向集群的流量,以了解性能;
  • 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求;
  • 静态响应处理:在边缘位置直接建立部分响应,从而避免其转发到内部集群;
  • 多区域弹性:跨域AWS Region进行请求路由。

编写Zuul微服务网关

  1. 创建 Maven 工程,pom文件添加已下依赖:
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
  1. 在配置文件application.yml中添加:
server:
  port: 8040
spring:
  application:
    name: microsrvice-gateway-zuul
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
#关闭才可查看端点
management:
  security:
    enabled: false
  1. 在启动类上添加@EnableZuulProxy注解,声明一个Zuul代理,该代理使用Ribbon来定位注册在Eureka Server中的微服务;同时,该代理还整合了hystrix,所有经过Zuul的请求都会在Hystrix命令中执行。

  2. 启动用户微服务,电影微服务,

    访问http://localhost:8040/micorservice-consumer-movie/user/1,请求会被转发到http://localhost:8010/user/1

    访问http://localhost:8040/microservice-provider-user/1,请求会被转发到http://localhost:8000/1

  • 说明默认情况下,Zuul会代理所有注册到Eureka Server的微服务,并且Zuul的路由规则如下:http://ZUUL_HOST:ZUUL_PORT/微服务在Eureka上的serviceId/**会被转发到serviceId对应的微服务。
  1. Zuul可以使用Ribbon达到负载均衡的效果。
  2. Zuul已经整合Hystrix,访问http://localhost:8040/hystrix.stream可以查看监控。
  • GET方式访问routes端点:http://127.0.0.1:8040/routes:
{
  "/microservice-consumer-movie/**": "microservice-consumer-movie",
  "/microservice-provider-user/**": "microservice-provider-user"
}
  • POST方式访问该端点,强制刷新Zuul当前映射的路由列表。
  • 访问filters端点:http://127.0.0.1:8040/filters:
{
  "error": [
    {
      "class": "org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter",
      "order": 0,
      "disabled": false,
      "static": true
    }
  ],
  "post": [
    {
      "class": "org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter",
      "order": 1000,
      "disabled": false,
      "static": true
    }
  ],
  "pre": [
    {
      "class": "org.springframework.cloud.netflix.zuul.filters.pre.DebugFilter",
      "order": 1,
      "disabled": false,
      "static": true
    },
    {
      "class": "org.springframework.cloud.netflix.zuul.filters.pre.FormBodyWrapperFilter",
      "order": -1,
      "disabled": false,
      "static": true
    },
    {
      "class": "org.springframework.cloud.netflix.zuul.filters.pre.Servlet30WrapperFilter",
      "order": -2,
      "disabled": false,
      "static": true
    },
    {
      "class": "org.springframework.cloud.netflix.zuul.filters.pre.ServletDetectionFilter",
      "order": -3,
      "disabled": false,
      "static": true
    },
    {
      "class": "org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter",
      "order": 5,
      "disabled": false,
      "static": true
    }
  ],
  "route": [
    {
      "class": "org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter",
      "order": 100,
      "disabled": false,
      "static": true
    },
    {
      "class": "org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter",
      "order": 10,
      "disabled": false,
      "static": true
    },
    {
      "class": "org.springframework.cloud.netflix.zuul.filters.route.SendForwardFilter",
      "order": 500,
      "disabled": false,
      "static": true
    }
  ]
}

Zuul路由配置详解

  1. 自定义指定微服务的访问路径:
zuul:
  routes:
    microservice-provider-user: /user/**

microservice-provider-user微服务就会被映射到路径/user/**

  1. 忽略指定微服务:
zuul:
  ignored-services: microservice-provider-user,microservice-consumer-movie
  1. 忽略所有微服务,只路由指定微服务:
ignored-services: "*"
routes:
  microservice-provider-user: /user/**
  1. 同时指定微服务的serviceId和路径:
zuul:
  routes:
    #    user-route只是名称,可以任意起
    user-route:
      service-id: microservice-provider-user
      path: /user/**
  1. 同时指定pathURL:
zuul:
  routes:
    #    user-route只是名称,可以任意起
    user-route:
      url: http://localhost:8000/
      path: /user/**

但是这样有些问题,这种方式配置的路由不会作为HystrixCommand执行,也不能使用Ribbon来负载均衡多个URL

  1. 同时指定pathURL,并且不破坏ZuulHystrix,Ribbon特性:
zuul:
  routes:
    user-route:
      service-id: microservice-provider-user
      path: /user/**
ribbon:
  eureka:
    enabled: false
microservice-provider-user:
  ribbon:
    listOfServers: localhost:8000,localhost:8001
  1. 路由前缀:
  • 访问Zuul/api/microservice-provider-user/1,请求转发到micorservice-provider-user/api/1:
zuul:
  prefix: /api
  stripPrefix: false
  routes:
    microservice-provider-user: /user/**
  • 访问Zuul/user/1,请求转发到micorservice-provider-user/user/1:
zuul:
  routes:
    microservice-provider-user:
      path: /user/**
      stripPrefix: false
  1. 忽略某些路径:
zuul:
  routes:
    microservice-provider-user: /user/**
  ignored-patterns: /**/admin/** #忽略所有包含admin路径的

该文章摘自《Spring Cloud 与 Docker 微服务架构实战(第二版)》

以上


文章作者: Qliang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Qliang !
评论
 上一篇
九、微服务网关之Zuul过滤器 九、微服务网关之Zuul过滤器
过滤器类型与请求生命周期 PRE:这种过滤器在请求被路由之前调用。可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。 ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apach
2019-01-26
下一篇 
七、微服务容错处理之Hystrix的监控 七、微服务容错处理之Hystrix的监控
Hystrix的监控 为客户端添加spring-boot-starter-actuator依赖; 访问http://127.0.0.1:8010/hystrix.stream,就会不断刷新如下监控数据: ping: data: {"t
2019-01-23
  目录