大家如果觉得我写的好,可以关注这个项目,之后我的学习过程中都会把学习笔记放入这个项目中。
https://github.com/IndustriousSnail/learning-notes
Spring Cloud Zuul服务网关
目录
一、服务网关简介
1.1 为什么要使用服务网关
假设,我们有许多微服务,商品、订单、用户等等。那么前端不可能为每一个服务单独配置地址,必须有一个统一的接口地址。 所以就需要使用服务网关作为这些服务的统一入口。1.2 服务网关的要素
- 稳定行,高可用
- 性能,并发性
- 安全性
- 扩展性
作为所有服务的统一入口,如果它挂了,那所有的服务都挂了。所以这两点必须保证。所以这上面的都需要做到。
1.3 Zuul的特点
1.路由+过滤器=Zuul2.核心是一系列的过滤器
1.4 Zuul中的HTTP请求生命周期
如图所示,Zuul中定义了四种标准过滤器:
1. 前置(Pre)
2. 后置(Post)
3. 路由(Route)
4. 错误(Error)
这四种过滤器靠RequestContext通信。
1. 当HTTP请求到达时,首先进入PreFilters(前置过滤器)。
2. 之后会经过RoutingFilter(路由过滤器)进行路由转发,分发给服务。
3. 最后服务响应HTTP请求之后,经过PostFilter(后置路由器)。
4. 如果上述过滤器发生异常时,会进入ErrorFilter.
5. customFilters(自定义过滤器)可以加载任何一个位置。
二、Zuul组件的使用
2.1 简单使用案例
1.新建Zuul项目,同样需要引入Eureka和Config依赖。 还有Zuul依赖。<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
2.在Application启动类上增加@EnableZuulProxy注解
@SpringBootApplication
@EnableZuulProxy //开启网关服务
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
3.启动项目。就可以使用网关访问其他服务的接口了。
比如,我们的网关端口是6080。 我们有一个服务order,他有一个接口test。
如果访问order的话是“localhost:8080/test”。那么使用网关访问则是:
localhost:6080/order/test
1.localhost为网关的地址。
2.6080为网关的端口。
3.order为要访问接口的服务的名称。
4./test为要访问的接口。
2.2 自定义路由
上面我们使用的是“服务的名称+服务的url”进行接口调用。如果要自定义路由规则,需要使用以下配置。zuul:
# 路由配置
routes:
# 自定义规则的规则名称
myOrder:
# 自定义的路由路径
path: /myOrder/**
# 要路由到的服务的名称
serviceId: order
# 简洁写法, order为要路由到的服务名称,后面是自定义的路由路径。
# order: /myOrder/**
# 如果要禁止某个接口的外部调用,可以使用如下配置
# ignored-patterns: #这个参数接受一个set<String>,String是一个正则表达式。具体写法如下
# - /order/test # 禁止“/order/test”这个路径的访问
# - /myOrder/test
之后使用下面地址同样可以访问到接口(之前的也可以使用)。
http://localhost:6080/myOrder/test
2.3 查看所有路由规则
1.增加配置,关闭安全限制。management:
security:
enabled: false
2.访问routes接口
http://localhost:6080/routes //低版本访问这个
http://localhost:6080/application/routes //高版本访问这个
3.可以看到浏览器打印了如下内容
{
/myOrder/**: "order",
/config/**: "config",
/order/**: "order"
}
前面的是路由规则,后面是服务名称。
2.4 Cookie的传递
如果使用了Zuul,那么Cookie是无法正常传递到Controller中的。 是因为Zuul默认对Http Header进行了敏感过滤。对应源码中的下列一段代码。private Set<String> sensitiveHeaders = new LinkedHashSet<>(
Arrays.asList("Cookie", "Set-Cookie", "Authorization"));
如果要解除Cookie的限制。或者增加敏感头的配置,需要对sensitiveHeaders进行配置。
比如,解除敏感头,只需要将sensitiveHeaders配置为空,如下:
zuul:
# 路由配置
routes:
# 自定义规则的规则名称
myOrder:
# 自定义的路由路径
path: /myOrder/**
# 要路由到的服务的名称
serviceId: order
# 将该配置配置为空,不让其拦截Cookie。
sensitiveHeaders:
三、自定义过滤器的使用
1.自定义过滤器,继承ZuulFilter类@Component
public class CustomFilter extends ZuulFilter { //继承抽象类ZuulFilter,并将其注入bean
/**
* 定义过滤器的类型。
* @return 过滤器类型。可以包含"pre","post","route","error"四种。
*/
@Override
public String filterType() {
//import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
return PRE_TYPE; //使用pre(前置过滤器)
}
/**
* 定义过滤器的顺序。 数值越小越靠前。
* 可以到“import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants”
* 这个类下面查看其他系统过滤器的优先级。
* @return 过滤器的优先级。值越小越先执行。
*/
@Override
public int filterOrder() {
return 0;
}
/**
* @return 是否启动该过滤器
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 处理逻辑
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
System.out.println("pre拦截器");
RequestContext requestContext = RequestContext.getCurrentContext();//获取当前上下文
HttpServletRequest httpServletRequest = requestContext.getRequest(); //获取HttpServletRequest
//拿到HttpServletRequest之后,就可以做一些自己的处理逻辑
//....处理逻辑
//比如,我们校验url中是否含有token参数
String token = httpServletRequest.getParameter("token");
if(StringUtils.isEmpty(token)){
//如果参数中没有token参数,则直接返回失败,不再转发到各个服务Controller。
requestContext.setSendZuulResponse(false); //设置发送Zuul响应为False。
requestContext.setResponseStatusCode(401); //设置http状态码
}
//处理逻辑结束。
return null;
}
}
2.重启Zuul Server就行了。