Spring Cloud微服务解决方案⑧:Zuul(API网关)

简单的来说,我们把zuul这个项目启动起来,注册到eurake上,那么他就可以代理eurake上面的服务(默认),各种玩法听我细细道来。

源码下载路径在:https://download.csdn.net/download/qq_22075041/10869452,代码参考microservice-gateway-zuul模块。

首先加入zuul的依赖

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<!--需要eurake的client依赖,因为要注册到eurake上-->
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

启动类上加一个注解@EnableZuulProxy,配置文件只需要把注册到eurake的配置做一下就可以了:

server:
  port: 8040
spring:
  application:
    name: microservice-gateway-zuul
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true

以上配置zuul默认代理eurake的所有服务,调用的时候以注册到eurake上的服务名。

但是我觉得服务名太长了不好记,我要自定义,配置如下:

zuul:
  routes:
  # 服务名 访问路径  注意/*和/**的区别:适配一层和适配多层
    microservice-provider-user: /user/** 

如果我要忽略某几个微服务的代理呢?这样配(多个用逗号分开):

zuul:
  ignored-services: microservice-provider-user,microservice-consumer-movie

如果我只想代理指定的微服务呢?

zuul:
  ignored-services: '*'   # 使用'*'可忽略所有微服务
  routes:
    microservice-provider-user: /user/**

还可以这样玩:同时指定微服务的serviceId和对应路径path:

zuul:
  routes:
    abc:                   # 该配置方式中,abc只是给路由一个名称,可以任意起名。
      service-id: microservice-provider-user
      path: /user/**              # service-id对应的路径

玩法2:同时指定path和url

zuul:
  routes:
    user-route:                   # 该配置方式中,user-route只是给路由一个名称,可以任意起名。
      url: http://localhost:8000/ # 指定的url
      path: /user/**              # url对应的路径。

玩法2升级:同时指定path和URL,并且不破坏Zuul的Hystrix、Ribbon特性

zuul:
  routes:
    user-route:
      path: /user/**
      service-id: microservice-provider-user
ribbon:
  eureka:
    enabled: false    # 禁用掉ribbon的eureka使用。详见:http://cloud.spring.io/spring-cloud-static/Camden.SR3/#_example_disable_eureka_use_in_ribbon
microservice-provider-user:
  ribbon:
    listOfServers: localhost:8000,localhost:8001

为Zuul添加全局映射前缀: 应用场景比如项目根目录不是/ 而是/abc之类的

zuul:
  prefix: /api
  strip-prefix: false # 默认为ture
  routes:
    microservice-provider-user: /user/**
logging:
  level:
    com.netflix: DEBUG
    
# 访问Zuul的/api/microservice-provider-user/1路径,请求将会被转发到microservice-provider-user的/api/1,,可以查看日志打印,有助于理解。

为Zuul添加局部映射前缀,就是给某个服务添加:

zuul:
  routes:
    microservice-provider-user: 
      path: /user/**
      strip-prefix: false
logging:
  level:
    com.netflix: DEBUG
    
# 这样访问Zuul的/user/1路径,请求将会被转发到microservice-provider-user的/user/1,可以查看日志打印,有助于理解。

我要忽略某些敏感路径,这样配:

zuul:
  ignoredPatterns: /**/admin/**   # 忽略所有包括/admin/的路径
  routes:
    microservice-provider-user: /user/**

还有基于正则的玩法,削微有点不同,代码参考microservice-gateway-zuul-reg-exp模块:

@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {

  @Bean
  public PatternServiceRouteMapper serviceRouteMapper() {
    // 调用构造函数PatternServiceRouteMapper(String servicePattern, String routePattern)
    // servicePattern指定微服务的正则
    // routePattern指定路由正则
    return new PatternServiceRouteMapper("(?<name>^.+)-(?<version>v.+$)", "${version}/${name}");
  }

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

====================================

1.zuul现在使用的是HttpClient,可以使用其他的

2.zuul还支持把一些敏感请求头文件不传到代理的服务上

3.zuul服务自身转发,也可以配置。

4.访问zuul的/route,可以看到zuul所有代理的情况

5.@EnableZuulServer是一个zuul的轻量级自由注解,不带有负载,断路等功能

=========================================

接下里聊一下大文件上传,参考代码microservice-gateway-zuul-file-upload模块:

# 上传大文件得将超时时间设置长一些,否则会报超时异常。以下几行超时设置来自http://cloud.spring.io/spring-cloud-static/Camden.SR3/#_uploading_files_through_zuul
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000
ribbon:
  ConnectTimeout: 3000
  ReadTimeout: 60000

还有一个小技巧,我们上传一般使用的是springMVC,当我们使用zuul代理的时候,可以在代理路径前加上/zuul/*,则不会被springMVC上传的时候限制大小。

=============================================

zuul的fallback,参考代码microservice-gateway-zuul-fallback模块,其实就是自定义一个response

package com.itmuch.cloud.study.fallback;

import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider;
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.nio.charset.Charset;

@Component
public class UserFallbackProvider implements ZuulFallbackProvider {
  @Override
  public String getRoute() {
    // 表明是为哪个微服务提供回退
    return "microservice-provider-user";
  }

  @Override
  public ClientHttpResponse fallbackResponse() {
    return new ClientHttpResponse() {
      @Override
      public HttpStatus getStatusCode() throws IOException {
        // fallback时的状态码
        return HttpStatus.OK;
      }

      @Override
      public int getRawStatusCode() throws IOException {
        // 数字类型的状态码,本例返回的其实就是200,详见HttpStatus
        return this.getStatusCode().value();
      }

      @Override
      public String getStatusText() throws IOException {
        // 状态文本,本例返回的其实就是OK,详见HttpStatus
        return this.getStatusCode().getReasonPhrase();
      }

      @Override
      public void close() {
      }

      @Override
      public InputStream getBody() throws IOException {
        // 响应体
        return new ByteArrayInputStream("用户微服务不可用,请稍后再试。".getBytes());
      }

      @Override
      public HttpHeaders getHeaders() {
        // headers设定
        HttpHeaders headers = new HttpHeaders();
        MediaType mt = new MediaType("application","json", Charset.forName("UTF-8"));
        headers.setContentType(mt);

        return headers;
      }
    };
  }
}

==================================

定义zuul的过滤器:

package com.itmuch.cloud.study.filters.pre;

import javax.servlet.http.HttpServletRequest;

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

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

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

  @Override
  public String filterType() {
    return "pre";
  }

  @Override
  public int filterOrder() {
    return 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", request.getMethod(), request.getRequestURL().toString()));
    return null;
  }
}

然后注入这个bean

package com.itmuch.cloud.study;

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.itmuch.cloud.study.filters.pre.PreRequestLogFilter;

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

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

zuul支持自定义Fifter,也有很多实现好的Fifter(在org.springframework.cloud.netflix.zuul.filters包下)。

如果想禁用某一个Fifter,只需设置zuul.<SimpleClassName>.<filterType> .disable = true。例如,要禁用org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter 需设置 zuul.SendResponseFilter.post.disable = true。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页