• Zuul


    学习笔记

    作用api网关,路由转发,过滤器,负载均衡等多种作用

    简介:类似Nginx,反向代理的功能,不过netflix自己增加了一些配合其他组件的特性。在微服务架构中,后端服务往往不直接开放给调用端,而是通过一个API网关根据请求的url,路由到相应的服务。当添加API网关后,在第三方调用端和服务提供方之间就创建了一面墙,这面墙直接与调用方通信进行权限控制,后将请求均衡分发给后台服务器。

     

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

    Zuul与Nginx区别

    相同点:Zuul和Nginx都可以实现负载均衡、反向代理、过滤请求、实现网关效果。

    不同点

    Zuul采用java语言编写,采用ribbon+eureka实现本地负载均衡,适合微服务中实现网关。

    Nginx采用C语言编写,采用微服务端实现负载均衡,适合于服务端负载均衡,也可以实现网关。Nginx比Zuul功能会更加强大,因为Nginx整合一些脚本语言(Nginx+Lua)。

    (建议nginx+zuul实现网关,nginx作用实现反向代理,zuul对微服务实现网关拦截。)

     

    创建路由网关

    pom.xml

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.8.RELEASE</version>
      </parent>
      
      <!-- 管理依赖 -->
      <dependencyManagement>
          <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
          </dependencies>
      </dependencyManagement>
      
      <dependencies>
        <!-- SpringCloud eureka-server -->
        <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>
      </dependencies>
      
      <!-- 注意:这里必须要添加,否则各种依赖有问题 -->
      <repositories>
          <repository>
              <id>spring-milestones</id>
              <name>Spring Milestones</name>
              <url>https://repo.spring.io/libs-milestone</url>
              <snapshots>
                  <enabled>false</enabled>
              </snapshots>
          </repository>
      </repositories>

    启动类增加 @EnableZuulProxy 注解开启 Zuul 功能

    application.yml

    spring:
      application:
        name: mobileshop-zuul
    
    server:
      port: 8771
    
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/
    
    zuul:
      routes:
        api-seller:
          path: /api/seller/**
          serviceId: mobileshop-api-seller-feign

    路由说明:以 /api/seller 开头的请求都转发给 moblieshop-api-seller-feign 服务

    测试访问:

     

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

    @Component
    public class ApiSellerFeignbackProvider implements FallbackProvider {
        @Override
        public String getRoute() {
            return "mobileshop-api-seller-feign";
        }
    
        @Override
        public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
            return new ClientHttpResponse() {
                /**
                 * 网关向 api 服务请求失败了,但是消费者客户端向网关发起的请求是成功的,
                 * 不应该把 api 的 404,500 等问题抛给客户端
                 * 网关和 api 服务集群对于客户端来说是黑盒
                 */
                @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;
                }
            };
        }
    }

    测试

    创建服务过滤器

    @Component
    public class LoginFilter extends ZuulFilter {
        private static final Logger logger = LoggerFactory.getLogger(LoginFilter.class);
        /**
         * 配置过滤类型,有四种不同生命周期的过滤器类型
         * 1. pre:路由之前
         * 2. routing:路由之时
         * 3. post:路由之后
         * 4. error:发送错误调用
         */
        @Override
        public String filterType() {
            return "pre";
        }
        /**
         * 配置过滤的顺序
         */
        @Override
        public int filterOrder() {
            return 0;
        }
        /**
         * 配置是否需要过滤:true/需要,false/不需要
         */
        @Override
        public boolean shouldFilter() {
            return true;
        }
        /**
         * 过滤器的具体业务代码
         */
        @Override
        public Object run() throws ZuulException {
            RequestContext context = RequestContext.getCurrentContext();
            HttpServletRequest request = context.getRequest();
            String token = request.getParameter("token");
            if (token == null) {
                context.setSendZuulResponse(false);
                context.setResponseStatusCode(401);
                try {
                    HttpServletResponse response = context.getResponse();
                    response.setContentType("text/html;charset=utf-8");
                    context.getResponse().getWriter().write("非法请求");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }
    }

    测试过滤器

  • 相关阅读:
    vue
    Html5的本地储存 Web Storage
    java json解析(转)
    Python常用字符编码(转)
    特殊符号集锦(转)
    neo4j性能调优(转)
    hadoop fs -text和hadoop fs -cat的区别(转)
    docker和dockerfile极简入门(转)
    docker原理(转)
    neo4j配置(转)
  • 原文地址:https://www.cnblogs.com/tripleDemo/p/11649966.html
Copyright © 2020-2023  润新知