SpringCloud(Zuul)

主要收集、整理Zuul相关的知识点,并加以自己的实践理解

1 什么是API网关

  • 网关这种东西,是伴随着微服务风生水起的,微服务可以没有api网关,但是最好有,也并不是绝对的。因为有这个东西是合理的,没有的话,你的微服务会很难受。

  • 首先网关最基础的作用就是对外包括ios、android、webapp、website、h5、微信小程序甚至是第三方提供一个统一服务接入入口。聚合内网众多微服务,为端上提供统一的api入口。对外统一使-用http协议,网关屏蔽了后端协议的差异性,后端可以专注于提供服务,无需考虑协议的转换。

  • 其次,网关应该具备API防刷以及限流的功能。防刷可以保护你的API不会被恶意调用,限流可以保护你的后端不会被冲垮。网关应该还具备权鉴功能,是否具备对某个api的访问功能,应该做在api网关层会好很多。保护后端服务,提供完善的流控、服务降级、ACL、鉴权机制。

  • 提供API管理平台,包括API的配置、沙箱测试、发布、修改、下线。

  • 提供API层面的监控与报表,做到对业务自身的掌控,以及对用户行为等进行分析。为开放平台的持续完善提供基础服务。

  • 它可以为不同类型的客户端定义不同的api:
    在这里插入图片描述

2 什么是Zuul

  • Zuul是Spring Cloud全家桶中的微服务API网关。所有从设备或网站来的请求都会经过Zuul到达后端的Netflix应用程序。作为一个边界性质的应用程序,Zuul提供了动态路由、监控、弹性负载和安全功能。Zuul底层利用各种filter实现如下功能:

      1) 认证和安全 识别每个需要认证的资源,拒绝不符合要求的请求。
      2) 性能监测 在服务边界追踪并统计数据,提供精确的生产视图。
      3) 动态路由 根据需要将请求动态路由到后端集群。
      4) 压力测试 逐渐增加对集群的流量以了解其性能。
      5) 负载卸载 预先为每种类型的请求分配容量,当请求超过容量时自动丢弃。
      6) 静态资源处理 直接在边界返回某些响应。
    

3 Zuul的核心

Filter是Zuul的核心,用来实现对外服务的控制。Filter的生命周期有4个,分别是“PRE”、“ROUTING”、“POST”、“ERROR”,整个生命周期可以用下图来表示。
在这里插入图片描述
Zuul大部分功能都是通过过滤器来实现的,这些过滤器类型对应于请求的典型生命周期。

  • PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。这个阶段后如果有自定义的过滤器,则会执行自定义的过滤器。
  • ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
  • ERROR:在其他阶段发生错误时执行该过滤器。 除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。
  • POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。

4 Zuul中默认实现的Filter

类型顺序过滤器功能
pre-3ServletDetectionFilter标记处理Servlet的类型
pre-2Servlet30WrapperFilter包装HttpServletRequest请求
pre-1FormBodyWrapperFilter包装请求体
route1DebugFilter标记调试标志
route5PreDecorationFilter处理请求上下文供后续使用
route10RibbonRoutingFilterserviceId请求转发
route100SimpleHostRoutingFilterurl请求转发
route500SendForwardFilterforward请求转发
post0SendErrorFilter处理有错误的请求响应
post1000SendResponseFilter处理正常的请求响应

5 搭建SpringCloud Zuul

5.1 maven依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    <version>2.1.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    <version>2.1.2.RELEASE</version>
</dependency>

5.2 启动类中开启Zuul服务

package com.kinglong.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication
@EnableZuulProxy//开启zuul
public class Application {

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

}

5.3 配置文件

server.port=8091
#服务名
spring.application.name=06-springcloud-api-gateway

#自定义路由
zuul.routes.api-kinglong.path=/api-kinglong/**
#负载均衡的服务名
zuul.routes.api-kinglong.service-id=05-springcloud-service-feign
#eureka服务注册地址
eureka.client.service-url.defaultZone=http://eureka8085:8085/eureka/,http://eureka8086:8086/eureka/

以上就可以直接启动了,这就是最简版的Zuul,他只是起到了对请求的转发作用。

5.4 自定义Filter

实现自定义Filter,需要继承ZuulFilter的类,并覆盖其中的4个方法。

package com.kinglong.springcloud.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * 自定义Filter
 * 
 * @author haojinlong
 */
