SpringCloud(Hoxton.SR3)基础篇:第八章、SpringCloud之Zuul网关原理及其配置

简介:

  Zuul是spring cloud中的微服务网关。网关: 是一个网络整体系统中的前置门户入口。请求首先通过网关,进行路径的路由,定位到具体的服务节点上。

  Zuul是一个微服务网关,首先是一个微服务。也是会在Eureka注册中心中进行服务的注册和发现。也是一个网关,请求应该通过Zuul来进行路由。

  Zuul网关不是必要的。是推荐使用的。

  使用Zuul,一般在微服务数量较多(多于10个)的时候推荐使用,对服务的管理有严格要求的时候推荐使用,当微服务权限要求严格的时候推荐使用。

一、Zuul网关的作用

  Zuul可以通过加载动态过滤机制,从而实现以下各项功能:

  1.验证与安全保障: 识别面向各类资源的验证要求并拒绝那些与要求不符的请求。

  2.审查与监控: 在边缘位置追踪有意义数据及统计结果,从而为我们带来准确的生产状态结论。

  3.动态路由: 以动态方式根据需要将请求路由至不同后端集群处。

  4.压力测试: 逐渐增加指向集群的负载流量,从而计算性能水平。

  5.负载分配: 为每一种负载类型分配对应容量,并弃用超出限定值的请求。

  6.静态响应处理: 在边缘位置直接建立部分响应,从而避免其流入内部集群。

  7.多区域弹性: 跨越AWS区域进行请求路由,旨在实现ELB使用多样化并保证边缘位置与使用者尽可能接近。

 

二、Zuul网关的应用

1、网关访问方式

  通过zuul访问服务的,URL地址默认格式为:http://zuulHostIp:port/要访问的服务名称/服务中的URL

  服务名称:properties配置文件中的spring.application.name。

  服务的URL:就是对应的服务对外提供的URL路径监听。

2、网关依赖注入

<!-- zuul相关引用 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<!-- eureka客户端端依赖jar包 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

 

3、网关启动器

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

/**
 * @EnableZuulProxy - 开启Zuul网关。
 *  当前应用是一个Zuul微服务网关。会在Eureka注册中心中注册当前服务。并发现其他的服务。
 *  Zuul需要的必要依赖是spring-cloud-starter-netflix-zuul。
 */
@SpringBootApplication
//zuul代理注解
@EnableZuulProxy
public class ZuulApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZuulApplication.class, args);
    }
}

4、网关全局变量配置

  4.1 application.yml配置

spring:
   application:
      name: springcloud-gateway-zuul
server:
   port: 8040
#eureka客户端连接配置
eureka:
   client:
      service-url:
         #注册中心地址
         defaultZone: http://user:password123@localhost:8761/eureka/
   instance:
      #将ip注册到eureka上
      prefer-ip-address: true

 

  4.2 URL路径匹配

 

