spring cloud之zuul

写在前面

本篇文章仅作为近日参考其他文章后,自己实践的记录和总结,场景到细节尚有很多不足,有待补充和修正。

概述

Zuul使用一系列不同类型的过滤器,使我们能够快速灵活地将功能应用于我们的边缘服务。 这些过滤器可帮助我们执行
以下功能:
身份验证和安全 - 识别每个资源的身份验证要求,并拒绝不满足他们的请求。
洞察和监测 - 跟踪边缘的有意义的数据和统计数据,以便我们准确地了解生产情况。
动态路由 - 根据需要将请求动态路由到不同的后端集群。
压力测试 - 逐渐增加到集群的流量,以衡量性能。
负载分配 - 为每种类型的请求分配容量并删除超出限制的请求。
静态响应处理 - 直接在边缘构建一些响应,而不是将它们转发到内部集群
多区域弹性 - 跨AWS地区的路由请求,以使我们的ELB使用多样化

简单使用

zuul网关的使用往往需要新建一个单独的微服务作为网管服务,新建服务首先需要引入依赖

<dependencies>
    <!--zuul核心依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-zuul</artifactId>
    </dependency>	
    <!--需要单独引入eureka client依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
    </dependency>
</dependencies>

然后简单配置一下yml文件即可

spring:
  application:
    name: common-zuul
#  profiles:
#    active: zuul1
server:
  port: 8888
eureka:
  client:
    serviceUrl:
      defaultZone: http://user:passwd@127.0.0.1:8761/eureka
  instance:
    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${server.port}

这个时候就可以直接启动并使用网关服务啦。

zuul默认以其他微服务的spring.application.name作为路径前缀
比如先现有微服务 consumer-a :

spring:
  application:
    name: consumer-a

该微服务提供接口为:

@GetMapping("/c/getByFeign/{id}")
public String getByFeign(@PathVariable String id) {
	return producerFeign.get(id);
}

则直接访问上面的接口路径应为http://127.0.0.1:8888/c/getByFeign/{id}
通过默认网关的方式路径应为http://127.0.0.1:8888/consumer-a/c/getByFeign/{id}

开启日志打印

为了查看网关路由转换的处理详情,我们仅须在yml文件添加如下配置即可

logging:
  level:
    org.springframework.cloud.netflix.zuul: debug

zuul反向代理

上面我们了解了zuul默认的代理方式,下面是通过yml配置实现更多样的代理方式

  1. 为指定的微服务添加代理规则(方式一)
