zoukankan      html  css  js  c++  java
  • 7、Spring -Cloud-路由网管Spring Cloud Zuul

    7.1、为什么需要Zuul

    Zuul 作为路由网关组件,在微服务架构中有着非常重要的作用:

     7.2、Zuul的工作原理

    Zuul 是通过 Servlet 来实现的,
    Zuul 通过自定义的 Zuu!Servlet (类似于 Spring MVC的DispatcServlet )来对请求进行控制
     
    Zuul 的核心是一系列过滤器
    可以在 Http 请求的发起和响应返回期间执行 系列的过滤器。
    包含以下四种过滤器:

     

    Zuul 采取了动态读取、编译和运行这些过滤器
    过滤器 间不能直接相互通信,通过RequestContext 对象来共享数据
    每个请求都会创建一个RequestContext 对象
    特性:

     

    请求的生命周期图:

     

    7.3、案例

    7.3.1、搭建 Zuul 服务

    新建一个项目:

     

    pom文件:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    此时需要使用到的工程:
    配置均是之前的配置:
    spring.application.name=feign
    server.port=8087
    eureka.client.service-url.defaultZone=http://localhost:8762/eureka/
    #开启Hystrix的功能
    feign.hystrix.enabled=true

    在下方配置文件的使用: 

     

    spring.application.name=hystric
    server.port=8088
    eureka.client.service-url.defaultZone=http://localhost:8762/eureka/
    #开启Hystrix的功能
    feign.hystrix.enabled=true

    在下方配置文件的使用: 

     新建工程的配置类:

    @EnableZuulProxy
    @EnableEurekaClient
    @SpringBootApplication
    public class EurekaZuulClientApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(EurekaZuulClientApplication.class, args);
        }
    }
    配置文件:
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8762/eureka/
    
    server:
      port: 5000
    spring:
      application:
        name: zuul
    
    zuul:
      routes:
        #自定义的
        ribbonapi:
          #路径
          path: /ribbonapi/**
          #引入的application(上述需要使用到的工程名)
          serviceid: hystric
    
        feignapi:
          path: /feignapi/**
          serviceid: feign
    zuul.routes.ribbonapi中的ribbonapi时自己定义的
    需要指定path和serviceId两者配合使用
    就可以将指定类型的请求url路由到制定的serviceId
    即满足/ribbonapi 开头的请求Url都会被分发到hystric 服务
    如果某个服务存在多个实例,Zul结合Ribbon会做负载均衡,将请求均分的部分路由到不同服务的实例。
     
    此时也需要进行启动上述的两个工程,分别修改器端口号进行访问测试:
    Eureka注册中心:

     
    两个服务是可以进行访问的

    此时访问:
    hi是之前的请求url

    这里会有负载均衡

     

    可见Zuul在路由转发做了负载均衡。
     
    如果不需要用 Ribbon 做负载均衡
    可以指定服务实例的 Uri
    zuul:
      routes:
        ribbonapi:
          path: /ribbonapi/**
          serviceid: hystric
          url: http://localhost:8089
    重新启动此时不会负载均衡,值会使用这个端口的进行服务!!!
     
    如果你想指定 Url 并且想做负载均衡
    那么就需要自己维护负载均衡的服务注册列表。
    首先、ribbon.eureka.enabled 改为 false 
    Ribbon 负载均衡客户端不向Eureka Client 获取服务注册列表信息
    然后需要自己维护一份注册列表
    该注册列表对应的服务名为hiapi-vl(这 名字可自定义)

    7.3.2、Zuul 上配置 API 接口的版本号

     
    若要给每个服务的API接口的加上前缀
    此时的v1就是版本号
     
    待补充.....

    7.3.3、Zuul 上配置熔断器

     
    Zuul 作为 Netflix 组件,可以和Ribbon、Eureka、Hystrix 等组件相结合,
    实现负载均衡、熔断器的功能。
     
    在默认情况下, Zuul和Ribbon相结合,实现了负载均衡的功能
     
    MyFallbackProvider.class
    package com.cr.eurekazuulclient.zull;
    
    import org.slf4j.LoggerFactory;
    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.logging.Logger;
    
    @Component
    public class MyFallbackProvider implements FallbackProvider {
    
        @Override
        public String getRoute() {
            // 表明是为哪个微服务提供回退,*表示为所有微服务提供回退
            return "hystric";
        }
    
        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("The service is unavailable.".getBytes());
                }
    
                @Override
                public HttpHeaders getHeaders() {
                    HttpHeaders headers = new HttpHeaders();
                    headers.setContentType(MediaType.APPLICATION_JSON);
                    return headers;
                }
            };
        }
    
        @Override
        public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
    
            if (cause != null && cause.getCause() != null){
                String reason = cause.getCause().getMessage();
                System.out.println("exception:" + reason);
            }
            return fallbackResponse();
        }
    }
    此时启动服务!!!
    访问hystrix的地址:
    关闭该端口的服务:
    此时的字符串是上文中的提示字符串

    重启hystrix服务:

     7.3.4、在Zuul中使用过滤器

    过滤器的类型: 

    实现过滤器自需要继承ZuulFilter,并且实现其中的抽象方法
    包括:filterType()、fil terOrder()、shouldFilter ()、Object run()
     
    filterType():过滤器类型
    filterOrder()是过滤顺序,值越小越早执行过滤器
    shouldFilter()表示该过滤器是都过滤逻辑,为true则执行run()方法,false则不执行run()方法
    run()方法写具体的过滤逻辑
     
    本次的测试请求参数是否传送token参数
    若没有传,则请求不被路由到具体的服务实例直接返回响应状态吗401
    package com.cr.eurekazuulclient.zull;
    
    import com.netflix.zuul.ZuulFilter;
    import com.netflix.zuul.context.RequestContext;
    import com.netflix.zuul.exception.ZuulException;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    import java.util.logging.Logger;
    
    @Component
    public class MyZuulFilter extends ZuulFilter {
    
        //private static Logger log= (Logger) LoggerFactory.getLogger(MyZuulFilter.class);
        @Override
        public String filterType() {
            return "pre";
        }
    
        @Override
        public int filterOrder() {
            return 1;
        }
    
        @Override
        public boolean shouldFilter() {
            return true;
        }
    
        @Override
        public Object run() throws ZuulException {
            RequestContext ctx = RequestContext.getCurrentContext();
            HttpServletRequest request = ctx.getRequest();
            Object accessToken = request.getParameter("token");
    
            if (accessToken == null){
                System.out.println("token is empty");
                //log.warning("token is empty");
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(401);
                try {
                    ctx.getResponse().getWriter().write("token is empty");
                }catch (Exception e){
                    return  null;
                }
            }
            return null;
        }
    }
    Zuul 的过滤器 ZuulFilter 的使用。
     
    注意 EnableZuulProxy 注解能注册到 eureka 服务上,是因为该注解包含了
    eureka 客户端的注解,该 EnableZuulProxy 是一个复合注解。
     
    http://localhost:8150/routes 地址可以查看该zuul微服务网关代理了多少微服务的serviceId
     
     
         * 在 zuul 中定义了四种不同生命周期的过滤器类型:
         *
         *      1、pre:可以在请求被路由之前调用;
         *
         *      2、route:在路由请求时候被调用;
         *
         *      3、post:在route和error过滤器之后被调用;
         *
         *      4、error:处理请求时发生错误时被调用;

    此时请求:

    此时加上参数token:

    MyZuulFilter这个 Bean 注入 IoC 容器之后
    对请求进行了过滤
    并在请求路由转发之前进行了逻辑判断
     
    在实际开发中,可以用此过滤器进行安全验证

    7.3.5、Zuul常见的使用方式

    Zuul 是采用了类似于 Spring MVC的DispatchServlet 来实现的
    采用的是异步阻塞模型,所以性能比 Ngnix 差
     
    由于 Zuul和其他 Netflix 组件可以相互配合、无缝集成 Zuul 很容易
    就能实现负载均衡、智能路由和熔断器等功能
     
    大多数情况下、Zuul 都是以集群的形式存在的
     
    由于Zuul的横向扩展能力非常好
    所以当负载过高时
    可以通过添加实例来解决性能瓶颈。

     

  • 相关阅读:
    Log4Net 全方位跟踪程序运行
    ASP.NET MVC 3和Razor中的@helper 语法
    C# 4.0四大新特性代码示例与解读
    程序员必读
    重学算法(1)--遍历二叉树
    重学算法-目录
    Epplus使用技巧
    JQuery 获取URL中传递的参数
    Epplus 使用案例
    .net调用存储过程详解(转载)
  • 原文地址:https://www.cnblogs.com/Mrchengs/p/10654069.html
Copyright © 2011-2022 走看看