文章目录
Zuul
微服务网关
未使用网关
如果让客户端直接与各个微服务通信,会有以下问题:
- 客户端会多次请求不同的微服务,增加了客户端的复杂性。
- 存在跨域请求,在一定场景下处理相对复杂。
- 认证复杂,每个服务都需要独立认证。
- 难以重构,随着项目的迭代,可能需要重新划分微服务。例如,多个微服务的整合,或一个微服务的拆分。如果客户端直接与微服务通信,那么重构将很难实施。
- 某些微服务可能使用了对防火墙/浏览器不友好的协议,直接访问时会有一定的困难。
使用网关
微服务网关封装了应用程序的内部结构,客户端只用跟网关交互,而无须直接调用特定微服务的接口。
使用微服务网关还有以下优点:
- 易于监控。可在微服务网关收集监控数据并将其推送到外部系统进行分析。
- 易于认证。可在微服务网关上进行认证,然后再将请求转发到后端的微服务,而无须在每个微服务中进行认证。
- 减少了客户端与各个微服务之间的交互次数。
Zuul简介
Zuul是Netflix开源的微服务网关,其核心是一系列的过滤器,这些过滤器可完成以下功能:
- 身份认证与安全:识别每个资源的验证要求,并拒绝那些与要求不符的请求。
- 审查与监控:在边缘位置追踪有意义的数据和统计结果,从而带来精确的生产视图。
- 动态路由:动态地将请求路由到不同地后端集群。
- 压力测试:逐渐增加指向集群的流量,以了解性能。
- 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求。
- 静态响应处理:在边缘位置直接建立部分响应,从而避免其转发到内部集群。
- 多区域弹性:跨越AWS Region进行请求路由,旨在实现ELB(Elastic Load Balancing,弹性负载均衡)使用的多样化,以及让系统的边缘更贴近系统的使用者。
Zuul使用的默认HTTP客户端是Apache HTTP Client;使用RestClient:ribbon.restclient.ebanled=true;使用okhttp3.OkHttpClient:ribbon.okhttp.enabled=true
使用
- 创建Maven项目
- 引入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- 在启动类上添加注解
@EnableZuulProxy
,声明一个Zuul代理。该代理使用Ribbon来定位注册在Eureka Server中的微服务;同时,该代理还整合了Hystrix实现容错,所有经过Zuul的请求都会在Hystrix命令中执行。
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
- 编写配置文件:
server:
port: 8040
spring:
application:
name: zuul
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
路由规则
默认情况下,Zuul会代理所有注册到Eureka Server的微服务,并且Zuul的路由规则如下:
http://Zuul_host:Zuul_port/微服务的虚拟主机名/**
注意虚拟主机名大小写区分
例如:http://localhost:8040/eureka-client-hystrix-consumer/findById/1 会转发到 http://localhost:8080/findById/1 上
管理端点
当 @EnableZuulProxy
与 Spring Boot Actuator配合使用时,Zuul会暴露两个端点:/actuator/routes和/actuator/filters。Zuul包含Actuator组件。
需要更改配置文件:
management:
endpoints:
web:
exposure:
# 暴露所有端点
include: "*"
routes端点(/actuator/routes)
- 使用GET方法访问该端点,即可返回Zuul当前映射的路由列表。
- 使用POST方法访问该端点就会强制刷新Zuul当前映射的路由列表。尽管路由会自动刷新,Spring Cloud依然提供了强制立即刷新的方式。
- 可以使用
/actuator/routes/details
查看更多与路由相关的详情设置
filters端点(/actuator/filters)
访问该端点,即可返回Zuul中当前所有过滤器的详情。
路由配置详解
想查看Zuul转发的具体细节,可将 com.netflix
包的日志级别设为 DEBUG
:
logging:
level:
com.netflix: debug
自定义指定微服务的访问路径
配置 zuul.routes.指定微服务的serverId = 指定路径
即可:
zuul:
routes:
# 微服务的虚拟主机名
eureka-client-hystrix-consumer: /user/**
完成设置后,eureka-client-hystrix-consumer微服务就会被映射到/user/**路径。
http://localhost:8040/user/user/1 与 http://localhost:8040/eureka-client-hystrix-consumer/user/1 等价
忽略微服务
- 忽略多个微服务需要使用“,”逗号隔开:
zuul:
ignored-services: 微服务的虚拟主机名1,微服务的虚拟主机名2
- 忽略全部微服务:
zuul:
# 忽略全部微服务
ignored-services: "*"
同时指定微服务的serviceId和对应路径
zuul:
routes:
# 该配置方式中,user-route只是给路由一个名称,可以任意起名
user-route:
service-id: eureka-client-hystrix-consumer
#service-id对应的路径
path: /user/**
该方式与自定义指定微服务的访问路径效果相同
同时指定url和对应路径
zuul:
routes:
# 该配置方式中,user-route只是给路由一个名称,可以任意起名
user-route:
# 指定的url
url: http://localhost:8080
# url对应的路径
path: /user/**
这样就可以将 /user/** 映射到 http://localhost:8080 。
注意:此方式配置的路由不会作为HystrixCommand执行,同时也不能使用Ribbon来负载均衡多个url。解决方案:
zuul:
routes:
# 该配置方式中,user-route只是给路由一个名称,可以任意起名
user-route:
service-id: eureka-client-hystrix-consumer
path: /user/**
ribbon:
eureka:
# 为Ribbon禁用Eureka
enabled: false
eureka-client-hystrix-consumer:
ribbon:
# 多个地址用“,”逗号隔开
listOfServers: localhost:8080
这样就可以既指定path与url,又不破坏Zuul的Hystrix与Ribbon特性了。
使用正则表达式指定Zuul的路由匹配规则
借助PatternServiceRouteMapper ,实现从微服务到映射路由的正则匹配:
@Bean
public PatternServiceRouteMapper patternServiceRouteMapper() {
//调用构造函数public PatternServiceRouteMapper(String servicePattern, String routePattern)
//servicePattern 指定微服务的正则
//routePattern 指定路由的正则
return new PatternServiceRouteMapper("(?<name>^.+)-(?<version>v.+$)"
,"${version}/${name}");
}
通过这段代码即可实现将诸如microservice-provider-user-v1这个微服务,映射到/v1/microservice-provider-user/**这个路径。
路由前缀
- 请求路径:/user/consumer/1 被转发成:eureka-client-hystrix-consumer的/user/1
zuul:
prefix: /user
strip-prefix: false
routes:
eureka-client-hystrix-consumer: /consumer/**
- 请求路径: http://localhost:8040/user/1 被转发到 eureka-client-hystrix-consumer的/user/1
zuul:
routes:
eureka-client-hystrix-consumer:
path: /user/**
strip-prefix: false
忽略某些路径
使用 ignored-patterns
指定忽略路径的正则:
zuul:
routes:
eureka-client-hystrix-consumer: /user/**
# 忽略所有包含/findById/的路径
ignored-patterns: /**/findById/**
本地转发
zuul:
routes:
route-name:
path: /path-a/**
url: forward: /path-b
当访问Zuul的 /path-a/**
路径将转发到Zuul的 /path-b/**
路径