正文

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

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

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

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

一、Zuul网关的作用

网关有以下几个作用:

  • 统一入口:未全部为服务提供一个唯一的入口,网关起到外部和内部隔离的作用,保障了后台服务的安全性。
  • 鉴权校验:识别每个请求的权限,拒绝不符合要求的请求。
  • 动态路由:动态的将请求路由到不同的后端集群中。
  • 减少客户端与服务端的耦合:服务可以独立发展,通过网关层来做映射。

二、Zuul网关的应用

1、网关访问方式

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

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

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

2、网关依赖注入

        org.springframework.cloud      spring-cloud-starter-eureka          org.springframework.cloud      spring-cloud-starter-zuul           org.springframework.retry     spring-retry   

3、网关启动器

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

4、网关全局变量配置

4.1 URL路径匹配

# URL pattern  # 使用路径方式匹配路由规则。  # 参数key结构:zuul.routes.customName.path=xxx  # 用于配置路径匹配规则。  # 其中customName自定义。通常使用要调用的服务名称,方便后期管理  # 可使用的通配符有: * ** ?  # ? 单个字符  # * 任意多个字符,不包含多级路径  # ** 任意多个字符,包含多级路径  zuul.routes.eureka-application-service.path=/api/**  # 参数key结构:zuul.routes.customName.url=xxx  # url用于配置符合path的请求路径路由到的服务地址。  zuul.routes.eureka-application-service.url=http://127.0.0.1:8080/ 

4.2 服务名称匹配

# service id pattern 通过服务名称路由  # key结构 :zuul.routes.customName.path=xxx  # 路径匹配规则  zuul.routes.eureka-application-service.path=/api/**  # key结构 :zuul.routes.customName.serviceId=xxx  # serviceId用于配置符合path的请求路径路由到的服务名称。  zuul.routes.eureka-application-service.serviceId=eureka-application-service 

服务名称匹配也可以使用简化的配置:

# simple service id pattern 简化配置方案  # 如果只配置path,不配置serviceId。则customName相当于服务名称。  # 符合path的请求路径直接路由到customName对应的服务上。 zuul.routes.eureka-application-service.path=/api/** 

4.3 路由排除配置

# ignored service id pattern  # 配置不被zuul管理的服务列表。多个服务名称使用逗号','分隔。  # 配置的服务将不被zuul代理。 zuul.ignored-services=eureka-application-service  # 此方式相当于给所有新发现的服务默认排除zuul网关访问方式,只有配置了路由网关的服务才可以通过zuul网关访问  # 通配方式配置排除列表。  zuul.ignored-services=*  # 使用服务名称匹配规则配置路由列表,相当于只对已配置的服务提供网关代理。  zuul.routes.eureka-application-service.path=/api/**  # 通配方式配置排除网关代理路径。所有符合ignored-patterns的请求路径都不被zuul网关代理。  zuul.ignored-patterns=/**/test/**  zuul.routes.eureka-application-service.path=/api/** 

4.4 路由前缀配置

# prefix URL pattern 前缀路由匹配  # 配置请求路径前缀,所有基于此前缀的请求都由zuul网关提供代理。  zuul.prefix=/api  # 使用服务名称匹配方式配置请求路径规则。  # 这里的配置将为:http://ip:port/api/appservice/**的请求提供zuul网关代理,可以将要访问服务进行前缀分类。  # 并将请求路由到服务eureka-application-service中。  zuul.routes.eureka-application-service.path=/appservice/** 

5 Zuul网关配置总结

网关配置方式有多种,默认、URL、服务名称、排除|忽略、前缀。

网关配置没有优劣好坏,应该在不同的情况下选择合适的配置方案。扩展:大公司为什么都有API网关?聊聊API网关的作用

zuul网关其底层使用ribbon来实现请求的路由,并内置Hystrix,可选择性提供网关fallback逻辑。使用zuul的时候,并不推荐使用Feign作为application client端的开发实现。毕竟Feign技术是对ribbon的再封装,使用Feign本身会提高通讯消耗,降低通讯效率,只在服务相互调用的时候使用Feign来简化代码开发就够了。而且商业开发中,使用Ribbon+RestTemplate来开发的比例更高。

