• SpringCloud微服务实战-Zuul路由网关


    本文转自:http://blog.csdn.net/qq_22841811/article/details/67637786#准备工作

    刚开始写博客,先从摘录开始吧。后续陆续将有道的笔记迁移过来~~~。

    1 API Gateway

    2 Zuul介绍

    2.1 zuul的功能

    • Routing in an integral part of a microservice architecture. For example, / may be mapped to your web application, /api/users is mapped to the user service and /api/shop is mapped to the shop service. Zuul is a JVM based router and server side load balancer by Netflix.
    • 路由在微服务架构的一个组成部分。 例如,/可以映射到您的Web应用程序,/ api / users映射到用户服务,并且/ api / shop映射到商店服务。 Zuul是Netflix的基于JVM的路由器和服务器端负载均衡器。
    • 其功能包括 
      • 验证
      • 见解
      • 压力测试
      • 金丝雀测试
      • 动态路由
      • 服务迁移
      • 减载
      • 安全
      • 静态响应处理
      • 主动/主动流量管理
    • Zuul的规则引擎允许规则和过滤器基本上用任何JVM语言编写,内置支持Java和Groovy。

    2.2 Zuul的配置简述

    • 配置属性zuul.max.host.connections已被两个新属性zuul.host.maxTotalConnections和zuul.host.maxPerRouteConnections替换,默认分别为200和20。
    • 所有路由的默认Hystrix隔离模式(ExecutionIsolationStrategy)为SEMAPHORE。 如果首选此隔离模式,则可以将zuul.ribbonIsolationStrategy更改为THREAD。

    2.3 在springcloud中使用zuul

    • Spring Cloud创建了一个嵌入式Zuul代理,以简化一个非常常见的用例开发,即UI应用程序想要代理对一个或多个后端服务的调用。此功能对于用户界面代理所需的后端服务非常有用,从而避免了对所有后端独立管理CORS和身份验证问题。
    • 要启用它,使用@EnableZuulProxy注释一个Spring Boot主类,并将本地调用转发到相应的服务。按照惯例,ID为“users”的服务将从位于/ users处的代理(带有前缀剥离)接收请求。代理使用Ribbon来定位要通过发现转发的实例,并且所有请求都在hystrix命令中执行,因此故障将显示在Hystrix指标中,一旦电路打开,代理将不会尝试联系服务。
    • 注意:Zuul启动器不包括发现客户端,因此对于基于服务ID的路由,您需要在类路径中提供其中一个(例如Eureka是一个选择)。

    3 Zuul的基本使用

    • maven依赖
     
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>spring-cloud-microservice-study</artifactId>
            <groupId>com.clsaa.learn.springcloud</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>microservice-gateway-zuul</artifactId>
    
        <dependencies>
            <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>
        </dependencies>
    </project>
     
    • 启动类
    package com.clsaa.learn.zuul;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
    
    /**
        使用@EnableZuulProxy注解激活zuul。
     * 跟进该注解可以看到该注解整合了@EnableCircuitBreaker、@EnableDiscoveryClient,是个组合注解,目的是简化配置。
     * Created by Egg on 2017/7/25
     */
    @SpringBootApplication
    @EnableZuulProxy
    public class ZuulApplication {
        public static void main(String[] args) {
            SpringApplication.run(ZuulApplication.class,args);
        }
    }

    配置文件:application.yml

    spring:
      application:
        name: microservice-gateway-zuul
    server:
      port: 8040
    eureka:
      instance:
        hostname: localhost   # 指定该Eureka实例的主机名
        prefer-ip-address: true
      client:
        serviceUrl:
          defaultZone: http://username:password@localhost:8761/eureka

    3.1 测试

    • 启动microservice-api-gateway项目。还记得我们之前访问通过http://localhost:8000/1去访问microservice-provider-user服务中id=1的用户信息吗?

    我们现在访问http://localhost:8050/microservice-provider-user/1试试。会惊人地看到:

    {"id":1,"username":"Tom","age":12}

    这不正是microservice-provider-user服务中id=1的用户信息吗?

    所以我们可以总结出规律:访问

    http://GATEWAY:GATEWAY_PORT/想要访问的Eureka服务id的小写/** 将会访问到 http://想要访问的Eureka服务id的小写:该服务端口/**

    4 自定义配置Zuul路由

    上文我们已经完成了通过API Gateway去访问微服务的目的,是通过http://GATEWAY:GATEWAY_PORT/想要访问的Eureka服务id的小写/**的形式访问的,那么如果我们想自定义在API Gateway中的路径呢?譬如想使用http://localhost:8050/user/1就能够将请求路由到http://localhost:8000/1呢?

    只需要做一点小小的配置即可:

    spring:
      application:
        name: microservice-api-gateway
    server:
      port: 8050
    eureka:
      instance:
        hostname: gateway
      client:
        serviceUrl:
          defaultZone: http://discovery:8761/eureka/
    # 下面整个树都非必须,如果不配置,将默认使用 http://GATEWAY:GATEWAY_PORT/想要访问的Eureka服务id的小写/** 路由到:http://想要访问的Eureka服务id的小写:该服务端口/**
    zuul:
      routes:
        user:                                               # 可以随便写,在zuul上面唯一即可;当这里的值 = service-id时,service-id可以不写。
          path: /user/**                                    # 想要映射到的路径
          service-id: microservice-provider-user            # Eureka中的serviceId

    5 如何忽略某些服务

    准备工作

    1. 启动服务:microservice-discovery-eureka
    2. 启动服务:microservice-provider-user
    3. 启动服务:microservice-consumer-movie-ribbon

    如果我们现在只想将microservice-consumer-movie-ribbon服务暴露给外部,microservice-provider-user不想暴露,那么应该怎么办呢?

    依然只是一点小小的配置即可:

    spring:
      application:
        name: microservice-api-gateway
    server:
      port: 8050
    eureka:
      instance:
        hostname: gateway
      client:
        serviceUrl:
          defaultZone: http://discovery:8761/eureka/
    zuul:
      ignored-services: microservice-provider-user          # 需要忽视的服务(配置后将不会被路由)
      routes:
        movie:                                              # 可以随便写,在zuul上面唯一即可;当这里的值 = service-id时,service-id可以不写。
          path: /movie/**                                   # 想要映射到的路径
          service-id: microservice-consumer-movie-ribbon-with-hystrix    # Eureka中的serviceId
    • 也可使用ignoredServices:服务名
    • 路由必须有一个“路径”,可以指定为ant样式模式,所以“/ myusers / ”只匹配一个级别,但“/ myusers / *”分层匹配。
    • 后端的位置可以被指定为“serviceId”(对于来自发现的服务)或“url”(对于物理位置),例如。
    zuul:
      routes:
        users:
          path: /myusers/**
          url: http://example.com/users_service

    6 启动Hystrixcommand

    • 这些简单的url路由不会作为HystrixCommand执行,也不能使用Ribbon来平衡多个URL。 要实现此目的,请指定服务路由并为serviceId配置功能区客户端(这当前需要禁用功能区中的Eureka支持:有关详细信息,请参阅上文)。
    zuul:
      routes:
        users:
          path: /myusers/**
          serviceId: users
    
    ribbon:
      eureka:
        enabled: false
    
    users:  #这是ribion要请求的serviceID
      ribbon:
        listOfServers: http://localhost:7900,http://localhost:7901 

    7 使用正则表达规则路由

    • 可以使用regexmapper在serviceId和路由之间提供约定。 它使用正则表达式命名的组从serviceId提取变量并将它们注入到路由模式中。
    • regexmapper:用于routepattern转换为servicePattern
    • routepattern:路由正则表达式
    • servicePattern:service正则表达式
    @Bean
    public PatternServiceRouteMapper serviceRouteMapper() {
        return new PatternServiceRouteMapper(
            "(?<name>^.+)-(?<version>v.+$)",
            "${version}/${name}");
    }
    • 这意味着serviceId“myusers-v1”将映射到路由“/ v1 / myusers / ”。 接受任何正则表达式,但所有命名组必须同时存在于servicePattern和routePattern中。 如果servicePattern与serviceId不匹配,则使用缺省行为。 在上面的示例中,serviceId“myusers”将映射到路由“/ myusers / ”(未检测到任何版本)。此功能默认情况下处于禁用状态,仅适用于发现的服务。
    zuul:
      ignoredPatterns: /**/admin/**
      routes:
        users: /myusers/**
    • This means that all calls such as “/myusers/101” will be forwarded to “/101” on the “users” service. But calls including “/admin/” will not resolve.

    • 如果你需要你的路由以保留它们的顺序,你需要使用YAML文件,因为使用属性文件将会丢失顺序。 例如:如果要使用属性文件,则旧路径可能会在用户路径前面显示,导致用户路径无法访问。

    8 zuul.prefix

    • 要向所有映射添加前缀,请将zuul.prefix设置为一个值,例如/ api。 默认情况下,在转发请求之前,从请求中删除代理前缀(使用zuul.stripPrefix = false关闭此行为)。
    • prefix和stripPrefix(依赖于prefix的使用)连用影响是全局的
    • path和stripPrefix连用影响是局部的

    9 细节知识

    9.1 routes

    • 如果使用@EnableZuulProxy与Spring Boot Actuator,您将启用(默认情况下)一个额外的端点,通过HTTP作为/ routes可用。 到此端点的GET将返回映射路由的列表。 POST将强制刷新现有路由(例如,如果服务目录中有更改)。

    9.2 Strangulation Patterns (绞杀者模式)

    • 迁移现有应用程序或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

    9.3 fallback

    • 在类中定制http返回的属性
    package com.clsaa.learn.zuul.fallback;
    
    import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.client.ClientHttpResponse;
    import org.springframework.stereotype.Component;
    
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    @Component
    public class MyFallbackProvider implements ZuulFallbackProvider {
        @Override
        public String getRoute() {
            //route 如
            return "microservice-provider-user";
        }
    
        @Override
        public ClientHttpResponse fallbackResponse() {
            return new ClientHttpResponse() {
                @Override
                public HttpStatus getStatusCode() throws IOException {
                    return HttpStatus.OK;
                }
    
                @Override
                public int getRawStatusCode() throws IOException {
                    return 200;
                }
    
                @Override
                public String getStatusText() throws IOException {
                    return "OK";
                }
    
                @Override
                public void close() {
    
                }
    
                @Override
                public InputStream getBody() throws IOException {
                    return new ByteArrayInputStream(("fallback"+MyFallbackProvider.this.getRoute()).getBytes());
                }
    
                @Override
                public HttpHeaders getHeaders() {
                    HttpHeaders headers = new HttpHeaders();
                    headers.setContentType(MediaType.APPLICATION_JSON);
                    return headers;
                }
            };
        }
    }

    9.4 使用sidecar支持异构语言

    10过滤器

    10.1过滤器类型与请求生命周期

    • Zuul大部分功能都是通过过滤器来实现的。Zuul中定义了四种标准过滤器类型,这些过滤器类型对应于请求的典型生命周期。

      1. PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
      2. ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
      3. POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
      4. ERROR:在其他阶段发生错误时执行该过滤器。
      5. 除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。

    image

    10.2 编写zuul过滤器

    • 过滤器类
    package com.clsaa.learn.zuul;
    
    import com.netflix.zuul.ZuulFilter;
    import com.netflix.zuul.context.RequestContext;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    
    @Component
    public class PreZuulFilter extends ZuulFilter{
        private final static Logger LOGGER = LoggerFactory.getLogger(PreZuulFilter.class);
    
        @Override
        public String filterType() {
            return "pre";
        }
    
        @Override
        public int filterOrder() {
            return 1;//数字越大越靠后
        }
    
        @Override
        public boolean shouldFilter() {
            return true;
        }
    
        @Override
        public Object run() {
            HttpServletRequest servletRequest = RequestContext.getCurrentContext().getRequest();
            String host = servletRequest.getRemoteHost();
            PreZuulFilter.LOGGER.info("request host : " + host);
            return null;
        }
    }

    10.3 禁用过滤器

    479/5000 
    Zuul for Spring Cloud在代理和服务器模式下默认启用了一些ZuulFilter bean。 有关已启用的可能过滤器,请参阅zuul过滤器包。 如果你想禁用一个,只需设置:

    zuul.<SimpleClassName>.<filterType>.disable=true

    按照惯例,过滤器之后的包是Zuul过滤器类型。 例如,禁用

    org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter set zuul.SendResponseFilter.post.disable = true
    作者:Reno灬 出处:https://www.cnblogs.com/import-new/ 版权归作者所有,转载请注明出处
  • 相关阅读:
    基础实验7-2.2 插入排序还是堆排序 (25分)
    进阶实验6-3.1 红色警报 (25分)--并查集
    基础实验3-2.2 单链表分段逆转 (25分)--单链表
    基础实验6-2.2 汉密尔顿回路 (25分)--邻接矩阵
    案例6-1.3 哥尼斯堡的“七桥问题” (25分)--dfs图连通+度判断
    基础实验8-1.1 单身狗 (25分)
    基础实验7-2.3 德才论 (25分)--排序
    基础实验7-2.4 PAT排名汇总 (25分)--结构体排序(快排)
    进阶实验4-3.4 笛卡尔树 (25分)--二叉排序树+堆排序
    基础实验4-2.7 修理牧场 (25分)-堆+哈夫曼树
  • 原文地址:https://www.cnblogs.com/import-new/p/9110939.html
Copyright © 2020-2023  润新知