• ZULL图解+代码 ZuulFilter执行顺序


    使用路由网关统一访问接口概述

    在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现、服务消费、负载均衡、熔断器、智能路由、配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统。一个简单的微服务系统如下图:
    在这里插入图片描述

    在 Spring Cloud 微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(Zuul、Ngnix),再到达服务网关(Zuul 集群),然后再到具体的服。服务统一注册到高可用的服务注册中心集群,服务的所有的配置文件由配置服务管理,配置服务的配置文件放在 GIT 仓库,方便开发人员随时改配置。

    Zuul 简介

    Zuul 的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如 /api/user 转发到到 User 服务,/api/shop 转发到到 Shop 服务。Zuul 默认和 Ribbon 结合实现了负载均衡的功能。

    spring Boot 搭载 Zuul

    1.创建路由网关

    pom.xml 文件如下:

    
    
        4.0.0
    
        
            com.funtl
            hello-spring-cloud-dependencies
            1.0.0-SNAPSHOT
            ../hello-spring-cloud-dependencies/pom.xml
        
    
        hello-spring-cloud-zuul
        jar
    
        hello-spring-cloud-zuul
        http://www.8888.com
        2018-Now
    
        
            
            
                org.springframework.boot
                spring-boot-starter-web
            
            
                org.springframework.boot
                spring-boot-starter-tomcat
            
            
                org.springframework.boot
                spring-boot-starter-actuator
            
            
                org.springframework.boot
                spring-boot-starter-test
                test
            
            
    
            
            
                org.springframework.cloud
                spring-cloud-starter-netflix-eureka-server
            
            
                org.springframework.cloud
                spring-cloud-starter-netflix-zuul
            
            
        
    
        
            
                
                    org.springframework.boot
                    spring-boot-maven-plugin
                    
                        com.funtl.hello.spring.cloud.zuul.ZuulApplication
                    
                
            
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    主要是增加了 Zuul 的依赖

    
        org.springframework.cloud
        spring-cloud-starter-netflix-zuul
    
    
    • 1
    • 2
    • 3
    • 4

    2.Application

    增加 @EnableZuulProxy 注解开启 Zuul 功能

    package com.funtl.hello.spring.cloud.zuul;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
    
    @SpringBootApplication
    @EnableEurekaClient
    @EnableZuulProxy
    public class ZuulApplication {
        public static void main(String[] args) {
            SpringApplication.run(ZuulApplication.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    3.application.yml

    • 设置端口号为:8769
    • 增加 Zuul 配置
    spring:
      application:
        name: hello-spring-cloud-zuul
    
    server:
      port: 8769
    
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/
    
    zuul:
      routes:
        api-a:
          path: /api/a/**
          serviceId: hello-spring-cloud-web-admin-ribbon
        api-b:
          path: /api/b/**
          serviceId: hello-spring-cloud-web-admin-feign
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    路由说明:

    • 以 /api/a 开头的请求都转发给 hello-spring-cloud-web-admin-ribbon 服务
    • 以 /api/b 开头的请求都转发给 hello-spring-cloud-web-admin-feign 服务

    测试访问

    依次运行 EurekaApplicationServiceAdminApplicationWebAdminRibbonApplicationWebAdminFeignApplicationZuulApplication

    打开浏览器访问:http://localhost:8769/api/a/hi?message=HelloZuul 浏览器显示

    Hi,your message is :"HelloZuul" i am from port:8763
    
    • 1

    打开浏览器访问:http://localhost:8769/api/b/hi?message=HelloZuul 浏览器显示

    Hi,your message is :"HelloZuul" i am from port:8763
    
    • 1

    至此说明 Zuul 的路由功能配置成功

    配置网关路由失败时的回调

    package com.funtl.hello.spring.cloud.zuul.fallback;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
    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;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 路由 hello-spring-cloud-web-admin-feign 失败时的回调
     * 

    Title: WebAdminFeignFallbackProvider

    *

    Description:

    * * @author Lusifer * @version 1.0.0 * @date 2018/7/27 6:55 */ @Component public class WebAdminFeignFallbackProvider implements FallbackProvider { @Override public String getRoute() { // ServiceId,如果需要所有调用都支持回退,则 return "*" 或 return null return "hello-spring-cloud-web-admin-feign"; } /** * 如果请求服务失败,则返回指定的信息给调用者 * @param route * @param cause * @return */ @Override public ClientHttpResponse fallbackResponse(String route, Throwable cause) { return new ClientHttpResponse() { /** * 网关向 api 服务请求失败了,但是消费者客户端向网关发起的请求是成功的, * 不应该把 api 的 404,500 等问题抛给客户端 * 网关和 api 服务集群对于客户端来说是黑盒 * @return * @throws IOException */ @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() { } @Override public InputStream getBody() throws IOException { ObjectMapper objectMapper = new ObjectMapper(); Map map = new HashMap<>(); map.put("status", 200); map.put("message", "无法连接,请检查您的网络"); return new ByteArrayInputStream(objectMapper.writeValueAsString(map).getBytes("UTF-8")); } @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); // 和 getBody 中的内容编码一致 headers.setContentType(MediaType.APPLICATION_JSON_UTF8); return headers; } }; } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89

    ZuulFilter执行顺序 使用路由网关的服务过滤功能

    概述

    Zuul 不仅仅只是路由,还有很多强大的功能,本节演示一下它的服务过滤功能,比如用在安全验证方面。

    创建服务过滤器

    继承 ZuulFilter 类并在类上增加 @Component 注解就可以使用服务过滤功能了,非常简单方便

    ZuulFilter的执行顺序

    在这里插入图片描述

    filterType

    返回一个字符串代表过滤器的类型,在 Zuul 中定义了四种不同生命周期的过滤器类型

    • pre:路由之前
    • routing:路由之时
    • post: 路由之后
    • error:发送错误调用

    filterOrder

    过滤的顺序

    shouldFilter

    是否需要过滤,这里是 true,需要过滤

    run

    过滤器的具体业务代码 代码示例

    package com.zaofeng.springcloud.ZuulApplication.filter 中

    package com.funtl.hello.spring.cloud.zuul.filter;
    
    import com.netflix.zuul.ZuulFilter;
    import com.netflix.zuul.context.RequestContext;
    import com.netflix.zuul.exception.ZuulException;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    
    /**
     * Zuul 的服务过滤演示
     * 

    Title: LoginFilter

    *

    Description:

    * * @author Lusifer * @version 1.0.0 * @date 2018/5/29 22:02 */ @Component public class LoginFilter extends ZuulFilter { private static final Logger logger = LoggerFactory.getLogger(LoginFilter.class); /** * 配置过滤类型,有四种不同生命周期的过滤器类型 * 1. pre:路由之前 * 2. routing:路由之时 * 3. post:路由之后 * 4. error:发送错误调用 * @return */ @Override public String filterType() { return "pre"; } /** * 配置过滤的顺序 * @return */ @Override public int filterOrder() { return 0; } /** * 配置是否需要过滤:true/需要,false/不需要 * @return */ @Override public boolean shouldFilter() { return true; } /** * 过滤器的具体业务代码 * @return * @throws ZuulException */ @Override public Object run() throws ZuulException { RequestContext context = RequestContext.getCurrentContext(); HttpServletRequest request = context.getRequest(); logger.info("{} >>> {}", request.getMethod(), request.getRequestURL().toString()); String token = request.getParameter("token"); if (token == null) { logger.warn("Token is empty"); context.setSendZuulResponse(false); context.setResponseStatusCode(401); try { context.getResponse().getWriter().write("Token is empty"); } catch (IOException e) { } } else { logger.info("OK"); } return null; } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

    测试过滤器

    浏览器访问:http://localhost:8769/api/a/hi?message=HelloZuul 网页显示

    Token is empty
    
    • 1

    浏览器访问:http://localhost:8769/api/b/hi?message=HelloZuul&token=123 网页显示

    Hi,your message is :"HelloZuul" i am from port:8763
    
    • 1
  • 相关阅读:
    fastadmin如何让后台的日期显示成年月日格式
    【Linux入门指北】Linux磁盘扩容
    电池集成充电解决方案提供商【XCharge Group】获得壳牌风险投资
    java虚拟机垃圾回收相关概念
    Minio分布式集群部署(Swarm)
    一分钟get✔一个文献阅读的最核心技巧(用的是小绿鲸文献阅读器)
    vue3 watch & watchEffect
    J2EE项目部署与发布(Windows版本)
    练习推导一个最简单的BP神经网络训练过程【个人作业/数学推导】
    设计模式解析之模板方法模式:设计灵活可扩展的算法框架
  • 原文地址:https://blog.csdn.net/weixin_44684812/article/details/126663051