三、Zuul网关过滤器

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

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

  • 前置过滤:是请求进入Zuul之后,立刻执行的过滤逻辑。
  • 路由后过滤:是请求进入Zuul之后,并Zuul实现了请求路由后执行的过滤逻辑,路由后过滤,是在远程服务调用之前过滤的逻辑。
  • 后置过滤:远程服务调用结束后执行的过滤逻辑。
  • 异常过滤:是任意一个过滤器发生异常或远程服务调用无结果反馈的时候执行的过滤逻辑。无结果反馈,就是远程服务调用超时。

3.1 过滤器实现方式

继承父类ZuulFilter。在父类中提供了4个抽象方法,分别是:filterType, filterOrder, shouldFilter, run。其功能分别是:

filterType:方法返回字符串数据,代表当前过滤器的类型。可选值有-pre, route, post, error。

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

filterOrder:返回int数据,用于为同filterType的多个过滤器定制执行顺序,返回值越小,执行顺序越优先。

shouldFilter:返回boolean数据,代表当前filter是否生效。

run:具体的过滤执行逻辑。如pre类型的过滤器,可以通过对请求的验证来决定是否将请求路由到服务上;如post类型的过滤器,可以对服务响应结果做加工处理(如为每个响应增加footer数据)。

3.2 过滤器的生命周期

3.3 代码示例

