zoukankan      html  css  js  c++  java
  • Spring Cloud Zuul 路由网关及服务过滤

    Zuul 简介

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

    引入依赖

    pom.xml 中主要添加 spring-cloud-starter-netflix-eureka-serverspring-cloud-starter-netflix-zuul 依赖

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

    相关配置

    application.yml 中主要添加 Zuul 路由配置

    zuul:
      routes:
        api-a:
          path: /api/ribbon/**
          serviceId: hello-spring-cloud-web-admin-ribbon
        api-b:
          path: /api/feign/**
          serviceId: hello-spring-cloud-web-admin-feign
    

    路由说明:

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

    Application 入口类中添加 @EnableZuulProxy 注解开启 zuul 功能

    @SpringBootApplication
    @EnableEurekaClient
    @EnableZuulProxy
    public class ZuulApplication {
        public static void main(String[] args) {
            SpringApplication.run(ZuulApplication.class, args);
        }
    }
    

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

    创建 WebAdminFeignFallbackProvider 回调类

    /**
     * 路由 hello-spring-cloud-web-admin-feign 失败时的回调
     */
    @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<String, Object> 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;
                }
            };
        }
    }
    

    测试路由访问

    依次运行 EurekaApplication > ServiceAdminApplication > WebAdminRibbonApplication > WebAdminFeignApplication > ZuulApplication 各服务

    使用 Zuul 的服务过滤功能

    Zuul 不仅仅只是路由,还有很多强大的功能。比如用在安全验证方面。

    创建服务过滤器

    /**
     * Zuul 的服务过滤演示
     */
    @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();
            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;
        }
    }
    

    测试过滤器

  • 相关阅读:
    计蒜客模拟赛D2T2 蒜头君的排序:区间逆序对(移动端点) + 树状数组
    计蒜客模拟赛D2T1 蒜头君的兔子:矩阵快速幂
    计蒜客模拟赛D1T2 蒜头君的树:树上节点之间最短距离和
    计蒜客模拟赛D1T1 蒜头君打地鼠:矩阵旋转+二维前缀和
    Cubieboard安装系统
    awk速查手册
    sed速查手册
    常用正则表达
    MySQL索引小记
    jQuery中attr和prop的区别
  • 原文地址:https://www.cnblogs.com/antoniopeng/p/12687618.html
Copyright © 2011-2022 走看看