1:Zuul是什么
Zuul是Netflix开源的API网关。
API网关,相似于面向对象设计模式中的Facade模式,它的存在就像是整个微服务架构零碎的门面一样,所有的内部客户端拜访都须要通过它来进行调度和过滤,它除了要实现申请路由,负载平衡,起源合法性检测,权限校验,反爬虫等性能之外,还须要更多能力,比方与服务治理框架的联合,申请转发时的熔断机制,服务的聚合等一系列的高级性能。
官网:https://github.com/Netflix/zuul/
2:Zuul能干什么
- 身份验证和平安 - 辨认每个资源的身份验证要求,并回绝不满足的申请
- 审查和监测 - 跟踪边缘的有意义的数据和统计数据,以便咱们精确地理解生产运行状况
- 动静路由 - 依据须要将申请动静路由到不同的后端集群
- 压力测试 - 逐步减少到集群的流量,以掂量性能
- 负载调配 - 为每种类型的申请调配容量并删除超出限度的申请
- 动态响应解决 - 间接在边缘构建一些响应,而不是将它们转发到外部集群
3: 流程图
4:Zuul有什么
Zuul蕴含了对申请的路由和过滤两个最次要的性能:
其中路由性能负责将内部申请转发到具体的微服务实例上,是实现内部拜访对立入口的根底
而过滤器性能则负责对申请的处理过程进行干涉,是实现申请校验、服务聚合等性能的根底
然而实际上,路由性能在真正运行时,它的路由映射和申请转发都是由几个不同的过滤器实现的。其中,路由映射次要通过pre类型的过滤器实现,它将申请门路与配置的路由规定进行匹配,以找到须要转发的指标地址;而申请转发的局部则是由route类型的过滤器来实现,对pre类型过滤器取得的路由地址进行转发
5:HelloWorder
- 退出依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId></dependency>
- 配置示例,留神serviceId须要全小写
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/server.port=8780spring.application.name=service-zuulzuul.routes.api-a.path=/aa/**zuul.routes.api-a.serviceId=userservicezuul.routes.api-b.path=/bb/**zuul.routes.api-b.serviceId=service-feign
- 启动类退出注解
@EnableZuulProxy@EnableDiscoveryClient@SpringBootApplication
1:@EnableZuulProxy开启Zuul服务,将本地调用转发到相应的服务,Zuul应用Ribbon来定位一个要转发到的服务实例,并且所有申请都以 hystrix命令执行
2:留神@EnableZuulProxy不包含发现服务的客户端,因而对于基于服务ID的路由,还须要提供服务治理(例如Eureka)
3:应用@EnableZuulServer也能够运行不带代理的Zuul服务器,差异是它不会主动增加任何代理过滤器,也没有服务发现和代理
- 测试运行
1:如果配置文件外面没有配置zuul的话,zuul会把Eureka Server外面的服务都读取进去,此时运行的时候,须要用各个服务的serviceId做为ContextPath
2:如果配置了zuul,还能够用配置的前缀代替服务的serviceId,而后进行拜访
3:如果不心愿间接应用serviceId进行拜访,能够配置ignored-services: '’,例如:zuul.ignored-services='’,当然能够不必*,而是间接把要禁用的服务的serviceId列举进去,用逗号离开
6:传统路由配置
所谓的传统路由配置形式就是在不依赖于服务发现机制的状况下,通过在配置文件中具体制订每个路由表达式实例的映射关系来实现api网关对外部申请的路由。
- 单实例配置:
通过zuul.routes.<route>.path与zuul.routes.<route>.url参数对的形式进行配置,如:
zuul.routes.cc.path=/cc/**zuul.routes.cc.url=http://localhost:8769
- 多实例配置
通过zuul.routes.<route>.path与zuul.routes.<route>.serviceId参数的形式进行配置,联合Ribbon来做负载平衡,且让Ribbon敞开和Eureka的联合,比方:
zuul.routes.cc.path=/cc/**#zuul.routes.cc.url=http://localhost:8769zuul.routes.cc.serviceId=ccserviceribbon.eureka.enabled=falseccservice.ribbon.listOfServers=http://localhost:8769/,http://localhost:8768/
这种简略的URL路由不会被执行为HystrixCommand,也不能应用Ribbon对多个URL进行负载平衡
7:服务路由配置
spring cloud zuul整合了spring cloud eureka,实现了对服务实例的自动化保护,那么应用服务路由配置的时候,不须要像传统路由配置形式那样为serviceId指定具体服务实例地址,只须要通过zuul.routes.<route>.path与zuul.routes.<route>.serviceId参数对的形式进行配置即可。
还能够简化配置,间接设置<route>为具体的serviceId,例如:
zuul.routes.service-feign.path=/dd/**
请记得开启后面示例中敞开的Ribbon和Eureka的联合。
8:服务路由的默认规定
大部分的路由规定机会都会采纳服务名作为内部申请的前缀,zuul曾经主动的帮咱们实现以服务名作为前缀的映射,不须要去配置它。
如果不心愿内部能间接拜访,能够应用zuul.ignored-services参数来设置一个服务名匹配表达式来定义不主动创立路由的规定。
9:自定义路由映射关系
有时候,为了兼容内部不同版本的客户端程序,咱们须要在微服务接口上定义版本的标记,比方:service-v1、 service-v2,而这样在映射的时候不太好治理。
通常的做法是为这些不同版本的微服务利用,生成以版本号作为路由前缀定义规定的路由规定,比方/v1/userservice/,具体示例如下:
@Beanpublic PatternServiceRouteMapper serviceRouteMapper(){ return new PatternServiceRouteMapper("(?<name>^.+)-(?<version>v.+$)","${version}/${name}");}
门路匹配
在zuul中,路由匹配的门路表达式采纳ant格调定义:
1:? 匹配任意单个字符
2:* 匹配任意数量的字符
3:** 匹配任意数量的字符,反对多级目录
留神:当存在多个匹配的路由规定时,匹配后果齐全取决于路由规定的定义程序
因为properties的配置内容无奈保障有序,所以当呈现这样的状况的时候,为了保障路由的优先程序,须要应用yml文件来配置,以实现有序的路由规定
10:cookie与头信息
默认状况下,spring cloud zuul在申请路由时,会过滤掉http申请头信息中一些敏感信息,避免它们被传递到上游的内部服务器。
默认的敏感头信息通过zuul.sensitiveHeaders参数定义,默认包含cookie,set-Cookie,authorization三个属性。
这会引发一个常见的问题,应用了spring security,shiro等平安框架构建的web利用,通过spring cloud zuul构建的网关来进行路由时,因为cookie信息无奈传递,web利用将无奈实现登录和鉴权。为了解决这个问题,配置的办法能够为:
1:通过设置全局参数为空来笼罩默认值,如:
zuul.sensitiveHeaders=
不举荐这种做法,范畴太大
2:将指定路由的敏感头设置为空,如:
zuul.routes.userservice.sensitiveHeaders=
11:重定向问题
应用API网关的一个重要起因就是将网关作为对立入口,从而不裸露所有外部服务细节。但咱们在利用外部跳转的url却是具体web利用实例的地址,而不是通过网关的路由地址,该问题的根本原因在于spring cloud zuul在路由申请时,并没有将最后的host信息设置正确,怎么办呢?
配置zuul.add-host-header=true即可
12:路由回退
12.1:Hystrix和ribbon反对
- Spring Cloud Zuul默认集成了Hystrix和Ribbon,天然就领有线程隔离和断路器,以及对服务调用的客户端负载平衡性能。 须要留神的是,当应用path与url的映射关系来配置路由规定的时候,对于路由转发的申请不会采纳hystrixCommand来包装,所以这类申请没有线程隔离和断路器的爱护,并且也不会有负载平衡的能力。因而,咱们在应用zuul的时候尽量应用path和serviceId的组合来进行配置,这样不仅能够保障api网关的强壮和稳固,也能用到ribbon的客户端负载平衡性能。
- 所有路由的默认Hystrix隔离模式(ExecutionIsolationStrategy)为SEMAPHORE
12.2:Hystrix的路由回退
- 能够通过创立ZuulFallbackProvider类型的bean来提供回退响应
- zuul首先会去判断是否存在自定义的zuulFallbackProvider,如果有,那么间接回调你自定义实现类的fallbackResponse()办法。如果不存在会走hystrix的fallback逻辑(有可能间接抛出异样)
- 尽管Zuul提供了降级的回调办法fallbackResponse(),然而这个办法是无参的,也就是说此时尽管你可能给调用端返回一个音讯,然而此时你并不知道产生了什么样的异样(也就是说在这里你是获取不到异样信息的)。
13:申请路由其它配置
- 路由前缀
zuul.prefix:为路由规定减少前缀,例如: zuul.prefix=/user。
zuul.strip-prefix(默认为true):这个设置是在转发申请之前,从申请中删除代理前缀
- 本地跳转
通过在serviceId中应用forward来指定须要跳转的服务器资源门路,例如:
zuul.routes.api-t.path=/tt/**
zuul.routes.api-t.serviceId=forward:/tt
- 疏忽表达式
zuul.ignored-patterns:设置不心愿被api网关进行路由的url表达式。例如:
ignoredPatterns: //products/
留神:它的范畴并不是针对某个路由,而是对所有路由,所以要小心应用。
- 路由端点
应用@EnableZuulProxy,将启用/routes端点,可返回映射路由的列表。
能够通过将endpoints.routes.enabled设置为false来禁用此端点
- 配置属性
zuul.max.host.connections已被两个新属性zuul.host.maxTotalConnections和zuul.host.maxPerRouteConnections替换,别离默认为200和20
- 性能优化
Zuul外部路由能够了解为应用一个线程池去发送路由申请,所以咱们也须要扩充这个线程池的容量,如:
zuul.host.max-per-route-connections=1000
zuul.host.max-total-connections=1000