• Spring Cloud(六):服务网关zuul


    通过前面几篇文章的介绍,Spring Cloud微服务架构可通过Eureka实现服务注册与发现,通过Ribbon或Feign来实现服务间的负载均衡调用,通过Hystrix来为服务调用提供服务降级、熔断机制避免雪崩效应,通过Spring Cloud Config实现服务配置的集中化管理。微服务架构内部管理的基本组件差不多都已涵盖了,但是我们的服务最终是需要提供给客户端访问的,客户端如何来访问这些微服务,就需要引入一个叫服务网关的组件了。

    zuul

    zuul是netflix提供的一个基于JVM的路由与服务端负载均衡器。它在客户端与后端服务之间建立了一道关卡,客户端所有请求必须经过zuul转发到后端对应的微服务,返回结果再经由zuul返回给客户端。zuul与Eureka,Config组合的基本结构如图

    zuul

    zuul作为Eureka Client从Eureka Server获取其它微服务的配置信息,从而可以将客户端请求通过Service ID来负载均衡地转发到后端的服务实例,同时也作为Config Client从Config Server获取自身所需的配置信息。

    在netflix内部,zuul被用来实现安全认证、动态路由、反向代理、服务迁移、服务削峰、压力测试、金丝雀测试(灰度发布测试)等功能。本文介绍zuul的基本使用与路由规则。

    基本使用

    创建maven项目 springcloud-zuul

    1.pom.xml中引入依赖 spring-cloud-starter-netflix-zuul

    <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-config</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>
    

    2.application.yml配置文件中添加必要的配置,主要是eureka客户端配置

    spring:
      application:
        name: zuul-server
    
    server:
      port: 8765
    
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/
    

    3.启动类添加注解 @EnableZuulProxy

    @SpringBootApplication
    @EnableZuulProxy
    public class ZuulApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ZuulApplication.class, args);
        }
    }
    

    一如既往的简单,Spring Cloud之所以流行就是因为它基于Spring Boot将一些通用的功能进行了开箱即用的封装,使得开发者简单几步就能快速集成一个微服务框架。

    依次启动前文所创建的springcloud-eureka, springcloud-config, springcloud-eureka-client, springcloud-zuul,http://localhost:8765/hello-service/hello 返回 Hello, welcome to spring cloud. env: hello-service-dev, value: hello-service-dev 可见通过zuul的请求转发到了hello-service。

    为了验证zuul转发请求具备负载均衡的能力,可以将springcloud-eureka-client 中的hello接口返回值做一些调整,并改变端口重启一个实例,再次请求http://localhost:8765/hello-service/hello 将能看到返回结果在两者之间切换。

    以上配置文件中并没有加任何路由配置,zuul是怎么将请求正确转发到对应的微服务的呢? 请看下面的路由规则。

    路由规则

    1.默认路由规则

    zuul提供了默认的路由规则,不需要任何配置就会默认将注册的服务进行路径映射。我们可以通过actuator提供的接口来查看,在application.yml中添加配置

    management:
      endpoints:
        web:
          exposure:
            include: "*"
    

    放开actuator的其它接口访问(默认只放开了/info 与/health接口), 浏览器中访问 http://localhost:8765/actuator/routes, 可以看到返回的zuul默认的路由映射关系

    zuul-route

    zuul默认将 /service-id/** 的请求路由到Service ID(即spring.application.name的值)为 service-id的服务,如 /hello-service/hello,将转发到hello-service服务的/hello接口。

    2.自定义路由规则

    我们看到zuul的默认路由规则将config-server也映射出来了,对于这类内部服务我们不希望暴露,则可以通过 zuul.ignoredServices 来进行屏蔽,在application.yml配置文件中添加

    zuul:
      ignored-services: "config-server"
    

    重启,再次查看http://localhost:8765/actuator/routes , config-server已经被屏蔽了。

    通过zuul.routes可添加自定义路由,可以有 zuul.routes.{route-name}.path + zuul.routes.{route-name}.serviceId或urlzuul.routes.{service-id}: path 两个格式, 如下

    zuul:
      ignored-services: "config-server"
      routes:
        hello:
          path: /hi/**
          serviceId: hello-service
        hello-service: /hi2/**
        jboost:
          path: /jboost/**
          url: http://blog.jboost.cn
    

    访问 http://localhost:8765/hi/hellohttp://localhost:8765/hi2/hello 都将路由到 hello-service的hello接口,访问 http://localhost:8765/jboost/ 将访问到jboost博客首页。添加自定义路由后,默认路由仍然存在, 你仍然可以通过 http://localhost:8765/hello-service/hello 来访问 hello-service的hello接口。

    默认的路由规则将Service ID作为匹配路径,看起来有点长,我们想将匹配路径缩短一点,比如hello-service的匹配路径想改为 /hello/**, 而不是/hello-service/**, 如果像上面配置,一个微服务系统可能涉及几十甚至上百个服务,那配置起来将是一场噩梦。别急, zuul提供了 ServiceRouteMapper 接口来解决这一问题,其中 PatternServiceRouteMapper 可以基于正则表达式来进行路由抽取。

    创建一个配置类,注入一个 PatternServiceRouteMapper 的bean,如下

    @Configuration
    public class ZuulConfiguration {
    
        @Bean
        public PatternServiceRouteMapper serviceRouteMapper() {
            return new PatternServiceRouteMapper(
                    "(?<name>^.+)-(?<postfix>.+$)",
                    "${name}");
        }
    }
    

    该实现将会对所有服务的路由进行调整,service id 形如 name-postfix的匹配路径为 /name/**, 如hello-service 匹配 /hello/**。 如果正则表达式匹配失败,则还是以默认规则进行路由,如果匹配成功,则默认规则失效,但在配置文件中定义的路由仍然有效。上述验证中,你都可以通过 http://localhost:8765/actuator/routes 来查看当前生效的路由。

    其它配置

    zuul使用Ribbon来定位服务实例,所有请求都在hystrix command里执行,所以在zuul中可以添加Ribbon, Hystrix相关配置(具体参考前面Ribbon、Hystrix相关文章)

    • zuul.ignoredPatterns 对某些路径进行屏蔽,如 /**/admin/** 将会屏蔽所有路径中包含admin的接口访问
    • zuul.sensitiveHeaders 对一些header进行过滤,不传递给后端服务,默认包括Cookie,Set-Cookie,Authorization, 如果要让zuul发送所有header,则需要显式地将sensitiveHeaders置空值
    • zuul.prefix 为所有映射添加前缀,如/api, 这样route里配的 /myusers/** 就能匹配客户端请求的/api/myusers/**。默认zuul代理在转发时,前缀会被移除,通过设置zuul.stripPrefix=false可不移除

    总结

    本文简单介绍了zuul的基本使用与路由规则,更高阶的应用我们后面继续。
    认真生活,快乐分享
    欢迎关注微信公众号:空山新雨的技术空间
    获取Spring Boot,Spring Cloud,Docker等系列技术文章
    公众号二维码

  • 相关阅读:
    响应者链的事件传递过程
    事件的产生和传递
    UIView不接受触摸事件的三种情况
    利用UIActivityController调用ios系统自带的分享功能,实现微信发布多图的功能
    CALayer
    CATransition-转场动画
    iOS分类、延展和子类的区别
    ios如何普安短图片类型
    使用Google code + SVN进行多人开发
    搭建CppUnit错误总结
  • 原文地址:https://www.cnblogs.com/spec-dog/p/12326370.html
Copyright © 2020-2023  润新知