SpringCloudNetflix(四) 网关 Zuul

Zuul是什么

Zuul 即微服务网关,主要有两个功能

  1. 请求路由,也可以说请求转发
  2. 请求过滤

通过路由(将外部请求转发到具体的微服务实例上),完成微服务统一入口。

过滤器则负责对请求进行处理,比如请求校验等

Zuul的使用

Zuul需要和Eureka配合使用,Zuul将自身注册到Eureka服务治理中,在能够获取其他微服务的信息时,还能够保障自身的高可用。

  1. 新建Zuul模块
  2. pom.xml引入依赖
<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>
  1. 修改application.yml
server:
  port: 9000

spring:
  application:
    name: zuul

eureka:
  client:
    serviceUrl:
      # 随机找到一台注册,而不是三台一起注册,注册成功就不注册了
      defaultZone: http://eureka001:8761/eureka/

  instance:
    #    statusPageUrlPath: ${server.servletPath}/info
    #    healthCheckUrlPath: ${server.servletPath}/health
    instance-id: zuul #此实例注册到eureka服务端的唯一的实例ID
    prefer-ip-address: true  #是否显示IP地址
    leaseRenewalIntervalInSeconds: 10 #eureka客户需要多长时间发送心跳给eureka服务器,表明它仍然活着,默认为30 秒 (与下面配置的单位都是秒)
    leaseExpirationDurationInSeconds: 30 #Eureka服务器在接收到实例的最后一次发出的心跳后,需要等待多久才可以将此实例删除,默认为90秒

# 配置路由
zuul:
  prefix: /api
  ignored-services: "*"
  strip-prefix: false # 默认为true,如需要保留/client则需要修改为false, 也可以单独给某个服务配置
  routes:
    myconsumer:
      serviceId: eureka-consumer
      path: /client/**
    myproduct:
      serviceId: eureka-product
      path: /product/**    # /* 只有一层, /product/select能到,/product/xxx/select就不行

  1. 启动类加上@EnableZuulProxy或者@EnableZuulServer
@SpringBootApplication
@EnableZuulProxy
public class AppZuul {
    public static void main(String[] args) {
        SpringApplication.run(AppZuul.class);
    }
}

@EnableZuulServer和@EnableZuulProxy的区别

官网解释:Spring Cloud Netflix installs a number of filters, depending on which annotation was used to enable Zuul. @EnableZuulProxy is a superset of @EnableZuulServer. In other words, @EnableZuulProxy contains all the filters installed by @EnableZuulServer. The additional filters in the “proxy” enable routing functionality. If you want a “blank” Zuul, you should use @EnableZuulServer.

简单来说Spring Cloud Netflix安装了许多过滤器,而@EnableZuulProxy@EnableZuulServer的超集,@EnableZuulProxy 包含 @EnableZuulServer的所有过滤器。如何抉择,需要看你是否需要启用附加的过滤器。

具体可以参考官网:https://docs.spring.io/spring-cloud-netflix/docs/2.2.8.RELEASE/reference/html/#router-and-filter-zuul 9.18.4 - 9.18.5

或者博客:https://juejin.cn/post/6844903992183488520

路由

路由配置:

zuul:
  prefix: /api
  ignored-services: "*"  #禁止微服务名调用,避免多重地址
  strip-prefix: false # 默认为true,如需要保留/client则需要修改为false, 也可以单独给某个服务配置
  routes:
    myconsumer:
      serviceId: eureka-consumer
      path: /client/**
    myproduct:
      serviceId: eureka-product
      path: /product/**    # /* 只有一层, /product/select能到,/product/xxx/select就不行

过滤器

类型触发时机使用场景
PRE在请求被路由之前调用身份验证、记录调试信息等
ROUTING在请求被路由之后构建发送给微服务的请求
POST微服务执行之后收集统计信息和指标
ERROR发生错误时错误日志

触发时机图:

在这里插入图片描述

过滤器如何使用:

@Component
public class LogFilter extends ZuulFilter {
    @Override
    public String filterType() {
      	//过滤器的类型
        return FilterConstants.PRE_TYPE;
    }
    @Override
    public int filterOrder() {
        // 过滤器优先级  数字越小优先级越高
        return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1;
    }
    @Override
    public boolean shouldFilter() {
      //shouldFilter:返回一个 boolean值来判断该过滤器是否要执行, true表示执行, false表示不执行。
        return true ;
    }
    @Override
    public Object run() throws ZuulException {
      	//run:过滤器的具体逻辑。
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
        String remoteAddr = request.getRemoteAddr();
        System.out.println("访问者IP:"+remoteAddr+"访问地址:"+request.getRequestURI());
        return null;
    }
}

Zuul 容错和回退

Zuul默认已经整合了Hystrix和Ribbon

如何进行降级

// 官方Demo
class MyFallbackProvider implements FallbackProvider {
    @Override
    public String getRoute() {
      // 声明哪个微服务进行降级回退  return *则对所有服务进行降级
        return "customers";
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, final Throwable cause) {
        if (cause instanceof HystrixTimeoutException) {
            return response(HttpStatus.GATEWAY_TIMEOUT);
        } else {
            return response(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    private ClientHttpResponse response(final HttpStatus status) {
      //这里返回一个ClientHttpResponse对象 并实现其中的方法,关于回退逻辑的详细,便在下面的方法中
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
              //返回一个HttpStatus对象 这个对象是个枚举对象, 里面包含了一个status code 和reasonPhrase信息 
                return status;
            }
            @Override
            public int getRawStatusCode() throws IOException {
              	//返回status的code 比如 404,500等
                return status.value();
            }
            @Override
            public String getStatusText() throws IOException {
              	//返回一个HttpStatus对象的reasonPhrase信息
                return status.getReasonPhrase();
            }
            @Override
            public void close() {
              //降级信息响应之后调用的方法
            }
            @Override
            public InputStream getBody() throws IOException {
             		//把降级信息响应回前端
                return new ByteArrayInputStream("fallback".getBytes());
            }
            @Override
            public HttpHeaders getHeaders() {
             		//需要对响应报头设置的话可以在此设置
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                return headers;
            }
        };
    }
}

Zuul 高可用的实现方式

Zuul怎么来实现高可用呢,这里需要分不同的情况

  1. 同一注册中心,服务间调用,这里之间可以使用Ribbon即可(Zuul就相当于其中的注册中心的服务)。

在这里插入图片描述

  1. 不同注册中心,或者说不同微服务体系,甚至,单体架构,如何进行调用?

在这里插入图片描述

这种情况同样有很多选择,需要根据内部情况来抉择

  1. Nginx代理,一般来说公司都会有Nginx集群,这里可以直接使用Nginx来代理即可。
  2. HA代理,Haproxy同样可以实现。但HA同样需要集群搭建。
  3. vip,通过vip漂移应该也可以实现。

这里只是提出方案,就不具体写出配置了。

Zuul 如何实现动态路由

Zuul 动态路由:https://blog.csdn.net/qq_20112609/article/details/84539747

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值