一.前言
1.介绍
- 在微服务中如果没有网关,一个客户端完成一个业务动作,可能需要调用多个微服务接口,而且每个微服务都需要安全认证,加大了客户端的复杂性。
- zuul是一个客户端和服务端之间的中间层,客户端所有的请求流量都经过zuul做分发,zuul代理了后端的微服务,对于客户端来说屏蔽了后端微服务调用的复杂性;当后端微服务进行业务调整,只需要在zuul中调整路由规则就可以了,客户端和服务端得到了良好解耦合
- Zuul也是一款由Netflix开发的微服务网关开源软件,和Netflix开发的Eureka,Ribbon和Hystrix配合使用
- Zuul主要功能为路由器和过滤器,这篇主要介绍路由功能
2.项目准备
- 项目地址完整例子传送门
-
此篇文章用到项目模块:
- 模块介绍:
1.eureka-server-standalone
: 提供注册中心的服务
2.zuul-gateway
:提供zuul网关功能,注册到eureka
服务中心
3.zuul-consumer
:提供接口调用,具有hystrix
熔断功能,和ribbon
负载均衡功能,注册到eureka
服务中心
二.创建zuul服务
- Spring Cloud集成Zuul代理,可以默认代理注册中心的服务。从而避免了后端每个微服务都需要独立管理CORS和身份验证问题。
1.官网资料
- Zuul使用
- Netflix / Zuul
2.创建 zuul-gateway
项目
- 在启动类中
ZuulGatewayApplication.java
中
@EnableZuulProxy
@SpringCloudApplication
public class ZuulGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulGatewayApplication.class, args);
}
}
加入
@EnableZuulProxy
表示此项目启动zuul代理功能
加入@SpringCloudApplication
表示此项目启动断路由,eureka
注册功能
- 在pom.xml中
org.springframework.cloud
spring-cloud-starter-netflix-zuul
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
引入
zuul
和eureka-client
依赖,其中zuul
包含了hystrix
,actuator
,ribbon
等功能,见下图
- 配置文件
application.yml
中
spring:
application:
name: Zuul-Gateway
server:
port: 9001
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
management:
endpoints:
web:
exposure:
include: '*'
management.endpoints.web.exposure.include
:打开actuator
的监控端口,,默认只打开了health
,info
的监控监控点*
代表全部打开,此举是用于查看/routes
接口,返回此zuul
代理了多少服务,以及路由规则;如下:
-
启动验证
1.依次启动eureka-server-standalone
端口为8760,zuul-gateway
端口为9001
2.zuu
项目有对外暴露的actuator
端点/routes
:获取zuul项目的代理服务列表
/routes/details
:zuul项目的代理服务详情3.访问
http://localhost:9001/actuator/routes
,可见如下,只代理了自己的服务{ "/zuul-gateway/**": "zuul-gateway"}
4.也可以查看详情
localhost:9001/actuator/routes/details
{ "/zuul-gateway/**": { "id": "zuul-gateway", "fullPath": "/zuul-gateway/**", "location": "zuul-gateway", "path": "/**", "prefix": "/zuul-gateway", "retryable": false, "customSensitiveHeaders": false, "prefixStripped": true } }
3.创建 zuul-consumer
项目
提供接口调用,注册到
eureka
服务中心,具有hystrix
熔断功能,和ribbon
负载均衡功能在启动类中
ZuulConsumerApplication.java
中
@SpringCloudApplication
@RestController
public class ZuulConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulConsumerApplication.class, args);
}
@Qualifier("eurekaRegistration")
@Autowired
private Registration registration;
@GetMapping("getInstanceServiceIdAndPort")
public String getInstanceServiceIdAndPort(){
String serviceId = registration.getServiceId();
int port = registration.getPort();
return serviceId+":"+port;
}
@GetMapping("getInstanceServiceIdAndPortWithThrowError")
@HystrixCommand(fallbackMethod = "rollBack")
public String getInstanceServiceIdAndPortWithThrowError(){
int port = registration.getPort();
throw new RuntimeException("go away!!"+"and port is : "+port);
}
public String rollBack(Throwable e){
return "throw error is : "+e.getMessage();
}
}
实现
getInstanceServiceIdAndPort
:用于提供获取本机实例和端口的接口服务
实现getInstanceServiceIdAndPortWithThrowError
:模拟熔断回退
注入Registration
:获取本地的一些信息
- 在pom.xml中
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.boot
spring-boot-starter-actuator
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
org.springframework.boot
spring-boot-starter-web
- 配置文件
application.yml
中
spring:
application:
name: Zuul-Consumer
server:
port: 9003
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
management:
endpoints:
web:
exposure:
include: '*'
management.endpoints.web.exposure.include
:打开actuator
的监控端口,默认只打开了health
,info
的监控监控点*
代表全部打开
4. 验证代理
依次启动
eureka-server-standalone
端口为8760,zuul-gateway
端口为9001,zuul-consumer
启动2个实例端口分别为9002,9003-
访问
http://localhost:9001/actuator/routes
,可见如下,代理了自己的服务zuul-gateway
的同时也代理了zuul-consumer
{ "/zuul-gateway/**": "zuul-gateway", "/zuul-consumer/**": "zuul-consumer" }
也可以查看详情
localhost:9001/actuator/routes/details
{ "/zuul-gateway/**": { "id": "zuul-gateway", "fullPath": "/zuul-gateway/**", "location": "zuul-gateway", "path": "/**", "prefix": "/zuul-gateway", "retryable": false, "customSensitiveHeaders": false, "prefixStripped": true }, "/zuul-consumer/**": { "id": "zuul-consumer", "fullPath": "/zuul-consumer/**", "location": "zuul-consumer", "path": "/**", "prefix": "/zuul-consumer", "retryable": false, "customSensitiveHeaders": false, "prefixStripped": true } }
-
验证代理的
ribbon
负载均衡,和hystrix
熔断保护功能
1.默认情况下zuul
有自己的路由规则- 会将
/zuul-consumer/**
转发到zuul-consumer
服务的接口上,通过调用/routes
也可以清晰的看到
2.访问代理接口
http://localhost:9001/zuul-consumer/getInstanceServiceIdAndPort
返回端口轮询切换,代表ribbon负载均衡正常工作- Zuul-Consumer:9002
- Zuul-Consumer:9003
- 会将
3.访问代理接口`http://localhost:9001/zuul-consumer/getInstanceServiceIdAndPortWithThrowError`,返回降级信息代表`hystrix`降级正常运行
>throw error is : go away!!and port is : 9002
三. 路由配置
1.使用url方式映射路由
- 直接使用
path
和url
地址路由到具体服务 - 在
zuul-gateway
的配置文件application.yml
中,添加zuul: routes: user-defined-zuul-a: path: /zuul-api-a/** url: http://localhost:9002 user-defined-zuul-b: path: /zuul-api-b/** url: http://localhost:9003
-
user-defined-zuul-a
和user-defined-zuul-b
是自定义key,/zuul-api-a/**
的请求会被路由到http://localhost:9002
服务 - 访问
/routes/details
可见代理详情{ "/zuul-api/**": { "id": "zuul", "fullPath": "/zuul-api/**", "location": "http://localhost:9002", "path": "/**", "prefix": "/zuul-api", "retryable": false, "customSensitiveHeaders": false, "prefixStripped": true }, "/zuul-gateway/**": { "id": "zuul-gateway", "fullPath": "/zuul-gateway/**", "location": "zuul-gateway", "path": "/**", "prefix": "/zuul-gateway", "retryable": false, "customSensitiveHeaders": false, "prefixStripped": true }, "/zuul-consumer/**": { "id": "zuul-consumer", "fullPath": "/zuul-consumer/**", "location": "zuul-consumer", "path": "/**", "prefix": "/zuul-consumer", "retryable": false, "customSensitiveHeaders": false, "prefixStripped": true } }
- 调用接口验证访问,zuul网关服务
http://localhost:9001/zuul-api-b/getInstanceServiceIdAndPort
,返回代理信息Zuul-Consumer:9003
- 注意:此种方式不会触发ribbon负载均衡和hystrix熔断功能
2. 使用服务id方式进行路由
直接使用
path
和serviceId
服务路由到具体服务,具有ribbon负载均衡和hystrix熔断功能-
在
zuul-gateway
的配置文件application.yml
中,添加zuul: routes: user-defined-zuul-c: path: /zuul-api-c/** serviceId : Zuul-Consumer
-
user-defined-zuul-c
是自定义key,/zuul-api-c/**
的请求会被路由到服务名称是Zuul-Consumer
的微服务 - 访问
/routes
可见代理
{ "/zuul-api-c/**": "Zuul-Consumer", "/zuul-gateway/**": "zuul-gateway", "/zuul-consumer/**": "zuul-consumer" }
-
-
上述配置可简写为
zuul: routes: Zuul-Consumer: /zuul-api-c/**
- 直接使用
servcieId:url
的形式
- 直接使用
3. 默认路由&忽略指定服务列表
- 如果我们不进行自定义配置,则zuul有自己的默认路由规则,如下:
"/zuul-gateway/**": "zuul-gateway", "/zuul-consumer/**": "zuul-consumer"
- 当我们访问zuul网关的
zuul-gateway/hello
就会路由到具体的微服务/hello
接口上
- 当我们访问zuul网关的
- 有时我们需要有zuul代理某个微服务,这时就需要忽略指定微服务代理
- 我们先查看一下,使用默认路由的代理情况,现在我们启动的项目如下
Zuul-Gateway
网关,ZuulConsumer
接口服务,EurekaServerStandalone
注册中心,访问zuul的/actuator/routes
端点接口,得到如下代理路由:"/zuul-gateway/**": "zuul-gateway", "/zuul-consumer/**": "zuul-consumer"
- 在
zuul-gateway
的配置文件application.yml
中,添加忽略配置,忽略zuul-gateway
微服务zuul: ignoredServices: 'zuul-gateway'
- 重启再次访问
/actuator/routes
,可见zuul-gateway
不再被代理{ "/zuul-consumer/**": "zuul-consumer" }
- 设置为
zuul.ignored-services=*
的时候将关闭所有默认路由配置规则
- 设置为
4. 路由优先级
- 路由规则是根据先后定义从上到下,假如某个请求路径可以和多个路由配置规则相匹配的话,Zuul根据匹配的先后顺序来决定最终使用哪个路由配置,例如如下配置
zuul: routes: Zuul-Consumer: /zuul-api-c/** Zuul-Consumer2: /zuul-api-c/a/**
- 访问
/zuul-api-c/a/xx
,不会转发到Zuul-Consumer2
服务上,会在Zuul-Consumer
查找相关接口,若没有,返回404
错误码
5.路由前缀 & 本地转发
- 使用
zuul.prefix
属性给全体路由添加前缀
访问zuul: prefix: /api
actuator/routes
可见所有代理都添加了前缀{ "/api/zuul-consumer2/**": "zuul-consumer2", "/api/zuul-gateway/**": "zuul-gateway", "/api/zuul-consumer/**": "zuul-consumer" }
-
zuul
不仅可以将请求转发到其他服务身上,也可以将请求转发到自己本身-
在zuul配置文件中,添加如下配置
zuul: routes: api: path: /api-d/** url: forward:/
-
url: forward:/
:代表跳转到本zuul服务的/
路径下所有接口
-
-
在Zuul-Gateway添加接口服务
@EnableZuulProxy @SpringCloudApplication @RestController public class ZuulGatewayApplication { public static void main(String[] args) { SpringApplication.run(ZuulGatewayApplication.class, args); } @Autowired private Registration registration; @GetMapping("hello") public String getInstanceServiceIdAndPort(){ String serviceId = registration.getServiceId(); int port = registration.getPort(); return serviceId+":"+port; } }
-
验证,访问
http://localhost:9001/api-d/hello
返回Zuul-Gateway:9001
-
6.头部过滤 & 重定向
-
在使用Zuul网关的时候你可能会遇到Cookie丢失的情况,这是因为默认情况下Zuul会过滤掉HTTP请求头中的一些敏感信息,不会向后传播,默认值为:
private Set
sensitiveHeaders = new LinkedHashSet(Arrays.asList("Cookie", "Set-Cookie", "Authorization")); -
这些敏感信息通过下面的配置设定,设置全局
zuul: sensitive-headers: Cookie,Set-Cookie,Authorization
-
设置某一个代理服务
zuul: routes: users: path: /myusers/** sensitiveHeaders: Cookie,Set-Cookie,Authorization url: https://downstream
-
关闭头部过滤,
sensitiveHeaders
设置为空就可以了zuul: routes: users: path: /myusers/** sensitiveHeaders: url: https://downstream
-
重定向host处理设置问题,使用如下配置解决
zuul: add-host-header: true
上一篇:Spring Cloud Hystrix聚集监控信息,Turbine详解(Finchley版本)