• SpringCloud学习之zuul


    一。为什么要有网关

      我们先看一个图,如果按照consumer and server(最初的调用方式),如下所示

      这样我们要面临如下问题:

      1. 用户面临着一对N的问题既用户必须知道每个服务。随着服务的增多难免会....

      2.消费端(在这里可能是服务,也有可能为controller等),如何进行安全控制?比如说对调用者身份的验证,防止爬虫,或者限制IP在一定时间内的请求数?

      3.即便做了这些验证,那么每个消费端都要重复的编写代码?会不会造成冗余?

      那么解决这些问题,我们不妨进行改造一下:

      

      这样我们可以将一对N转成了一对一,用户只需跟网关打交道就好了,这样我们可以在网关里处理身份验证等安全性问题,何乐而不为呢

    二。SpringCloud中的zuul

      Zuul 是在云平台上提供动态路由,监控,弹性,安全等服务框架,Zuul 相当于是设备和 Netflix 流应用的 Web 网站后端所有请求的前门。同时Zuul使用一系列不同类型的过滤器,使我们能够快速,灵活地将功能应用于我们的安全服务。这些过滤器可帮助我们执行以下功能:

    • 身份验证和安全性 - 识别每个资源的身份验证要求并拒绝不符合要求的请求。

    • 洞察和监测 - 跟踪有意义的数据和统计数据,以便为我们提供准确的生产视图。

    • 动态路由 - 根据需要动态路由请求到不同的后端群集。

    • 压力测试 - 逐渐增加群集流量以衡量性能。

    • 加载Shedding - 为每种类型的请求分配容量并删除超出限制的请求。

    • 静态响应处理 - 直接在边缘建立一些响应,而不是将它们转发到内部群集

    • 多区域弹性 - 跨AWS区域的路由请求,以便扩大我们的ELB使用范围。

      1.首先我们先添加spring-cloud对zuul的依赖:

    compile('org.springframework.cloud:spring-cloud-starter-zuul')

      2.我们创建application.yml配置文件:

     

    spring:
      application:
        name: gateway-server
    server:
      port: 8080
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8000/eureka
    zuul:
      routes:
        orders:
          path: /orders/**
          #url: http://www.baidu.com
          serviceId: ORDER-SERVER
        pay:
          path: /pay/**
          serviceId: PAY-SERVER
    View Code

      3.编写启动类

    package com.zhibo.springcloud.zuul;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
    
    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableZuulProxy
    public class ZuulApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ZuulApplication.class,args);
        }
    }
    View Code

      注意@EnableZuulProxy是@EnableZuulServer的一个超集,我们可以通过源代码发现 org.springframework.cloud.netflix.zuul.ZuulProxyAutoConfiguration继承了ZuulServerAutoConfiguration

    三。 zuul中的filter

      4.1 filter(过滤器)是一个很重要的概念,它可以在真正的请求之前进行必要的业务操作,比如说验证等。那么在zuul中过滤器最核心的接口为IZuulFilter,该接口定义非常简单: 

    /*
     * Copyright 2013 Netflix, Inc.
     *
     *      Licensed under the Apache License, Version 2.0 (the "License");
     *      you may not use this file except in compliance with the License.
     *      You may obtain a copy of the License at
     *
     *          http://www.apache.org/licenses/LICENSE-2.0
     *
     *      Unless required by applicable law or agreed to in writing, software
     *      distributed under the License is distributed on an "AS IS" BASIS,
     *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *      See the License for the specific language governing permissions and
     *      limitations under the License.
     */
    package com.netflix.zuul;
    
    import com.netflix.zuul.exception.ZuulException;
    
    /**
     * BAse interface for ZuulFilters
     *
     * @author Mikey Cohen
     *         Date: 10/27/11
     *         Time: 3:03 PM
     */
    public interface IZuulFilter {
        /**
         * a "true" return from this method means that the run() method should be invoked
         *
         * @return true if the run() method should be invoked. false will not invoke the run() method
         */
        boolean shouldFilter();
    
        /**
         * if shouldFilter() is true, this method will be invoked. this method is the core method of a ZuulFilter
         *
         * @return Some arbitrary artifact may be returned. Current implementation ignores it.
         * @throws ZuulException if an error occurs during execution.
         */
        Object run() throws ZuulException;
    
    }
    View Code

      而ZuulFilter是一个实现IZuulFilter接口的抽象类,这个类在接口的基础上又添加了如下抽象方法

    /**
         * to classify a filter by type. Standard types in Zuul are "pre" for pre-routing filtering,
         * "route" for routing to an origin, "post" for post-routing filters, "error" for error handling.
         * We also support a "static" type for static responses see  StaticResponseFilter.
         * Any filterType made be created or added and run by calling FilterProcessor.runFilters(type)
         *
         * @return A String representing that type
         */
        abstract public String filterType();
    
        /**
         * filterOrder() must also be defined for a filter. Filters may have the same  filterOrder if precedence is not
         * important for a filter. filterOrders do not need to be sequential.
         *
         * @return the int order of a filter
         */
        abstract public int filterOrder();
    View Code

      我在这里简单解释一下这几个方法作用:

      filterType:定义过滤器的类型:常见的有pre(预处理阶段) post(请求原始服务之前) error(发生错误以后) route(请求原始服务之后)

      filterOrder:定义多个过滤器的优先级,值越小优先级越高

      shouldFilter:值如果为true,那么终会执行run()方法

      run : 过滤器实际上执行的内容

      4.2 RequestContext是ConcurrentMap的一个子类,这个类可以拿到HttpServletRequest与HttpServletResponse,同时这个类当中的数据可以被多个zuulFilter共享,其中有几个方法值得我们注意以下:

       getCurrentContext() 获取ThreadLocal中的RequestContext对象

       setSendZuulResponse() 如果设置为false那么将终止对原始地址的路由

       setResponseStatusCode() 设置http的状态响应码

       addZuulResponseHeader() 设置响应头,通过这个方法我们能解决响应时中文乱码问题

       setResponseBody() 设置响应体

     

      4.3 代码示例:实现用户名验证 

     

    package com.zhibo.springcloud.zuul;
    
    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;
    import com.netflix.zuul.ZuulFilter;
    import com.netflix.zuul.context.RequestContext;
    import com.netflix.zuul.exception.ZuulException;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    
    @Component
    public class ValidateUserZuulFilter extends ZuulFilter {
    
        /**
         *
         * @return
         */
        @Override
        public String filterType() {
            return "pre";
        }
    
        @Override
        public int filterOrder() {
            return 0;
        }
    
        @Override
        public boolean shouldFilter() {
            return true;
        }
    
        @Override
        public Object run() throws ZuulException {
            RequestContext requestContext = RequestContext.getCurrentContext();
            HttpServletRequest request = requestContext.getRequest();
            String loginName = request.getParameter("loginName");
            if (loginName == null || !"admin".equals(loginName)) {
                requestContext.setSendZuulResponse(false);
                requestContext.setResponseStatusCode(500);
                Gson gson = new GsonBuilder().create();
                requestContext.addZuulResponseHeader("content-type", "application/json;charset=utf-8");
                requestContext.setResponseBody(gson.toJson(new ResponseEntity("没有登录名", HttpStatus.CONFLICT)));
                return null;
            }
            return null;
        }
    }
    View Code

     

    四。zuul中超时的设置总结

      在这篇文章里已经很详细的说明了,请大家参考:周立的Springcloud超时总结

  • 相关阅读:
    JS保留两位小数
    xml,json,html格式化工具
    SQL查询递归
    javascript验证价格输入
    类库说明文档生成器
    转换数据库时间字段格式函数
    mysql python 汉字乱码的解决方案
    Python list 按元素属性排序, key 的用法
    原以为会不同的
    libsvm 文本分类(分两类)(实验结果)直接调用Libsvm工具
  • 原文地址:https://www.cnblogs.com/niechen/p/8563319.html
Copyright © 2020-2023  润新知