本文所构建的代码已上传至Github(注意切换分支) ,所有代码均亲测有效,祝食用愉快。
一、Why Zuul
目前,我们使用Spring Cloud Netflix中的Eureka实现了服务注册中心以及服务注册与发现;而服务间通过Ribbon或Feign实现服务的消费以及均衡负载;使用Hystrix的融断机制来避免在微服务架构中个别服务出现异常时引起的故障蔓延。
在该架构中,我们的服务集群包含:consumer-demo、user-service,他们都会注册与订阅服务至eureka-server,而所有服务都是直接对外暴露到,直接暴露我们的服务地址,这样的实现显然是不能投入到生产环境使用到.
先来说说这样架构需要做的一些事儿以及存在的不足:
- 首先,破坏了服务无状态特点。
- 为了保证对外服务的安全性,我们需要实现对服务访问的权限控制,而开放服务的权限控制机制将会贯穿并污染整个开放服务的业务逻辑,这会带来的最直接问题是,破坏了服务集群中REST API无状态的特点。
- 从具体开发和测试的角度来说,在工作中除了要考虑实际的业务逻辑之外,还需要额外考虑对接口访问的控制处理。
- 其次,无法直接复用既有接口。
- 当我们需要对一个即有的集群内访问接口,实现外部服务访问时,我们不得不通过在原有接口上增加校验逻辑,或增加一个代理调用来实现权限控制,无法直接复用原有的接口。
为了解决类似上面的问题,引入服务网关势在必行.我们需要将权限控制这样的东西从我们的服务单元中抽离出去,而最适合这些逻辑的地方就是处于对外访问最前端的地方,我们需要一个更强大一些的均衡负载器的服务网关。 至于为什么使用Zuul,当然是因为它是SpringCloud体系中目前使用较为广泛到网关组件(偏见)
二、What Is Zuul
Zuul is a gateway service that provides dynamic routing, monitoring, resiliency, security, and more.
翻译:Zuul 是提供了动态路由、监控、弹性、安全等功能的网关服务。
微服务网关是整个微服务体系中极为重要的一环,作为整个系统的门神,Zuul起到的作用有:
- 用户鉴权:全局微服务的统一鉴权,减少冗余代码,提升系统健壮性与安全性
- 压力测试:能够逐渐向集群增加请求流量,以了解集群整体到性能;
- 静态响应处理:直接建立部分响应,从而避免请求真正转发到后端集群内部;
- 动态路由:动态地将请求路由(转发)到不同到后端集群;
- 负载分配:为每一种负载类型分配对应到容量,并直接放弃超出限定值到请求;
- ……
区别Eureka与Zuul:Zuul是consumer的统一入口,Eureka是provider的统一入口
三、How To Use Zuul
3.1 新建子模块(zuul-gateway-7000)
3.2 添加mvn依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
3.3 新增配置
server.port=7000
spring.application.name=zuul-gateway
# EurekaServer地址
eureka.client.service-url.defaultZone=http://127.0.0.1:7001/eureka,http://127.0.0.1:7002/eureka
# 指定自己的ip信息,不指定的话会自己寻找
eureka.instance.prefer-ip-address=true
eureka.instance.ip-address=127.0.0.1
# 路由映射配置方式一
#zuul.routes.service1.service-id=consumer-demo
#zuul.routes.service1.path=/cd/**
# 路由映射配置方式二(推荐)
zuul.routes.consumer-demo=/cd/**
# 设置对外屏蔽服务
zuul.ignored-services=consumer-demo,user-service
3.4 依次启动eureka-server、user-service、consumer-demo、zuul-gateway,可以看到请求执行成功:
// 20200102214115
// http://localhost:7000/cd/consumer/sysUser/selectById?id=1
{
"id": 1,
"username": "haha",
"password": "111111",
"name": "zhangsan",
"age": 21,
"gender": 1,
"remarks": "11223344"
}
而直接请求consumer-demo的请求执行失败:
四、过滤器(todo)
五、负载均衡与熔断
Zuul中默认就已经集成了Ribbon负载均衡和Hystix熔断机制。但是所有的超时策略都是走的默认值,比如熔断超时时间只有1S,很容易就触发了。因此建议我们手动进行配置:
zuul:
retryable: true
ribbon:
ConnectTimeout: 250 # 连接超时时间(ms)
ReadTimeout: 2000 # 通信超时时间(ms)
OkToRetryOnAllOperations: true # 是否对所有操作重试
MaxAutoRetriesNextServer: 2 # 同一服务不同实例的重试次数
MaxAutoRetries: 1 # 同一实例的重试次数
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMillisecond: 6000 # 熔断超时时长:6000ms