SpringCloud微服务网关Zuul

Zuul是什么?
  1. Spring Cloud Zuul是整合Netflix公司的Zuul开源项目实现的微服务网关,它实现了请求路由、负载均衡、校验过虑等功能
  2. 默认http客户端是Apache Http Client, 也可以使用RestClient或者okhttp3,如果使用RestClient可以设置ribbon.restclient.enabled=true;如果使用okhttp3,可以设置ribbon.okhttp.enabled=true
  3. Zuul的核心是一系列的过滤器,这些过滤器可以完成以下功能
  • 身份认证和安全,识别每个资源的验证请求,并拒绝哪些不符合要求的请求
  • 审查和监控,在边缘位置追踪有意义的数据和统计结果,从而带来精确的生产视图
  • 动态路由,动态地将请求路由到不同的微服务
  • 压力测试,逐渐增加指向集群的流量,以了解性能
  • 负载分配,为每一种负载类型分配对应容量,并启用超出限定值的请求
  • 静态响应处理,在边缘位置直接建立部分响应,从而避免其转发到内部集群
  • 多区域弹性
什么是网关?

服务网关是在微服务前边设置一道屏障,请求先到服务网关,网关会对请求进行过虑、校验、路由等处理。有了服务网关可以提高微服务的安全性,网关校验请求的合法性,请求不合法将被拦截,拒绝访问。

Zuul在系统架构中的位置

不管是来自于客户端(PC或移动端)的请求,还是服务内部调用。一切对服务的请求都会经过Zuul这个网关,然后再由网关来实现 鉴权、动态路由等等操作。Zuul就是我们服务的统一入口。


Zuul在系统架构中的位置
快速入门
  • 依赖

    
        org.springframework.cloud
        spring-cloud-starter-netflix-zuul
    

  • 配置路由
server:
  port: 40001
spring:
  application:
    name: api-gateway
zuul:
  routes:
    eureka-client-user: # 这里是路由id,随意写
      path: /eureka-client-user/** # 这里是映射路径
      url: http://127.0.0.1:20001 # 映射路径对应的实际url地址
  • 开启Zuul
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZuulApplication.class, args);
    }
}
  • 测试
    http://localhost:40001/eureka-client-user/hello
面向服务的路由

在上面的例子中我们把路径对应的服务地址写死了!如果同一服务有多个实例的话,这样做显然就不合理了。
我们应该根据服务的名称,去Eureka注册中心查找 服务对应的所有实例列表,然后进行动态路由。

  • 添加Eureka客户端依赖

    org.springframework.cloud
    spring-cloud-starter-netflix-eureka-client

  • 开启Eureka客户端发现功能
@SpringBootApplication
@EnableZuulProxy // 开启Zuul的网关功能
@EnableDiscoveryClient
public class ZuulDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(ZuulDemoApplication.class, args);
    }
}
  • application.yml
zuul:
  routes:
    eureka-client-user:
      path: /eureka-client-user/** 
      url: eureka-client-user
eureka:
  client:
    registry-fetch-interval-seconds: 5 # 获取服务列表的周期:5s
    service-url:
      defaultZone: http://127.0.0.1:10001/eureka/,http://127.0.0.1:10002/eureka/
  • 测试
    http://localhost:40001/eureka-client-user/hello
路由规则
  • 简化路由配置
    大多数情况下,路径名称和服务名会写成一样,这种情况下我们可以使用简化的配置方法
zuul:
  routes:
    eureka-client-user: /eureka-client-user/** 
  • 默认的路由规则
    默认情况下,一切服务的映射路径就是服务名本身,也就是说我们不配置也是可以的。
  • 路由前缀
    请求的路径就需要加上/api
zuul:
  prefix: /api # 添加路由前缀
  routes:
    eureka-client-user: /eureka-client-user/** 
过滤器

Zuul作为网关的其中一个重要功能,就是实现请求的鉴权。而这个动作我们往往是通过Zuul提供的过滤器来实现的。

  • ZuulFilter
    ZuulFilter是过滤器的顶级父类。
public abstract ZuulFilter implements IZuulFilter{
    //返回字符串,代表过滤器的类型
    //pre:请求在被路由之前执行
    //routing:在路由请求时调用
    //post:在routing和errror过滤器之后调用
    //error:处理请求时发生错误调用
    abstract public String filterType();

    //通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高
    abstract public int filterOrder();

    //返回一个Boolean值,判断该过滤器是否需要执行。返回true执行,返回false不执行    
    boolean shouldFilter();

    //过滤器的具体业务逻辑
    Object run() throws ZuulException;
}
  • 请求流程
    正常流程:
    1.请求到达首先会经过pre类型过滤器,而后到达routing类型,进行路由,请求就到达真正的服务提供者,执行请求,返回结果后,会到达post过滤器。而后返回响应。
    异常流程:
    1.整个过程中,pre或者routing过滤器出现异常,都会直接进入error过滤器,再error处理完毕后,会将请求交给POST过滤器,最后返回给用户。
    2.如果是error过滤器自己出现异常,最终也会进入POST过滤器,而后返回。
    3.如果是POST过滤器出现异常,会跳转到error过滤器,但是与pre和routing不同的时,请求不会再到达POST过滤器了。
  • 使用场景
    请求鉴权:一般放在pre类型,如果发现没有访问权限,直接就拦截了。
    异常处理:一般会在error类型和post类型过滤器中结合来处理。
    服务调用时长统计:pre和post结合使用。
  • 自定义过滤器
@Component
public class LoginFilter extends ZuulFilter {

    @Override
    public String filterType() {
        // 登录校验,肯定是在前置拦截
        return "pre";
    }

    @Override
    public int filterOrder() {
        // 顺序设置为1
        return 1;
    }

    @Override
    public boolean shouldFilter() {
        //返回true, 代表过滤器生效
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        //登录校验逻辑
        //1.获取Zuul提供的请求上下文对象
        RequestContext ctx = RequestContext.getCurrentContext();
        //2.从请求中获取token
        HttpServletRequest req = ctx.getRequest();
        String token = req.getParameter("access-token");
        //3.校验
        if(token == null || "".endsWith(token.trim())){
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
        }
        return null;
    }

}
负载均衡和熔断

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

你可能感兴趣的:(SpringCloud微服务网关Zuul)