#zuul配置
#1.zuul默认从eureka读取全部注册微服务services并进行代理访问,默认示例:http://localhost:8040/provider-user/simple/3
zuul:
   #zuul代理路由配置
   routes:
      #主键标志用来保持唯一,可以改成abc
      user:
         #zuul代理服务路径  
         path: /user-url/**
         url: http://localhost:7900/

  

  4.3 服务名称匹配

#zuul配置
#1.zuul默认从eureka读取全部注册微服务services并进行代理访问,默认示例:http://localhost:8040/provider-user/simple/3
zuul:
   #zuul代理路由配置
   routes:
      #主键标志用来保持唯一,可以改成abc
      user:
         #zuul代理服务路径
         # 一、/* 只能访问一层路径  比如   user-path/simple  
         # 二、/** 可以访问子路径 比如 user-path/simple/1
         path: /user-path/**
         #eureka注册服务id
         service-id: provider-user

 

  4.4 路由排除配置

#zuul配置
#1.zuul默认从eureka读取全部注册微服务services并进行代理访问,默认示例:http://localhost:8040/provider-user/simple/3
zuul:
   #zuul忽略代理的,表示禁用默认路由,只认我们自己配置的路由.
   ignoredServices: '*'
   #zuul代理路由配置
   routes:
      provider-user: /user/**

  

  4.5 路由前缀配置

#zuul配置
#1.zuul默认从eureka读取全部注册微服务services并进行代理访问,默认示例:http://localhost:8040/provider-user/simple/3
zuul:
   #前缀,当请求匹配前缀时会进行代理
   prefix: /simple
   #代理前缀默认会从请求路径中移除,通过该设置关闭移除功能
   strip-prefix: false
logging:
  level:
    com.netflix: DEBUG

  例:

  当 strip-prefix=true 的时 (会移除)
  (http://127.0.0.1:8040/api/provider-user/simple/3 -> http://192.168.1.100:7900/simple/3)
  当 strip-prefix=false的时(不会移除)
  (http://127.0.0.1:8040/api/provider-user/simple/3 -> http://192.168.1.100:7900/api/simple/3)

 

 postman测试结果(通过网关请求服务提供者):

 

 

 

三、Zuul网关过滤器

  1)过滤器实现方式

  Zuul中提供了过滤器定义,可以用来过滤代理请求,提供额外功能逻辑。如:权限验证,日志记录等。

  Zuul提供的过滤器是一个父类。父类是ZuulFilter。通过父类中定义的抽象方法filterType,来决定当前的Filter种类是什么。有前置过滤、路由后过滤、后置过滤、异常过滤。

  • 前置过滤(pre):前置过滤器,在请求被路由前执行,通常用于处理身份认证,日志记录等;
  • 路由后过滤(route):在路由执行后,服务调用前被调用;
  • 后置过滤(post): 在route或error执行后被调用,一般用于收集服务信息,统计服务性能指标等,也可以对response结果做特殊处理。
  • 异常过滤(error)任意一个filter发生异常的时候执行或远程服务调用没有反馈的时候执行(超时),通常用于处理异常;

  2)过滤器的生命周期

 

 

   3)代码示例

 

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;

public class PreZuulFilter extends ZuulFilter{
    
    private static final Logger LOGGER = LoggerFactory.getLogger(PreZuulFilter.class);
    /**
     * 表示是否使用该过滤器
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }
    
    /**
     * 具体的过滤执行逻辑
     */
    @Override
    public Object run() throws ZuulException {
        HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
        String host = request.getRemoteHost();
        PreZuulFilter.LOGGER.info("请求的host:{}", host);
        return null;
    }
    
    /**
     * 过滤器类型
     * 
     */
    @Override
    public String filterType() {
        // TODO Auto-generated method stub
        return "pre";
    }
    
    /**
     * 过滤器执行顺序。返回值越小,执行顺序越优先。
     */
    @Override
    public int filterOrder() {
        // TODO Auto-generated method stub
        return 1;
    }

}

 

 

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;

import com.qxj.cloud.filter.PreZuulFilter;

@SpringBootApplication
//zuul代理注解
@EnableZuulProxy
public class ZuulApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZuulApplication.class, args);
    }
    
    /**
     * 将过滤器交给Spring管理
     * @return
     */
    @Bean
    public PreZuulFilter preZuulFilter() {
        return new PreZuulFilter();
    }
}

四、Zuul的Fallback回退机制

  默认情况下,经过Zuul的请求都会使用Hystrix进行包裹,所以Zuul本身就具有断路器的功能。

  代码示例如下:

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

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;

/**
 * FallbackProvider实现类
 */
@Component
public class MyFallbackProvider implements FallbackProvider {
    
    /**
     * 表明是为哪个微服务提供回退,*表示为所有微服务提供回退
     */
    @Override
    public String getRoute() {
        return "provider-user";
    }
    
    /**
     * fallback逻辑。
     */
    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        System.out.println("route:" + route);
        System.out.println("exception:" + cause.getMessage());
        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("oooops!error,i'm the fallback.".getBytes());
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                return headers;
            }
        };
    }

}

  停止provider微服务。Postman执行测试结果

 

 

参考文献:

https://www.cnblogs.com/jing99/p/11696192.html

https://www.cnblogs.com/huangjuncong/p/9060984.html

posted @ 2020-06-14 22:41  圣痕道心  阅读(599)  评论(0编辑  收藏  举报