JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

聊聊微服务网关Zuul的使用 微服务网关的作用

wys521 2024-10-17 15:48:49 精选教程 21 ℃ 0 评论


简介

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

  • 身份认证和安全:识别每一个资源的验证要求,并拒绝那些不符的请求
  • 审查与监控:
  • 动态路由:动态将请求路由到不同后端集群
  • 压力测试:逐渐增加指向集群的流量,以了解性能
  • 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求
  • 静态响应处理:边缘位置进行响应,避免转发到内部集群
  • 多区域弹性:跨域AWS Region进行请求路由,旨在实现ELB(ElasticLoad Balancing)使用多样化

Spring Cloud对Zuul进行了整合和增强。目前,Zuul使用的默认是Apache的HTTP Client,也可以使用Rest Client,可以设置

ribbon.restclient.enabled=true

Zuul和Eureka配合使用

  • 添加依赖
  • <dependency>
    
          <groupId>org.springframework.cloud</groupId>
    
          <artifactId>spring-cloud-starter-eureka</artifactId>
    
    </dependency>
    
    <dependency>
    
          <groupId>org.springframework.cloud</groupId>
    
          <artifactId>spring-cloud-starter-zuul</artifactId>
    
    </dependency>
  • 启动类加上注解@EnableZuulProxy
  • yml文件添加zuul配置
  • Zuul Timeouts(zuul超时时间配置)

    zuul:
      ribbon:
        eager-load:
          enabled: true
      ignoredServices: '*' //忽略所有请求
      routes:
        preOrderOnlinePaid:  // 路由名称,随意,唯一即可
          path: /api/sps/orders/online-paid // 路由路径
          serviceId: sps-schedule-service  // 服务id
          stripPrefix: false
        preOrderOfflinePaid:
          path: /api/v1/orders/workflow-create
          serviceId: sps-preorder-service
          stripPrefix: false
        repairData:
          path: /api/v1/repairData/**
          serviceId: sps-crm-service
          stripPrefix: false
      host:   // Zuul routes by specifying URLs
        connect-timeout-millis: 60000
        socket-timeout-millis: 60000
    hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000 //hystrix超时时间设置
    ribbon:   //ribbon超时时间设置
      ConnectTimeout: 60000
      ReadTimeout: 60000

    zuul知识点详解

    1. 路由的前缀

    • zuul.prefix: 指定一个全局的前缀
    • strip-prefix: 是否将这个代理前缀去掉
    • 如果strip-prefix只是放在路由下面,那么就是局部的,不会影响全局(如上的配置)

    2. 忽略某些路径

    过滤掉path包含admin的请求

    zuul:
      ignoredPatterns: /**/admin/**
      routes:
    users: /myusers/**

    3. Zuul的安全

    • 敏感的Header设置

    在同一个系统中微服务之间共享Header,但是某些时候尽量防止让一些敏感的Header外泄。因此很多场景下,需要通过为路由指定一系列敏感的Header列表。例如:

    zuul:
      routes:
        abc:
          path: /provider/**
          service-id: microservice-provider-user
          sensitiveHeaders:Cookie,Set-Cookie,Authorization
          url: https://downstream
  • 忽略Header
  • 被忽略的Header不会被传播到其他的微服务去。其实敏感的Heade最终也是走的这儿. 默认情况下,ignored-headers是空的

    zuul:
      ignored-headers: Header1,Header2

    4. strangle模式

    在迁移现有应用程序或API时,一种常见的模式是“扼杀”旧的端点,用不同的实现慢慢替换它们。Zuul代理是一个有用的工具,因为您可以使用它来处理来自旧端点客户端的所有流量,但是将一些请求重定向到新端点。

    zuul:
      routes:
        first:
          path: /first/**
          url: http://first.example.com
        second:
          path: /second/**
          url: forward:/second
        third:
          path: /third/**
          url: forward:/3rd
        legacy:
          path: /**
          url: http://legacy.example.com  // 遗留的或者剩余的都走这个路径
    

    5. 使用Zuul上传文件

    配置上传文件的max-size

    spring:
      http:
       multipart:
         max-file-size: 2mb
         max-request-size: 2mb
    
    • 请求路径中添加/zuul前缀可以解决上传大文件报错的问题以及中文乱码的问题

    6. Zuul的容错与回退

    • 为Zuul添加回退

    想要为Zuul添加回退,需要实现FallbackProvider接口。在实现类中,指定为哪一个微服务提供回退,并且提供一个ClientHttpResponse作为回退响应。

    @Component
    public class BaseServiceFallbackProvider implements FallbackProvider {
        @Override
        public String getRoute() {
            // 服务id,如果需要所有调用都支持回退,则return "*"或return null
            return "*";
        }
        @Override
        public ClientHttpResponse fallbackResponse() {
            return null;
        }
        /**
         * 如果请求用户服务失败,返回信息给消费者客户端
         */
        @Override
        public ClientHttpResponse fallbackResponse(Throwable cause) {
            return new ClientHttpResponse() {
                @Override
                public HttpHeaders getHeaders() {
                    HttpHeaders httpHeaders = new HttpHeaders();
                    // 和body中的编码一致,否则容易乱码
                    httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
                    return httpHeaders;
                }
                @Override
                public InputStream getBody() throws IOException {
                    JSONObject r = new JSONObject();
                    r.put("state", 500);
                    r.put("message", cause.getMessage());
                    return new ByteArrayInputStream(r.toJSONString().getBytes("UTF-8"));
                }
                @Override
                public HttpStatus getStatusCode() throws IOException {
                    return HttpStatus.OK;
                }
                @Override
                public int getRawStatusCode() throws IOException {
                    return HttpStatus.OK.value();
                }
                @Override
                public String getStatusText() throws IOException {
                    return HttpStatus.OK.getReasonPhrase();
                }
                @Override
                public void close() {
    
                }
            };
        }
    }
    

    7. Zuul的高可用

    • Zuul客户端注册到了Eureka Server上

    此种情况,Zuul的高可用实现比较简单,只需将多个Zuul节点注册到Eureka Server,就可以实现Zuul高可用。此时,Zuul与其他的微服务高可用没啥区别。Zuul客户端会自动从Eureka Server中查询Zuul Server的列表,并使用Ribbon负载均衡的请求Zuul集群

    • Zuul客户端未注册到Eureka Server上

    如果Zuul客户端未注册到Eureka上,因为微服务可能被其他微服务调用,也可能直接被终端调用,比如手机App。此种情况下,我们需要借助额外的负载均衡器来实现Zuul的高可用,比如Nginx,比如HAProxy或者F5等

    8. Zuul的过滤器

    过滤器是Zuul的核心组件,Zuul大部分功能都是通过过滤器来实现的。

    • 过滤器类型和请求生命周期

    Zuul中定义了四种标准的过滤器类型,这些过滤器类型对应于典型的生命周期。

    1. PRE: 这种过滤器在请求被路由之前调用。可利用其实现身份验证等
    2. ROUTING: 这种过滤器将请求路由到微服务,用于构建发送给微服务的请求,并使用Apache Http Client或者Netflix Ribbon请求微服务
    3. POST: 这种过滤器在路由到微服务以后执行,比如为响应添加标准的HTTP Header,收集统计信息和指标,将响应从微服务发送到客户端等
    4. ERROR: 在其他阶段发生错误时执行该过滤器

    除了默认的过滤器类型,Zuul还允许创建自定义的过滤器类型。

    @Component
    public class AuthenticationFilter extends BaseFilter {
    
        public static final String ACCESS_TOKEN = "access-token";
    
        @Override
        public String filterType() {
            return FilterConstants.PRE_TYPE;
        }
    
        @Override
        public int filterOrder() {
            return 1;
        }
    
        @Override
        public boolean shouldFilter() {
            // todo 改成:读取配置文件需要验证token的uri为true,不需要为false
            return true;
        }
    
        @Override
        public Object run() {
            HttpServletRequest httpServletRequest =getRequestContext().getRequest();
    
            String token = httpServletRequest.getHeader(ACCESS_TOKEN);
            if (StringUtils.isNotBlank(token)) {
                tokenError(HttpStatus.UNAUTHORIZED.value(), "token error");
                return null;
            }
            //todo 校验token
            return null;
        }
    
    }

    Tags:

    本文暂时没有评论,来添加一个吧(●'◡'●)

    欢迎 发表评论:

    最近发表
    标签列表