@Component //加了注解后可以让这个过滤器注入到spring中,变为一个bean
public class AuthFilter extends ZuulFilter {

	/**
	 * 返回值为过滤器的类型,过滤器的类型决定了过滤器在哪个生命周期执行,
	 * pre标识在任意路由之前执行过滤器,其他值还有post,error,route和static,也可以自定义
	 *
	 * @return
	 */
	@Override
	public String filterType() {
		return "pre";
	}

	/**
	 * 表示过滤器的执行顺序,当过滤器很多时,可以通过该方法返回值指定过滤器的执行顺序
	 *
	 * @return
	 */
	@Override
	public int filterOrder() {
		return 0;
	}

	/**
	 * 判断过滤器是否执行,true表示执行,false表示不执行
	 *
	 * @return
	 */
	@Override
	public boolean shouldFilter() {
		return true;
	}

	/**
	 * 具体逻辑
	 * 如果请求地址中携带了token参数,则认为是合法的请求,如果不是则为非法请求。当然还是要根据具体业务场景做相应的处理。
	 * 这里只是实验功能
	 * @return
	 * @throws ZuulException
	 */
	@Override
	public Object run() throws ZuulException {
		RequestContext context = RequestContext.getCurrentContext();
		HttpServletRequest request = context.getRequest();
		String token = request.getParameter("token");
		if(null == token){
			context.setSendZuulResponse(false);
			context.setResponseStatusCode(401);
			context.addZuulResponseHeader("content-type", "text/html;charset=utf-8");
			context.setResponseBody("无权限访问");
		}

		return null;
	}
}

有了第四步之后,再如第三步一样不带token访问就无法访问了,会被拦截出去。
在这里插入图片描述

5.5 Zuul的路由规则

配置文件中的两个路由配置其实是可以简写,合并成一个配置,如下:

  • 原先的路由配置
#自定义路由
zuul.routes.api-kinglong.path=/api-kinglong/**
#负载均衡的服务名
zuul.routes.api-kinglong.service-id=05-springcloud-service-feign
  • 简写后的
zuul.routes.05-springcloud-service-feign=/api-kinglong/**

5.6 忽略某个不想对外提供的服务

默认情况下,eureka上所有注册的服务都会被Zuul创建映射关系来进行路由,但是业务场景可能只需要让feign来集中提供服务,而那些底层的服务提供者的服务是不想对外开放的。这时就需要采用一些配置,使其忽略那些不想对外提供服务的路由

#忽略掉服务提供者,如果有多个,可以用逗号隔开即可
zuul.ignored-services=01-springcloud-service-provider

也可以更加精确地具体到某个接口

#忽略掉某个接口
zuul.ignored-patterns=/**/hello/**

还可以统一的为路由增加前缀

zuul.prefix=/myapi

5.7 路由通配符含义

通配符含义举例说明
匹配任意单个字符/05-springcloud-service-feign匹配:/05-springcloud-service-feign/a,/05-springcloud-service-feign/b等
*匹配任意数量的字符/05-springcloud-service-feign/*匹配:/05-springcloud-service-feign/aaaa,/05-springcloud-service-feign/bbbb等,但是不可以匹配:/05-springcloud-service-feign/bb/oo/hhh
**匹配任意单个字符/05-springcloud-service-feign/**匹配:/05-springcloud-service-feign/a/r/ddd,/05-springcloud-service-feign/b/d/f等

6 Zuul和Nginx哪家强

有人已经做了相关测试

https://blog.csdn.net/zhangbijun1230/article/details/81660834
(基于zuul1测试)最后的结论:因为zuul是java开发的,所以服务器硬件配置对性能影响很大,在8核32G的配置上,Zuul才跑赢了Nginx。
https://www.2cto.com/kf/201805/746203.html
(基于zuul2测试,zuul2采用的是netty开发)性能和nginx相差不大,基本一致。

Zuul的原始性能接近Nginx。事实上,在启动预热之后,显示测试结果更好一些。但Nginx看上去会稳定一下,Zuul出现了2次的请求错误。
如果你想使用Zuul的其他功能,或者希望通过它与其他的Netflix服务集成(比如Eureka),Zuul可以作为其他简单反向代理的替代品。

文献参考来源:

https://blog.csdn.net/u011820505/article/details/79373594
https://microservices.io/patterns/apigateway.html
https://blog.csdn.net/qq_27384769/article/details/82991261

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值