zoukankan      html  css  js  c++  java
  • 微服务网关Zuul详解

    简述

      不同的微服务一般会有不同的服务地址,客户端在访问这些地址的时候需要记录几十甚至几百个地址,这对于客户端来说过于复杂和难以维护。

      这样存在的问题有:客户端会请求多个不同的服务,需要维护不同的请求地址,增加开发难度。而且这样的机制会增加身份认证的难度,每个微服务需要独立认证。

    微服务网关

      微服务网关就应运而生,微服务网关介于客户端与服务器之间的中间层它是一个服务器,是系统对外的唯一入口。所有的外部请求都会先经过微服务网关。客户端只需要与网关交互,只知道一个网关地址即可。

    Zuul网关

      Zuul网关是是Netflflix开源的微服务网关,它可以和Eureka、Ribbon、Hystrix等组件配合使用,Zuul组件的核心是一系列的过滤器。这些过滤器可以完成:

      动态路由:动态将请求路由到不同后端集群 

      压力测试:逐渐增加指向集群的流量,以了解性能

      负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求

      静态响应处理:边缘位置进行响应,避免转发到内部集群 

      身份认证和安全: 识别每一个资源的验证要求,并拒绝那些不符的请求。Spring Cloud对Zuul进行了整合和增强。 

      zuul的底层基于Servlet,本质上就是一系列的filter过滤器。

    zuul的基本使用

      首先要清楚的是zuul是一台服务器,我们要在项目中创建一个新的模组

      引入zuul的相关依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>

      在springboot启动类上加入zuul的支持注解

      至此zuul的准备工作已经完成

    zuul基础路由配置

      这里对路由的理解就是根据请求URL,将请求分配到对应的处理程序。在微服务体系中,Zuul负责接收所有的请求。根据不同的URL匹配规则,将不同的请求转发到不同的微服务处理。

      我们在项目的yml文件中可以配置zuul的路由:

    #路由配置
    zuul:
      routes:
        product-server: #路由的id
          path: /product-service/** #配置映射路径
          url: http://127.0.0.1:9001 #映射路径的实际微服务url地址

    面向服务的路由配置

      微服务一般是由几十、上百个服务组成,对于一个URL请求,最终会确认一个服务实例进行处理。如果对每个服务实例手动指定一个唯一访问地址,然后根据URL去手动实现请求匹配,这样做显然就不合理。

      Zuul支持与Eureka整合开发,根据ServiceID自动的从注册中心中获取服务地址并转发请求,这样做的好处不仅可以通过单个端点来访问应用的所有服务,而且在添加或移除服务实例的时候不用修改Zuul的路由配置。 

      我们首先要添加eureka的依赖:

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>

      然后开启eureka的服务发现:

      我们还需要配置eureka

    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:9000/eureka/
          registry-fetch-interval-seconds: 5 # 获取服务列表的周期:5s
      instance:
        preferIpAddress: true
        ip-address: 127.0.0.1

      此时我们的zuul基础路由配置中的url就可以不用写了,因为此时的服务地址是从eureka中获取的

      我们只需配置serviceId即可

    zuul:
      routes:
        product-service: # 这里是路由id,随意写
          path: /product-service/** # 这里是映射路径
          # url: http://127.0.0.1:9001 # 映射路径对应的实际url地址
          serviceId: service-product #整合eureka后会从eureka中获取服务地址
          sensitiveHeaders: #默认zuul会屏蔽cookie,cookie不会传到下游服务,这里设置为空则取 消默认的黑名单,如果设置了具体的头信息则不会传到下游服务

    配置的简化

      如果路由的id和service的id一致的话,我们可以只写这么一行配置映射路径

    zuul:
      routes:
        #product-service: # 这里是路由id,随意写
        #  path: /product-service/** # 这里是映射路径
        #  # url: http://127.0.0.1:9001 # 映射路径对应的实际url地址
        #  serviceId: service-product #整合eureka后会从eureka中获取服务地址
        #  sensitiveHeaders: #默认zuul会屏蔽cookie,cookie不会传到下游服务,这里设置为空则取 消默认的黑名单,如果设置了具体的头信息则不会传到下游服务
        service-product: /product-service/**

    Zuul网关加入之后的架构图

    Zuul网关过滤器

      zuul的路由功能实现了统一处理外部请求的功能,负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础。

      zuul还提供过滤器功能,负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。

      ZuulFilter有四种类型:

    PRE
    这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请
    求的微服务、记录调试信息等。
    ROUTING
    这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用
    Apache HttpClient或Netfifilx Ribbon请求微服务。 
    POST
    这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP
    Header、收集统计信息和指标、将响应从微服务发送给客户端等。
    ERROR
    在其他阶段发生错误时执行该过滤器。
      
      我们只需自定义一个filter类并继承ZuulFilter重写四个方法即可定义一个zuul过滤器类
      zuul提供一个RequstContext上下文对象,它内部采用ThreadLocal保存每个请求的一些信息,包括请求路由、错误信息、HttpServletRequest、HttpServletResponse,这使得一些操作是十分可靠的,它还扩展了ConcurrentHashMap,目的是为了在处理过程中保存任何形式的信息
    package hjj.filter;
    
    import com.netflix.zuul.ZuulFilter;
    import com.netflix.zuul.context.RequestContext;
    import com.netflix.zuul.exception.ZuulException;
    import org.apache.http.HttpStatus;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    
    /**
     * 自定义的zuul过滤器
     */
    @Component
    public class LoginFilter extends ZuulFilter {
    
        //定义过滤器类型 pre routing post error
        @Override
        public String filterType() {
            return "pre";
        }
    
        //指定过滤器的执行顺序 返回值越小执行顺序越高
        @Override
        public int filterOrder() {
            return 1;
        }
    
        //当前过滤器是否生效 true使用 false不使用
        @Override
        public boolean shouldFilter() {
            return true;
        }
    
        //执行过滤器中的业务逻辑 身份认证,所有的请求都需要携带一个参数:access-token
        @Override
        public Object run() throws ZuulException {
            //获取上下文对象
            RequestContext ctx = RequestContext.getCurrentContext();
            //获取request请求
            HttpServletRequest request = ctx.getRequest();
            //获取request参数
            String token = request.getParameter("access-token");
            //获取token并进行判断
            if(token == null){
                //拦截请求,认证失败
                ctx.setSendZuulResponse(false);//拦截请求
                ctx.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);//返回错误码
            }
            System.out.println("执行了过滤器");
            return null;
        }
    }
    zuul网关拦截器类 身份验证简单实现
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    一点一点积累,一点一点蜕变!
  • 相关阅读:
    图像分割学习笔记_1(opencv自带meanshift分割例子)
    基础学习笔记之opencv(10):Mat mask操作
    Qt学习之路_6(Qt局域网聊天软件)
    Qt学习之路_8(Qt中与文件目录相关操作)
    Android开发历程_6(RadioButton和CheckBox的使用)
    Qt学习之路_4(Qt UDP的初步使用)
    目标跟踪学习笔记_4(particle filter初探3)
    Reading papers_11(读Integrating local action elements for action analysis相关文章)
    基础学习笔记之opencv(8):Mat 基本图像容器
    基础学习笔记之opencv(14):随机数发生器&绘制文字
  • 原文地址:https://www.cnblogs.com/qq2210446939/p/15085687.html
Copyright © 2011-2022 走看看