什么是zuul: zuul是从设备和网站到应用程序后端的所有请求的前门。作为边缘服务的应用程序,旨在实现动态路由、监视、弹性和安全性。包含了队请求的路由和过滤这两个最主要的功能。 zuul是Netflix开源的服务网关,它可以和Eureka、Ribbon、Hystrix等组件配合使用。核心就是一系列的过滤器。并以过滤器完成以下的功能: 1.身份认证与安全:识别每个资源的验证要求,并拒绝那些与要求不符的请求。 2.审查与监视:在边缘位置追踪有意义的数据和统计结果,从而带来精确的生产视图。 3.动态路由:动态的将请求路由到不同的后端集群。 4.压力测试:逐渐增加只想集群的流量,以了解性能。 5.负载分配;为每一种负载类型分配对应的容量,并弃用超出限定值的请求。 6.静态响应处理:在边缘位置直接建立部分响应,从而避免其转发到内部集群 7.多区域弹性:跨越AWS Region 进行请求路由,旨在实现ELB(ELastic Load Balancing)使用的多样化,以及让系统的边缘更贴近系统的使用者。 什么是服务网关: Api Gateway(APIGW/API网关),是出现在系统边界的一个面向Api的、串行集中式的强管控服务,这里的边界是企业IT系统的边界,可以理解为企业级应用防火墙。主要起到隔离外部访问与内部系统的作用。在微服务概念的流行之前,Api网关就已经诞生了,例如银行、证券等领域的前置机系统,它可以解决访问认证、报文转换、访问统计等问题。 Api网关是一个服务器,是系统对外的唯一入口。Api网关封装了系统内部架构,为每个客户端提供定制的Api。所有的客户端和消费端都需要通过统一的网关接入微服务,在网关层处理所有非业务功能。Api网关并不是微服务场景中必须的组件,如下图,不管有没有Api网关,后端微服务都可以通过Api很好的支持客户端的访问。 引入Api网关的好处: 1.聚合接口使得服务调用者透明,降低了客户端与后端代码的耦合度。 2.聚合后台服务,节省流量,提高性能,提升用户体验 3.提供安全、流控、过滤、缓存、计算、监控等Api管理功能。 为什么要使用网关: 1.单体应用:浏览器发起请求到单体应用所在的机器,应用从数据库查询数据原路返回给浏览器,对于单体应用来说是不需要网关的 2.微服务:微服务的应用可能部署在不同的机房,不同地区,不同域名下。此时客户端想要请求对应的服务,我们需要知道的是机器具体的IP或者域名,当微服务实例众多的时候,记忆起来非常麻烦,对于客户端来说也太复杂了难以维护。此时,网关诞生了,客户端的请求发送到网关,由网关根据请求标识解析判断出具体的微服务地址,再把请求转发到微服务实例。这其中的记忆功能就需要交给网关来操作了。 如果让客户端与各个微服务直接交互: 1.客户端会多次请求不同的微服务,增加了客户端的复杂性(咱们也记不住这么多的域名) 2.存在跨域请求,在一定的场景下处理相对复杂(我人在上海,我请求发送到广东??上海也有微服务机器啊) 3.身份认证的问题,每个微服务之间需要独立身份认证(不交互,需要 无限登录) 4.难以重构,随着项目的迭代,可能需要重新划分微服务(更换了IP就需要输入新的IP来查看) 5.某些微服务可能使用了防火墙/浏览器不友好的协议,直接访问会有一定的困难。 因此我们需要网关介于客户端与服务器之间的中间层,所有外部请求率先经过微服务网关,客户端只需要与网关交互,只需要知道网关地址即可,优点: 1.易于监控,可在微服务网关收集监控数据并将其推送到外部系统进行分析 2.易于认证,可在微服务网关上进行认证,然后再将请求发送到后端的微服务,从而无需再每个微服务中进行认证。 3.减少了客户端与各个微服务之间的交互次数 网关具有身份认证与安全、审查与监控、动态路由、负载均衡、缓存、请求分片与管理、静态响应处理等功能。当然最主要的职责还是与“外界联系”。网关具备一下功能: 1.性能:Api高可用,负载均衡,容错机制。 2.安全:权限身份认证、脱敏、流量清洗,后端签名(保证全链路可信调用)、黑名单(非法调用的限制) 3.日志:日志记录,一旦涉及分布式,全链路跟踪必不可少 4.缓存:数据缓存 5.监控:记录请求响应数据,Api耗时分析,性能监控。 6.限流:流量控制,错峰流控,可以定义多种限流规则。 7.灰度:线上灰度部署,可以减少风险 8.路由:动态路由规则 Nginx+Lua与Zuul: Nginx 是 C 语言开发,而 Zuul 是 Java 语言开发 Nginx 负载均衡实现,采用服务器实现负载均衡,而 Zuul 负载均衡的实现是采用 Ribbon + Eureka 来实现本地负载均衡 Nginx 适合于服务器端负载均衡,Zuul 适合微服务中实现网关 Nginx 相比 Zuul 功能会更加强大,因为 Nginx 可以整合一些脚本语言(Nginx + Lua) Nginx 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP / POP3 /SMIP 服务器。Zuul 是 Spring Cloud Netflix 中的开源的一个 API Gateway 服务器,本质上是一个 Servlet 应用,提供动态路由,监控,弹性,安全等边缘服务的框架。 Zuul 相当于是从设备和网站到应用程序后端的所有请求的前门。 Nginx 适合做门户网关,是作为整个全局的网关,对外的处于最外层的那种;而 Zuul 属于业务网关,主要用来对应不同的客户端提供服务,用于聚合业务。各个微服务独立部署,职责单一,对外提供服务的时候需要有一个东西把业务聚合起来。 Zuul 可以实现熔断、重试等功能,这是 Nginx 不具备的。 服务名称路由:微服务一般是由几十、上百个服务组成的,对于URl地址路由的方式,如果对每个服务实例手动指定一个唯一的访问地址,这样做显然不合理。然后Zuul支持与Eureka整个开发,根据serviceld自动从注册中心获取服务地址并转发请求,这样做的好处不仅可以通过单个端点来访问所有的服务,而且在添加或移除服务实例时不用修改Zuul的路由配置。 网关过滤器: Zuul包含了对请求的路由和过滤两个核心功能,其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础;而过滤器功能则负责对请求的处理过程进行干预,是实现请求检验,服务聚合等功能的基础,然而实际上,路由功能在真正运行时,它的路由映射和请求转发都是由几个不同的过滤器完成的。 路由映射主要是通过pre类型的过滤器完成的,他将请求路径与配置的路由规则进行匹配,以找到需要转发的目标地址。 关键名词: 类型:定义路由流程中应用过滤器的阶段。公pre、routing、post、error四个阶段 执行顺序:执行过滤器所需的条件。tre开启,false关闭 动作:如果符合条件,将执行的动作。具体操作。 过滤器类型: pre:请求被路由到源服务器之前的过滤器 执行:身份认证、选路由、请求日志 routing:处理将请求发送到源服务器的过滤器 post:响应从源服务器返回是执行的过滤器 执行:对响应增加的Http头、收集统计和度量指标、将响应以流的形式发送到客户端 error:上述阶段出现错误时执行的过滤器。 网关熔断:Zuul的fallback容错处理逻辑,只针对timeout异常处理,当请求被Zuul路由后,只要服务有返回(包括异常),都不会触发Zuul的fallback容错逻辑。 网关限流:当请求达到阈值时,自动触发限流保护机制,返回错误结果。只要提供error错误处理机制。 为什么要限流: 1.用户增长过快(好事) 2.因为某个热点事件(微博热搜) 3.竞争对手爬虫 4.恶意的请求 限流算法: 1. 计算器算法: 计数器算法是限流算法里最简单也是最容易实现的一种算法。比如我们规定,对于 A 接口来说,我们 1 分钟的访问次数不能超过 100 个。那么我们可以这么做:在一开始的时候,我们可以设置一个计数器 counter,每当一个请求过来的时候,counter 就加 1,如果 counter 的值大于 100 并且该请求与第一个请求的间隔时间还在 1 分钟之内,触发限流;如果该请求与第一个请求的间隔时间大于 1 分钟,重置 counter 重新计数,但是有一个漏洞,如果我在0.59分发送100个请求,然后再1.00又发送100个请求, 那么其实这个用户在 1 秒里面,瞬间发送了 200 个请求。我们刚才规定的是 1 分钟最多 100 个请求,也就是每秒钟最多 1.7 个请求,用户通过在时间窗口的重置节点处突发请求, 可以瞬间超过我们的速率限制。用户有可能通过算法的这个漏洞,瞬间压垮我们的应用。 2.漏铜算法: 漏桶算法其实也很简单,可以粗略的认为就是注水漏水的过程,往桶中以任意速率流入水,以一定速率流出水,当水超过桶流量则丢弃,因为桶容量是不变的,保证了整体的速率。但是无法应对突发情况,忽然间很多的请求拥入,然后就会丢失很多的请求。 漏桶算法其实也很简单,可以粗略的认为就是注水漏水的过程,往桶中以任意速率流入水,以一定速率流出水,当水超过桶流量则丢弃,因为桶容量是不变的,保证了整体的速率。但是无法应对突发情况,忽然间很多的请求拥入,然后就会丢失很多的请求。 3.令牌桶算法: 令牌桶算法是对漏桶算法的一种改进,漏桶算法能够限制请求调用的速率,而令牌桶算法能够在限制调用的平均速率的同时还允许一定程度的突发调用。在令牌桶算法中,存在一个桶,用来存放固定数量的令牌。算法中存在一种机制,以一定的速率往桶中放令牌。每次请求调用需要先获取令牌,只有拿到令牌,才有机会继续执行,否则选择选择等待可用的令牌、或者直接拒绝。放令牌这个动作是持续不断的进行,如果桶中令牌数达到上限,就丢弃令牌。 Zuul 内部使用 Ratelimit 组件实现限流,使用的就是该算法,大概描述如下: 所有的请求在处理之前都需要拿到一个可用的令牌才会被处理; 根据限流大小,设置按照一定的速率往桶里添加令牌; 桶设置最大的放置令牌限制,当桶满时、新添加的令牌就被丢弃或者拒绝; 请求到达后首先要获取令牌桶中的令牌,拿着令牌才可以进行其他的业务逻辑,处理完业务逻辑之后,将令牌直接删除; 令牌桶有最低限额,当桶中的令牌达到最低限额的时候,请求处理完之后将不会删除令牌,以此保证足够的限流。 网关调优: 当请求通过 Zuul 网关路由到服务,并等待服务返回响应,这个过程中 Zuul 也有超时控制。Zuul 的底层使用的是 Hystrix + Ribbon 来实现请求路由。 当请求通过 Zuul 网关路由到服务,并等待服务返回响应,这个过程中 Zuul 也有超时控制。Zuul 的底层使用的是 Hystrix + Ribbon 来实现请求路由。 Zuul 中的 Hystrix 内部使用线程池隔离机制提供请求路由实现,其默认的超时时长为 1000 毫秒。Ribbon 底层默认超时时长为 5000 毫秒。如果 Hystrix 超时,直接返回超时异常。如果 Ribbon 超时,同时 Hystrix 未超时,Ribbon 会自动进行服务集群轮询重试,直到 Hystrix 超时为止。如果 Hystrix 超时时长小于 Ribbon 超时时长,Ribbon 不会进行服务集群轮询重试。