zuul: 
  routes:
    #单独设置某一个服务的反向代理规则
    consumer-a: /consumer/**

按照上面这样设置,那么
除了默认的 http://127.0.0.1:8888/consumer-a/c/getByFeign/{id} 路径可以访问之外,也可以使用 http://127.0.0.1:8888/consumer/c/getByFeign/{id} 路径访问

  1. 为指定的微服务添加代理规则(方式二)

    按照这种方式可以为添加的规则命名

zuul: 
  routes:
    #单独设置某一个服务的反向代理规则,名字可以随便,只要不重复即可
    consumer1:
      #代理路径
      path: /consumer1/**
      #需要反向代理的serviceId
      serviceId: consumer
    #单独设置某一个服务的反向代理规则,名字可以随便,只要不重复即可
    consumer2:
      #代理路径
      path: /consumer2/**
      #需要反向代理的serviceId
      serviceId: consumer
  1. 为指定的服务实例(ip+port)代理
zuul: 
  routes:
    #单独设置某一个服务的反向代理规则,名字可以随便,只要不重复即可
    byIp:
      #代理路径
      path: /comsumerIp/**
      #可以不是用serviceId,而是使用需要反向代理的服务地址
      #使用这种url的方式将不会支持Hystrix断路器和Ribbon负载均衡
      url: http://127.0.0.1:9010

按照上面的配置方式,例如请求网管地址 http://127.0.0.1:8888 /consumerIp/c/getByFeign/{id} 时,将会转到地址 http://127.0.0.1:9010/c/getByFeign/{id}

  1. 为所有服务的代理路径添加前缀
zuul:
  #给所有的代理路径增加前缀,需要使用/api/${serviceId}/**进行访问
  prefix: /api
  #是否保留额外的前缀,默认为true,设置为false将会移除zuul.prefix的配置
  #strip-prefix: false
  1. 关闭默认的代路径
    上面我们可以知道默认以代理微服务的spring.application.name值作为代理路径前缀,可以通过下面的yml配置关闭默认的代理路径,需要注意的是,如果关闭了服务的默认代理路径却不为其设置自定义的代理路径,那么zuul网关代理将无法转发该微服务的请求
zuul: 
  #设置某几个service不使用默认的反向代理
  #ignored-services: consumer1,consumer2
  #设置所有service都不使用默认的反向代理
  ignored-services: '*'

zuul监控端点

通过访问微服务的指定路径,即可查看zull网关服务代理的节点信息有哪些。

观察spring-cloud-starter-zuul依赖的内部关系,我们不难发现zuul网关服务默认自带spring cloud actuator安全组件。
在这里插入图片描述因此,为了方便查看监控端点,我们可以先关闭安全控制(不关闭的话访问监控端点会提示401,不关闭的情况下如何访问,不属于zuul范畴,有待更深入探究),yml配置如下:

management:
  security:
    #关闭安全设置,默认为true, 否则无法访问/routes管理端点
    #使用如下两个地址可以查看zuul的代理信息
    #/routes
    #/routes?format=details
    enabled: false

访问路径 http://127.0.0.1:8888/routes 可以查看代理的概览
在这里插入图片描述

访问路径 http://127.0.0.1:8888/routes?format=details 可以查看代理的详细信息
在这里插入图片描述

zuul过滤器

首先了解一下zuul网关服务请求的生命周期
在这里插入图片描述根据生命周期我们可以看出zuul过滤器主要分为四类

filterType说明
pre在收到请求后最先执行
route将请求路径转化为实际的目标服务请求路径时用到的过滤器
post目标服务返回结果后用到的过滤器
error请求发生异常时,用到的过滤器

zuul过滤器的核心接口类为com.netflix.zuul.ZuulFilter,概览如下

public abstract class ZuulFilter implements IZuulFilter, Comparable<ZuulFilter> {
    private final DynamicBooleanProperty filterDisabled = DynamicPropertyFactory.getInstance().getBooleanProperty(this.disablePropertyName(), false);

    public ZuulFilter() {
    }

    public abstract String filterType();

    public abstract int filterOrder();

	......
}

包括实现类com.netflix.zuul.IZuulFilter

package com.netflix.zuul;

public interface IZuulFilter {
    boolean shouldFilter();

    Object run();
}

从上面可以看出,zuul过滤器核心的四个方法为

实现方法说明
filterType返回当前过滤器的过滤器类型
filterOrder返回当前过滤器的过滤器的执行顺序
shouldFilter用于判断过滤器是否执行
run执行过滤器的实际操作

zuul过滤器执行操作时,主要是围绕着请求的上下文对象(com.netflix.zuul.context.RequestContext),主要的过滤器如下:
在这里插入图片描述
过滤器具体的执行逻辑,可以参考实现类源码的四个关键方法

下面是手动禁用zuul自带的核心过滤器的方法,以DebugFilter为例

zuul:
  #过滤器名称
  DebugFilter: 
    #过滤器的filterType
    pre:
      disable: false

自定义过滤器

在了解zuul过滤器工作原理之后,我们可以自己定义一个或多个过滤器来实现我们的想法。其中关键点是要实现com.netflix.zuul.ZuulFilter接口类,并使用@Component或其他方式将过滤器注入到spring容器。

其次便是了解com.netflix.zuul.context.RequestContext类的使用,下面将列举出部分重要的方法并说明,更有待补充

方法说明
set(String key)设置一个属性,key为属性名称,属性值默认为true
set(String key, Object value)设置一个属性,key为属性名称,属性值默认为value
getRequest()获取HttpServletRequest对象
setRequest(HttpServletRequest request)设置HttpServletRequest对象
getResponse()获取HttpServletResponse对象
setResponse(HttpServletResponse response)设置HttpServletResponse对象
sendZuulResponse()判断是否经过route环节,为false的话,将不会转发请求到微服务
setSendZuulResponse(boolean bSend)设置是否经过route环节,为false的话,将不会转发请求到微服务
getResponseStatusCode()获取响应编码
setResponseStatusCode(int nStatusCode)设置响应编码

zuul使用hystrix

zuul默认使用hystrix
在这里插入图片描述那么如何设置fallback(服务降级)呢?首先来了解org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider接口类

package org.springframework.cloud.netflix.zuul.filters.route;

import org.springframework.http.client.ClientHttpResponse;

/**
 * Provides fallback when a failure occurs on a route.
 * @author Ryan Baxter
 * @deprecated Use {@link FallbackProvider}
 */
@Deprecated
public interface ZuulFallbackProvider {

	/**
	 * The route this fallback will be used for.
	 * @return The route the fallback will be used for.
	 */
	public String getRoute();

	/**
	 * Provides a fallback response.
	 * @return The fallback response.
	 */
	public ClientHttpResponse fallbackResponse();
}

主要方法包括

实现方法说明
getRoute返回路由名称,及微服务的名称,返回所有微服务则返回 *
fallbackResponse异常时返回的响应对象

ps:可以发现该类为Deprecated,而现在应该使用什么类来替代尚且不知道,有待补充

下面是fallbak样例

@Component
public class ConsumerZuulFallbackProvider implements ZuulFallbackProvider {

	@Override
	public String getRoute() {
		//只针对一个微服务,针对所有微服务时使用 return "*";
		return "consumer";
	}

	@Override
	public ClientHttpResponse fallbackResponse() {
		return new ClientHttpResponse() {

			@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;
			}

			@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() {
				
			}
			
		};
	}

}

补充说明几点:

  1. 实现类须要使用@Component注解,以将其注入到spring容器
  2. 可以配置多个fallback类,如果同时存在针对所有微服务的fallback和针对某个微服务的fallback,将会以精确的为准,针对所有微服务的fallback(getRoute方法返回*)只视为默认的服务降级类
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值