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

zuul

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

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默认将 /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等系列技术文章

Spring Cloud(六):服务网关zuul的更多相关文章

  1. Spring Cloud Gateway 服务网关快速上手

    Spring Cloud Gateway 服务网关 API 主流网关有NGINX.ZUUL.Spring Cloud Gateway.Linkerd等:Spring Cloud Gateway构建于 ...

  2. Spring Cloud (13) 服务网关-路由配置

    传统路由配置 所谓传统路由配置方式就是在不依赖于服务发现机制情况下,通过在配置文件中具体制定每个路由表达式与服务实例的映射关系来实现API网关对外部请求的路由.没有Eureka服务治理框架帮助的时候, ...

  3. Spring Cloud (12) 服务网关-基础

    通过前几篇介绍,已经可以构建一个简单的微服务架构了,如下图: 通过eureka实现服务注册中心以及服务注册发现,通过ribbon或feign实现服务的消费以及负载均衡,通过spring cloud c ...

  4. Spring Cloud Gateway服务网关

    原文:https://www.cnblogs.com/ityouknow/p/10141740.html Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gatewa ...

  5. Spring Cloud (14) 服务网关-过滤器

    Spring Cloud Zuul作为网关所具备的最基本的功能:路由,还具备另外一个核心的功能:过滤器. 过滤器 通过Spring Cloud Zuul实现的路由功能,我们的微服务可以通过统一的API ...

  6. Spring Cloud 之 服务网关

    在微服务架构体系中,使用API 服务网关后的系统架构图如下: API服务网关的主要作用如下: 服务访问的统一入口 服务访问的负载均衡功能 服务访问的路由功能 在SpringCloud中,基于Netfl ...

  7. spring cloud:服务网关 Spring Cloud GateWay 入门

    Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gateway ,相比之前我们使用的 Zuul(1.x) 它有哪些优势呢?Zuul(1.x) 基于 Servlet,使 ...

  8. Spring Cloud 微服务:Eureka+Zuul+Ribbon+Hystrix+SpringConfig实现流程图

    相信现在已经有很多小伙伴已经或者准备使用springcloud微服务了,接下来为大家搭建一个微服务框架,后期可以自己进行扩展.会提供一个小案例: 服务提供者和服务消费者 ,消费者会调用提供者的服务,新 ...

  9. Spring Cloud微服务笔记(二)Spring Cloud 简介

    Spring Cloud 简介 Spring Cloud的设计理念是Integrate Everything,即充分利用现有的开源组件, 在它们之上设计一套统一的规范/接口使它们能够接入Spring ...

  10. Spring Cloud实战之初级入门(六)— 服务网关zuul

    目录 1.环境介绍 2.api网关服务 2.1 创建工程 2.3 api网关中使用token机制 2.4 测试 2.5 小结 3.一点点重要的事情 1.环境介绍 好了,不知不觉中我们已经来到了最后一篇 ...

随机推荐

  1. 良心推荐,我珍藏的一些Chrome插件

    上次搬家的时候,发了一个朋友圈,附带的照片中不小心暴露了自己的 Chrome 浏览器插件之多,于是就有小伙伴评论说分享一下我觉得还不错的浏览器插件. 我下面就把我日常工作和学习中经常用到的一些 Chr ...

  2. git submodule 管理子项目

    使用场景 拆分项目,当项目越来越大之后,我们希望 子模块 可以单独管理,并由 专门 的人去维护,这个时候只可以使用 git submodule 去完成. 常用命令 git clone <repo ...

  3. es6种for循环中let和var区别

    let和var区别: for(var i=0;i<5;i++){ setTimeout(()=>{ console.log(i);//5个5 },100) } console.log(i) ...

  4. Serv_U FTP服务端使用教程

    Serv-U FTP Server是一种被广泛运用的FTP服务器端软件,可以设定多个FTP服务器.限定登录用户的权限.登录主目录及空间大小等,功能非常完备.具有非常完备的安全特性,支持SSl FTP传 ...

  5. 求树上任意一点所能到达的最远距离 - 树上dp

    A school bought the first computer some time ago(so this computer's id is 1). During the recent year ...

  6. Callable接口用法

    注意点:FutureTask是Runnable的实现类,它的构造器可以传Callable接口的实现类. 例子如下: class MyThread implements Callable<Inte ...

  7. 测试工具Fiddler(三)—— 常见功能介绍

    Fiddler的功能面板 1.statistics:请求的性能指标:全世界范围的性能测试: RTP:一个请求的从发送出去到返回的时间: Show chart可以看出图表的示例: 2.inspector ...

  8. java intellij 工具的简单用法

    一.目录结构 1.新建项目(Empty Project) ->  新建module(可以有多个) => 出来src文件夹 -> 在src文件夹中新建package -> 在pa ...

  9. 保存数据到csv

    csv 逗号分隔值 一.写入 1.列表 单行添加 import csv # with open(file='a.csv', mode='w', encoding='utf-8', newline='' ...

  10. C语言进阶——编译预处理指令

    编译预处理指令 • #开头的是编译预处理指令 • 它们不是C语⾔的成分,但是C语⾔程序离不开它们 • #define⽤来定义⼀个宏 #define • #define <名字> <值 ...