05基于Zuul的网关路由
2021-01-03 本文已影响0人
攻城老狮
一 Zuul的路由配置
路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础
1.1 Zuul网关的基础路由转发配置
- 创建工程导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
- 编写启动类,在类上面添加Zuul的启用注解
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class,args);
}
}
- 编写配置
server:
port: 8080
spring:
application:
name: zuul
- 编写路由转发
zuul:
routes:
product: # 这里是路由id,随意写
path: /product-service/** # 这里是映射路径
url: http://127.0.0.1:9001 # 映射路径对应的实际url地址
sensitiveHeaders: #默认zuul会屏蔽cookie,cookie不会传到下游服务,这里设置为空则取消默认的黑名单,如果设置了具体的头信息则不会传到下游服务
- 测试访问
http://localhost:8080/product-service/product/1
1.2 面向服务的路由配置
- 添加Eureka客户端依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- eureka客户端配置
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/
instance:
prefer-ip-address: true
- 修改映射配置,通过服务名获取 (经过测试,也会默认使用负载均衡调用相应的服务)
zuul:
routes:
product:
path: /product-service/**
service-id: product # 需要转发的微服务实例名称
sensitiveHeaders:
- 简化的路由配置
我们的 路由id往往和服务名是相同的。因此Zuul就提供了一种简化的配置语法:
zuul:
routes:
product: /product-service/** # eureka的服务名称和路由id一样可以简化,然后直接跟路径
- 默认路由规则
默认情况下,一切服务的映射路径就是服务名本身
例如 服务名为: service-product ,则默认的映射路径就是: /service-product/**
二 加入Zuul后的架构
image-20210101150455589.png三 Zuul的过滤配置
过滤器功能负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。每一个进入Zuul的HTTP请求都会经过一系列的过滤器处理链得到请求响应并返回给客户端。
3.1 Zuul的过滤流程图
image-20210101151037949.png3.2 自定义过滤器
@Component
public class LoginFilter extends ZuulFilter {
//过滤器类型 ,pre post routing error
@Override
public String filterType() {
return "pre";
}
//过滤器顺序,越小越靠前
@Override
public int filterOrder() {
return 1;
}
//过滤器是否开启
@Override
public boolean shouldFilter() {
return true;
}
//过滤器处理逻辑
@Override
public Object run() throws ZuulException {
//获取Zuul提供的请求上下文对象
RequestContext context = RequestContext.getCurrentContext();
//获取请求参数token的值
HttpServletRequest request = context.getRequest();
String token = request.getParameter("token");
//判断
if (!"yorick".equals(token)){
//校验失败,拦截
context.setSendZuulResponse(false);
//401
context.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
}
//放行
return null;
}
}
Zuul的缺陷
- 性能问题,Zuul1x版本本质上就是一个同步Servlet,采用多线程阻塞模型进行请求转发。简单讲,每来一个请求,Servlet容器要为该请求分配一个线程专门负责处理这个请求,直到响应返回客户端这个线程才会被释放返回容器线程池。如果后台服务调用比较耗时,那么这个线程就会被阻塞,阻塞期间线程资源被占用,不能干其它事情。我们知道Servlet容器线程池的大小是有限制的,当前端请求量大,而后台慢服务比较多时,很容易耗尽容器线程池内的线程,造成 容器无法接受新的请求。
- 不支持长连接,如 websocket。