Spring Cloud Netflix-微服务网关(Zuul)



前言

以下类容来自书籍《Spring Cloud与Docker微服务架构实战(第2版)》


简介

在这里插入图片描述

上图中,一个功能客户端可能需要调用好几次下级服务,每个下级服务需要独立的认证,当某个服务部署在内网时,访问也较为困难。

在这里插入图片描述
微服务网关是介于客户端和服务端之间的中间层,所有外部请求会先经过网关。这样各服务提供者在后期因需求变动时,客户端无需关心,简化了开发。监控和认证也可在网关中进行。

NetFlix的服务网关是Zuul,可以和Eureka、Ribbon、Hystrix配合使用。Zuul的过滤器可完成一下功能:身份认证与安全、监控、动态路由、压力测试、负载均衡、静态响应处理(边缘位置建立部分响应,从而避免其转发到内部集群。)、多区域弹性(不懂)。

Zuul网关搭建

    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>
server:
  port: 8040
spring:
  application:
    name: microservice-gateway-zuul
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
management:
  security:
    enabled: false
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
  public static void main(String[] args) {
    SpringApplication.run(ZuulApplication.class, args);
  }
}

将网关服务注册到Eureka上,启动Eureka、服务提供者、服务消费者、Zuul网关服务。
此时访问http://localhost:8040/microservice-consumer-movie/user/1,服务网关会根据serviceId将请求转发到对应的服务,转发到http://localhost:8081/user/1。当然,在转发的同时也支持负载均衡。

Zuul的过滤器

在这里插入图片描述

过滤器是是Zuul的核心组件,大部分功能就是通过过滤器来实现的。

过滤器类型

  • PRE:请求被路由之前被调用,可实现身份验证,集群情况下选择微服务,记录调试信息。
  • ROUTING:将请求路由到微服务,用于构建发送给微服务的请求,并使用Apache HttpClient或Netflix Ribbon请求微服务。
  • POST:在路由到微服务以后执行,用来响应添加标准的HTTP Header、收集统计信息和指标,将响应从微服务发送给客户端。
  • Error:在其他阶段发生错误时执行

编写过滤器

PRE过滤器

public class PreRequestLogFilter extends ZuulFilter {
  private static final Logger LOGGER = LoggerFactory.getLogger(PreRequestLogFilter.class);

  @Override
  public String filterType() {
  //PRE类型的过滤器
    return FilterConstants.PRE_TYPE;
  }

  @Override
  public int filterOrder() {
  //在org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter之前执行
    return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
  }

  @Override
  public boolean shouldFilter() {
    return true;
  }

  @Override
  public Object run() {
    RequestContext ctx = RequestContext.getCurrentContext();
    HttpServletRequest request = ctx.getRequest();
    PreRequestLogFilter.LOGGER.info(String.format("send %s request to %s  ctx.getResponseBody()  %s", request.getMethod(), request.getRequestURL().toString(),ctx.getResponseBody()));
    return null;
  }
}
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
  public static void main(String[] args) {
    SpringApplication.run(ZuulApplication.class, args);
  }

  @Bean
  public PreRequestLogFilter preRequestLogFilter() {
    return new PreRequestLogFilter();
  }
 }

访问http://localhost:8040/microservice-provider-user/1,可看到PRE过滤器生效
在这里插入图片描述

POST过滤器

public class ResponseFilter extends ZuulFilter {

    private static final Logger LOGGER = LoggerFactory.getLogger(ResponseFilter.class);

    @Override
    public Object run() {

        RequestContext context = RequestContext.getCurrentContext();

        try {
            // 获取返回值内容,加以处理
            InputStream stream = context.getResponseDataStream();
            String body = StreamUtils.copyToString(stream, Charset.forName("UTF-8"));
            ResponseFilter.LOGGER.info(String.format("ResponsebBody %s", body));

            String returnStr = "哎呀,我被改掉了!";


            //你的处理逻辑,加密,添加新的返回值等等.....


            // 内容重新写入
            context.setResponseBody(returnStr);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();

        String requestURI = String.valueOf(ctx.get("requestURI"));

        if (requestURI.contains("test")) {
            //不需要处理的URL请求,返回false
            return false;
        }


        return true;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 3;
    }

    @Override
    public String filterType() {
        return FilterConstants.POST_TYPE;// 在请求被处理之后,会进入该过滤器
    }

}
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
  public static void main(String[] args) {
    SpringApplication.run(ZuulApplication.class, args);
  }

  @Bean
  public PreRequestLogFilter preRequestLogFilter() {
    return new PreRequestLogFilter();
  }

  @Bean
  public ResponseFilter responseFilter() {
    return new ResponseFilter();
  }
}

请求后可看到,我们可以获取并改变返回值
在这里插入图片描述
在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值