/**   * Zuul过滤器,必须继承ZuulFilter父类。   * 当前类型的对象必须交由Spring容器管理。使用@Component注解描述。   * 继承父类后,必须实现父类中定义的4个抽象方法。   * shouldFilter、 run、 filterType、 filterOrder   */  @Component  public class LoggerFilter extends ZuulFilter {      private static final Logger logger = LoggerFactory.getLogger(LoggerFilter.class);         /**       * 返回boolean类型。代表当前filter是否生效。       * 默认值为false。       * 返回true代表开启filter。       */      @Override      public boolean shouldFilter() {          return true;      }      /**       * run方法就是过滤器的具体逻辑。       * return 可以返回任意的对象,当前实现忽略。(spring-cloud-zuul官方解释)       * 直接返回null即可。       */      @Override      public Object run() throws ZuulException {          // 通过zuul,获取请求上下文          RequestContext rc = RequestContext.getCurrentContext();          HttpServletRequest request = rc.getRequest();          logger.info("LogFilter1.....method={},url={}",                  request.getMethod(),request.getRequestURL().toString());          // 可以记录日志、鉴权,给维护人员记录提供定位协助、统计性能          return null;      }      /**       * 过滤器的类型。可选值有:       * pre - 前置过滤       * route - 路由后过滤       * error - 异常过滤       * post - 远程服务调用后过滤       */      @Override      public String filterType() {          return "pre";      }      /**       * 同种类的过滤器的执行顺序。       * 按照返回值的自然升序执行。       */      @Override      public int filterOrder() {          return 0;      }  } 

四、Zuul网关的容错(与Hystrix的无缝结合)

在spring cloud中,Zuul启动器中包含了Hystrix相关依赖,在Zuul网关工程中,默认是提供了Hystrix Dashboard服务监控数据的(hystrix.stream),但是不会提供监控面板的界面展示。可以说,在spring cloud中,zuul和Hystrix是无缝结合的。

4.1 Zuul中的服务降级处理

在Edgware版本之前,Zuul提供了接口ZuulFallbackProvider用于实现fallback处理。从Edgware版本开始,Zuul提供了ZuulFallbackProvider的子接口FallbackProvider来提供fallback处理。

Zuul的fallback容错处理逻辑,只针对timeout异常处理,当请求被Zuul路由后,只要服务有返回(包括异常),都不会触发Zuul的fallback容错逻辑。

因为对于Zuul网关来说,做请求路由分发的时候,结果由远程服务运算的。那么远程服务反馈了异常信息,Zuul网关不会处理异常,因为无法确定这个错误是否是应用真实想要反馈给客户端的。

4.2 代码示例

/**   * 如果需要在Zuul网关服务中增加容错处理fallback,需要实现接口ZuulFallbackProvider   * spring-cloud框架,在Edgware版本(包括)之后,声明接口ZuulFallbackProvider过期失效,  * 提供了新的ZuulFallbackProvider的子接口 - FallbackProvider   * 在老版本中提供的ZuulFallbackProvider中,定义了两个方法。   *  - String getRoute()   *    当前的fallback容错处理逻辑处理的是哪一个服务。可以使用通配符‘*’代表为全部的服务提供容错处理。   *    如果只为某一个服务提供容错,返回对应服务的spring.application.name值。   *  - ClientHttpResponse fallbackResponse()   *    当服务发生错误的时候,如何容错。   * 新版本中提供的FallbackProvider提供了新的方法。   *  - ClientHttpResponse fallbackResponse(Throwable cause)   *    如果使用新版本中定义的接口来做容错处理,容错处理逻辑,只运行子接口中定义的新方法。也就是有参方法。   *    是为远程服务发生异常的时候,通过异常的类型来运行不同的容错逻辑。   */  @Component  public class TestFallBbackProvider implements FallbackProvider {      /**       * return - 返回fallback处理哪一个服务。返回的是服务的名称       * 推荐 - 为指定的服务定义特性化的fallback逻辑。       * 推荐 - 提供一个处理所有服务的fallback逻辑。       * 好处 - 服务某个服务发生超时,那么指定的fallback逻辑执行。如果有新服务上线,未提供fallback逻辑,有一个通用的。       */      @Override      public String getRoute() {          return "eureka-application-service";      }     /**       * fallback逻辑。在早期版本中使用。       * Edgware版本之后,ZuulFallbackProvider接口过期,提供了新的子接口FallbackProvider       * 子接口中提供了方法ClientHttpResponse fallbackResponse(Throwable cause)。       * 优先调用子接口新定义的fallback处理逻辑。      */      @Override      public ClientHttpResponse fallbackResponse() {          System.out.println("ClientHttpResponse fallbackResponse()");             List> result = new ArrayList<>();          Map data = new HashMap<>();          data.put("message", "服务正忙,请稍后重试");          result.add(data);                ObjectMapper mapper = new ObjectMapper();                 String msg = "";          try {              msg = mapper.writeValueAsString(result);          } catch (JsonProcessingException e) {              msg = "";          }                return this.executeFallback(HttpStatus.OK, msg,                   "application", "json", "utf-8");      }      /**       * fallback逻辑。优先调用。可以根据异常类型动态决定处理方式。       */      @Override      public ClientHttpResponse fallbackResponse(Throwable cause) {          System.out.println("ClientHttpResponse fallbackResponse(Throwable cause)");          if(cause instanceof NullPointerException){                         List> result = new ArrayList<>();              Map data = new HashMap<>();              data.put("message", "网关超时,请稍后重试");              result.add(data);                       ObjectMapper mapper = new ObjectMapper();                         String msg = "";              try {                  msg = mapper.writeValueAsString(result);              } catch (JsonProcessingException e) {                  msg = "";              }                          return this.executeFallback(HttpStatus.GATEWAY_TIMEOUT,                       msg, "application", "json", "utf-8");          }else{              return this.fallbackResponse();          }      }         /**       * 具体处理过程。       * @param status 容错处理后的返回状态,如200正常GET请求结果,201正常POST请求结果,404资源找不到错误等。       *  使用spring提供的枚举类型对象实现。HttpStatus       * @param contentMsg 自定义的响应内容。就是反馈给客户端的数据。      * @param mediaType 响应类型,是响应的主类型, 如:application、text、media。       * @param subMediaType 响应类型,是响应的子类型, 如:json、stream、html、plain、jpeg、png等。       * @param charsetName 响应结果的字符集。这里只传递字符集名称,如:utf-8、gbk、big5等。       * @return ClientHttpResponse 就是响应的具体内容。       *  相当于一个HttpServletResponse。       */      private final ClientHttpResponse executeFallback(final HttpStatus status,               String contentMsg, String mediaType, String subMediaType, String charsetName) {          return new ClientHttpResponse() {              /**               * 设置响应的头信息               */              @Override              public HttpHeaders getHeaders() {                  HttpHeaders header = new HttpHeaders();                  MediaType mt = new MediaType(mediaType, subMediaType, Charset.forName(charsetName));                  header.setContentType(mt);                  return header;              }              /**               * 设置响应体               * zuul会将本方法返回的输入流数据读取,并通过HttpServletResponse的输出流输出到客户端。               */              @Override              public InputStream getBody() throws IOException {                  String content = contentMsg;                  return new ByteArrayInputStream(content.getBytes());              }              /**               * ClientHttpResponse的fallback的状态码 返回String               */              @Override              public String getStatusText() throws IOException {                  return this.getStatusCode().getReasonPhrase();              }              /**               * ClientHttpResponse的fallback的状态码 返回HttpStatus               */              @Override              public HttpStatus getStatusCode() throws IOException {                  return status;              }              /**               * ClientHttpResponse的fallback的状态码 返回int               */              @Override              public int getRawStatusCode() throws IOException {                  return this.getStatusCode().value();              }              /**               * 回收资源方法               * 用于回收当前fallback逻辑开启的资源对象的。              * 不要关闭getBody方法返回的那个输入流对象。               */              @Override              public void close() {              }          };      }  } 

五、Zuul网关的限流保护

Zuul网关组件也提供了限流保护。当请求并发达到阀值,自动触发限流保护,返回错误结果。只要提供error错误处理机制即可。

Zuul的限流保护需要额外依赖spring-cloud-zuul-ratelimit组件。

      com.marcosbarbero.cloud      spring-cloud-zuul-ratelimit      1.3.4.RELEASE   

5.1 全局限流配置

使用全局限流配置,zuul会对代理的所有服务提供限流保护。

# 开启限流保护  zuul.ratelimit.enabled=true  # 60s内请求超过3次,服务端就抛出异常,60s后可以恢复正常请求  zuul.ratelimit.default-policy.limit=3  zuul.ratelimit.default-policy.refresh-interval=60  # 针对IP进行限流,不影响其他IP  zuul.ratelimit.default-policy.type=origin 

5.2 局部限流配置

使用局部限流配置,zuul仅针对配置的服务提供限流保护。

# 开启限流保护  zuul.ratelimit.enabled=true  # hystrix-application-client服务60s内请求超过3次,服务抛出异常。  zuul.ratelimit.policies.hystrix-application-client.limit=3  zuul.ratelimit.policies.hystrix-application-client.refresh-interval=60  # 针对IP限流。  zuul.ratelimit.policies.hystrix-application-client.type=origin 

5.3 限流参数简介

六、Zuul网关性能调优:网关的两层超时调优

使用Zuul的spring cloud微服务结构图:

从上图中可以看出。整体请求逻辑还是比较复杂的,在没有zuul网关的情况下,app client请求app service的时候,也有请求超时的可能。那么当增加了zuul网关的时候,请求超时的可能就更明显了。

当请求通过zuul网关路由到服务,并等待服务返回响应,这个过程中zuul也有超时控制。zuul的底层使用的是Hystrix+ribbon来实现请求路由。结构如下:

zuul中的Hystrix内部使用线程池隔离机制提供请求路由实现,其默认的超时时长为1000毫秒。ribbon底层默认超时时长为5000毫秒。如果Hystrix超时,直接返回超时异常。如果ribbon超时,同时Hystrix未超时,ribbon会自动进行服务集群轮询重试,直到Hystrix超时为止。如果Hystrix超时时长小于ribbon超时时长,ribbon不会进行服务集群轮询重试。

那么在zuul中可配置的超时时长就有两个位置:Hystrix和ribbon。具体配置如下:

# 开启zuul网关重试  zuul.retryable=true  # hystrix超时时间设置  # 线程池隔离,默认超时时间1000ms  hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=8000  # ribbon超时时间设置:建议设置比Hystrix小  # 请求连接的超时时间: 默认5000ms  ribbon.ConnectTimeout=5000  # 请求处理的超时时间: 默认5000ms  ribbon.ReadTimeout=5000  # 重试次数:MaxAutoRetries表示访问服务集群下原节点(同路径访问);MaxAutoRetriesNextServer表示访问服务集群下其余节点(换台服务器)  ribbon.MaxAutoRetries=1  ribbon.MaxAutoRetriesNextServer=1  # 开启重试  ribbon.OkToRetryOnAllOperations=true 

Spring-cloud中的zuul网关重试机制是使用spring-retry实现的。工程必须依赖下述资源:

    org.springframework.retry    spring-retry    

来源:https://www.tuicool.com/articles/n2AF3ea

网关的作用是什么_SpringCloud中Zuul网关原理及其配置,看它就够了相关推荐

  1. properties 配置回车_非常全面的讲解SpringCloud中Zuul网关原理及其配置,看它就够了!...

    本文同步Java知音社区,专注于Java 作者:kosamino http://www.cnblogs.com/jing99/p/11696192.html Zuul是spring cloud中的微服 ...

  2. 非常全面的讲解SpringCloud中Zuul网关原理及其配置,看它就够了!

    作者:kosamino www.cnblogs.com/jing99/p/11696192.html Zuul是spring cloud中的微服务网关.网关:是一个网络整体系统中的前置门户入口.请求首 ...

  3. properties 配置回车_非常全面的讲解SpringCloud中Zuul网关原理及其配置,看它就够了! - 风平浪静如码

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

  4. 全面的讲解SpringCloud中Zuul网关原理及其配置,看它就够了

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

  5. welcome-file-list标签的控制作用以及在springmvc中此标签的的配置方式

    我们在写安全性较高的网站时必然会对网站的入口进行限制, 而在这其中其关键作用的就是网站的根目录下WEB-INF中的web.xml中 <welcome-file-list>   <we ...

  6. PLC数据采集网关的作用是什么,PLC数据采集网关的功能都有哪些

    PLC数据采集网关远程诊断维护各地PLC,实现PLC的程序下载,编程,维护等功能,解决分布各地的多台工业PLC设备设施现场维护.监控维修等问题,进一步的节约成本以及更高效的对远程设施进行实时控制. P ...

  7. iOS开发中 经常遇到的坑,看我就够了! 韩俊强的博客

    从事iOS开发有些年月了,从最开始的磕磕绊绊,不知所措,到现在的遇到困难都能快速做出最佳方案处理,中间经历了不可或缺的痛苦.在项目开发中,本人有用印象笔记记录的习惯,所以很多重复出现的坑,很快迎刃而解 ...

  8. 关于 scrapy 中 COOKIES_ENABLED 设置 理解问题,看这里就够了

    看了很多的文章, 感觉写的都有点扯淡 ,误人子弟 . 源码中 : 默认是注释掉的,但是上面的备注写的是开启状态(没关系, 不管). 所以这个 就有了三个状态: 1. 第一个 源码的 注释状态: # D ...

  9. 计算机网络设置中的网关是什么设备,网关是什么_网关的作用与设置方法介绍 一看就明白...

    网关是什么?对于普通的用户来说,电脑网关不是很明白的,不过接触电脑多了之后,大家也会常常会听到"网关"这个词,那么问题就来了,这个网关是什么意思呢?它又有哪些作用呢?今晚,智能手机 ...

最新文章

  1. 用Zabbix部署onalert云告警平台
  2. 利用QCustomePlot绘制热力图,瀑布图,频谱色图等
  3. “双碳”目标下新型数据中心的方向
  4. 使用Bootstrap制作导航栏
  5. PyCharm入门教程——在编辑器中选择文本
  6. 不断电系统的容量如何计算?
  7. .NET Core跨平台图形处理库ImageSharp
  8. 体验了一下用word 2007发表博客
  9. Jedis使用测试——连接本地及远程的Redis
  10. php更新so需要重启吗,不重新编译PHP为php增加openssl.so模块
  11. 关于某系统的全面质量属性战术
  12. EM 算法的推导和解释
  13. linux 下安装小度wifi,Fedora/Ubuntu如何安装小度/360随身WIFI驱动
  14. PC微信多开源代码-消息钩子+ZwQuerySystemInformation
  15. Win11预览版更新错误怎么办?Win11预览版安装失败的解决方法
  16. sl400通过ac无法连接psk加密无线网络
  17. 十大股票资讯网站排名 炒股资讯网站排行榜 炒股必看的资讯网站推荐
  18. 远程驾驶一般怎么实现
  19. 如何重新设置苹果id密码_苹果ID密码忘了怎么办?
  20. oracle AWR 报告 中文版

热门文章

  1. html安装网卡驱动,如何手动安装无线网卡驱动,网卡驱动安装教程
  2. left join 临时表_不懂SQL优化?那你就OUT了——表连接的优化
  3. 【2019暑假刷题笔记-STL绪论】总结自《算法笔记》
  4. Redis+Nginx+JVM+设计模式+Spring全家桶+Dubbo万字总结
  5. 请立即弃用 Notepad++,还有 5 款更牛逼的选择!
  6. Lombok 介绍和使用详情
  7. 自己动手写一个单链表
  8. 创建JPA工程时提示:at least one user library must be selected
  9. get方法报空指针_智能指针shared_ptr踩坑笔记
  10. 浅谈迷宫搜索类的双向bfs问题(例题解析)