Spring-Cloud-Netflix-Zuul
Spring Cloud Zuul 笔记
Zuul 是 Netflix 开源的微服务网关,它可以和 Eureka, Ribbon, Hystrix 等组件配合使用。Zuul 的核心是一系列的过滤器,这些过滤器帮助我们实现路由转发和认证等功能。
Netflix / zuul
https://github.com/Netflix/zuul
API网关选型
为什么需要API网关?
微服务架构中,如果没有 API 网关,鉴权、限流、统计、监控等通用功能需要在每个服务中单独实现,带来大量重复工作。
API 网关的作用就是把这些公共的功能抽取出来放到网关层实现,使得每个微服务只需要关心自身的业务逻辑。
API网关选型考虑
APISIX 作者温铭《API 网关的选型和持续集成》中提到的选型考虑:
1、路由配置
类似 nginx 中的 location 配置。考虑是否支持动态配置?是否支持四层路由和七层路由?路由表如何组织遍历,是list还是tree?
2、插件扩展
如何编写插件,什么语言?是否支持热加载?
3、存储
路由等配置如何存储?放关系数据库还是内存kv?(kong放postgres,apisix是放etcd)
API网关常用架构方案
基于 Nginx+Lua+ OpenResty 的方案,Kong,orange 都是基于这个方案
基于 Netty、非阻塞IO模型。 通过网上搜索可以看到国内的宜人贷等一些公司是基于这种方案,是一种成熟的方案。
基于 Node.js 的方案。 这种方案是应用了 Node.js 天生的非阻塞的特性。
基于 java Servlet 的方案。 zuul 基于的就是这种方案,这种方案的效率不高,这也是 zuul 总是被诟病的原因。
开源产品
kong
一、功能
1、实现:基于 OpenResty(ngnix+lua)
2、路由配置:支持动态api路由配置。定期5秒轮询加载。
3、存储:PostgreSQL 或 Cassandra
4、管理界面:Kong dashboard
二、性能
借助于 Nginx 的事件驱动模型和非阻塞 IO, 性能优异。
OpenResty 和 kong 性能相近,大概是直连的 60%~70%
三、扩展性
编写lua脚本扩展,但不支持热加载。
优势:
劣势:需要专门的运维人员去维护
zuul
一、功能
1、实现:基于 Java Servlet 实现,集成在 Spring Boot 微服务内。
2、路由配置:Spring Boot 配置文件形式,搭配配置中心(比如Archaius)可做动态配置。
3、存储:无单独存储,Spring Boot 配置文件或配置中心。
4、无自带控制台,需要搭配其他组件
5、限流:编写 filter 实现,单机或分布式。
二、性能:
zuul 1.x 采用阻塞 IO 和多线程方式,即一个线程处理一次连接请求,当出现问题时,如后端延迟或设备错误重试,活跃的连接和线程数量会增加,这会加大服务器负载并可能使集群无法承受,性能损失较大。
zuul 2.x 多路复用 IO reactor 模式(netty)。zuul 2.x 和 Spring Cloud Gateway 性能相近,大概为直连的 40%
三、扩展性
zuul: Java 代码编写的 filter 不支持热加载。groovy 编写的 filter 支持热加载(轮询)。
四、选型考虑
zuul 1.x 的优势是基于 Srping Cloud 生态,但从 2018.12 开始 Spring Cloud netflix 组件已进入维护模式,此部分优势丢失。且由于 zuul 1.x 严重的性能问题,不建议使用。
Spring Cloud 网关组件主推 Spring Cloud Gateway, 无 zuul 2.x 集成计划。
zuul 2.x 不断跳票,性能低于 Spring Cloud Gateway, Spring 微服务中无特殊需求不推荐使用 zuul 2.x.
Spring Cloud Gateway
一、功能
1、实现:基于 Spring 5.x + Spring Boot 2.x + Reactor 实现,响应式的、非阻塞式的 API
二、性能
三、扩展性
四、选型考虑
zuul工作流程
在 zuul 中, 整个请求的过程是这样的,首先将请求给 zuulservlet 处理,zuulservlet 中有一个 zuulRunner 对象,该对象中初始化了 RequestContext 作为存储整个请求的一些数据,并被所有的 zuulfilter 共享。zuulRunner 中还有 FilterProcessor, FilterProcessor 作为执行所有的 zuulfilter 的管理器。FilterProcessor 从 filterloader 中获取 zuulfilter, 而 zuulfilter 是被 filterFileManager 所加载,并支持 groovy 热加载,采用了轮询的方式热加载。有了这些 filter 之后,zuulservelet 首先执行的 Pre 类型的过滤器,再执行 route 类型的过滤器,最后执行的是 post 类型的过滤器,如果在执行这些过滤器有错误的时候则会执行 error 类型的过滤器。执行完这些过滤器,最终将请求的结果返回给客户端。
Spring Boot 中启用 Zuul
maven 添加依赖:
<dependencyManagement>
<dependencies>
<!-- 管理Spring Cloud生态各组件的版本 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency<name />
</dependencies>
</dependencyManagement>
<!-- Netflix Zuul 微服务网关 -->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
应用主类使用 @EnableZuulProxy
注解开启Zuul
@EnableZuulProxy
@SpringCloudApplication
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
EnableZuulProxy 源码如下
package org.springframework.cloud.netflix.zuul;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.context.annotation.Import;
@EnableCircuitBreaker
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ZuulProxyMarkerConfiguration.class)
public @interface EnableZuulProxy {
}
路由转发
application.properties
zuul.routes.route-name.path: /backend/**
zuul.routes.route-name.url: http://localhost:${server.port}
或 application.yml
zuul:
routes:
route-name:
path: /backend/**
url: http://localhost:${server.port}
其中 route-name 是路由的名字,可以任意定义,每个路由规则由一个 path 和一个 url 组成, 匹配path的请求会被转发到 url
之后,所有 /backend/**
的请求都会自动转发到 http://localhost:${server.port}
过滤器
定义过滤器只需要继承 ZuulFilter
抽象类实现其定义的四个抽象函数就可对请求进行拦截与过滤。
filterType()
:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:
PRE
:该类型的filters在Request routing到源web-service之前执行。可以进行一些权限认证,日志记录,或者额外给Request增加一些属性供后续的filter使用;ROUTING
:该类型的filters用于把Request routing到源web-service,源web-service是实现业务逻辑的服务。这里使用HttpClient请求web-service; 一般用于构建发送给微服务的请求,并使用Apache HttpClient或Netflix Ribbon构建和发送原始HTTP请求的位置。POST
:该类型的filters在ROUTING返回Response后执行。用来实现对Response结果进行修改,收集统计数据以及把Response传输会客户端;ERROR
:上面三个过程中任何一个出现错误都交由ERROR类型的filters进行处理。
filterOrder()
:通过int值来定义过滤器的执行顺序
shouldFilter()
:返回一个boolean类型来判断该过滤器是否要执行,所以通过此函数可实现过滤器的开关。
run()
:过滤器的具体逻辑。需要注意,这里我们通过ctx.setSendZuulResponse(false)令zuul过滤该请求,不对其进行路由,然后通过ctx.setResponseStatusCode(401)设置了其返回的错误码,当然我们也可以进一步优化我们的返回,比如,通过ctx.setResponseBody(body)对返回body内容进行编辑等。
服务网关Spring Cloud Zuul(Finchley版本)
https://www.jianshu.com/p/f5cdce29890d
跟我学Spring Cloud(Finchley版)-16-Zuul
http://www.itmuch.com/spring-cloud/finchley-16/
Spring Cloud构建微服务架构(五)服务网关(Brixton版,比较老旧)
http://blog.didispace.com/springcloud5/
Spring Cloud 4.8 Router and Filter: Zuul (路由配置讲的比较多)
https://my.oschina.net/roccn/blog/826655
上一篇 Raft分布式一致性算法
下一篇 SSO单点登录
页面信息
location:
protocol
: host
: hostname
: origin
: pathname
: href
: document:
referrer
: navigator:
platform
: userAgent
: