新建服务怎么配置zuul
‘壹’ springcloud执行流程
1.Servlet
zuul.servletPath默认配置为/zuul,故请求为/zuul开头的会跳过dispatcherServlet直接进入ZuulServlet,该配置可以自定义配置,例如用于大文件上传
2.ZuulServlet中service方法
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
try {
this.init((HttpServletRequest)servletRequest, (HttpServletResponse)servletResponse);
RequestContext context = RequestContext.getCurrentContext();
context.setZuulEngineRan();
try {
//运行pre过滤器
this.preRoute();
} catch (ZuulException var12) {
//有异常,执行errorFilter
this.error(var12);
//再执行postFilter
this.postRoute();
return;
}
try {
//运行rote过滤器
this.route();
} catch (ZuulException var13) {
//有异常,执行errorFilter
this.error(var13);
//再执行postFilter
this.postRoute();
return;
}
try {
//运行post过滤器
this.postRoute();
} catch (ZuulException var11) {
//有异常,执行errorFilter
this.error(var11);
}
} catch (Throwable var14) {
this.error(new ZuulException(var14, 500, "UNHANDLED_EXCEPTION_" + var14.getClass().getName()));
} finally {
RequestContext.getCurrentContext().unset();
}
}
3.FilterProcessor
其运行交由FilterProcessor中的方法runFilters,根据service中的顺序,取不同的filter类型,执行其中的run方法
public Object runFilters(String sType) throws Throwable {
if (RequestContext.getCurrentContext().debugRouting()) {
Debug.addRoutingDebug("Invoking {" + sType + "} type filters");
}
boolean bResult = false;
List<ZuulFilter> list = FilterLoader.getInstance().getFiltersByType(sType);
if (list != null) {
for(int i = 0; i < list.size(); ++i) {
ZuulFilter zuulFilter = (ZuulFilter)list.get(i);
Object result = this.processZuulFilter(zuulFilter);//见下面zuulFilter的runFilter()
if (result != null && result instanceof Boolean) {
bResult |= ((Boolean)result).booleanValue();
}
}
}
return bResult;
}
zuulFilter的runFilter方法,当filter的shouldFilter()返回true时才执行run()方法
public ZuulFilterResult runFilter() {
ZuulFilterResult zr = new ZuulFilterResult();
if (!this.isFilterDisabled()) {
if (this.shouldFilter()) {
Tracer t = TracerFactory.instance().startMicroTracer("ZUUL::" + this.getClass().getSimpleName());
try {
Object res = this.run();
zr = new ZuulFilterResult(res, ExecutionStatus.SUCCESS);
} catch (Throwable var7) {
t.setName("ZUUL::" + this.getClass().getSimpleName() + " failed");
zr = new ZuulFilterResult(ExecutionStatus.FAILED);
zr.setException(var7);
} finally {
t.stopAndLog();
}
} else {
zr = new ZuulFilterResult(ExecutionStatus.SKIPPED);
}
}
return zr;
}
4.获取过滤器FilterRegistry
其中的属性private final ConcurrentHashMap<String, ZuulFilter> filters = new ConcurrentHashMap();
保存所有的过滤器
例子中有12个(其中有两个为自定义的):
[org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter@3dc68586,
org.springframework.cloud.netflix.zuul.filters.pre.Servlet30WrapperFilter@4001d8c1,
org.springframework.cl
‘贰’ 微服务核心组件 Zuul 网关原理剖析
Zuul 网关是具体核心业务服务的看门神,相比具体实现业务的系统服务来说它是一个边缘服务,主要提供动态路由,监控,弹性,安全性等功能。在分布式的微服务系统中,系统被拆为了多套系统,通过zuul网关来对用户的请求进行路由,转发到具体的后台服务系统中。
本 Chat 主要内容如下:
网关是具体核心业务服务的看门神,相比具体实现业务的系统服务来说它是一个边缘服务,主要提供动态路由,监控,弹性,安全性等功能,下面我们从单体应用到多体应用的演化过程来讲解网关的演化历程。
一般业务系统发展历程都是基本相似的,从单体应用到多应用,从本地调用到远程调用。对应单体应用架构模式(如下图1),由于只需一个应用,所有业务模块的功能都打包为了一个 War 包进行部署,这样可以减少机器资源和部署的繁琐。
图1 单体应用
在单体应用中,网关模块是和应用部署到同一个jvm进程里面的,当外部移动设备或者web站点访问单体应用的功能时候,请求是先被应用的网关模块拦截的,网关模块对请求进行鉴权、限流等动作后在把具体的请求转发到当前应用对应的模块进行处理。
随着业务的发展,网站的流量会越来越大,在单体应用中简单的通过加机器的方式可以带来的承受流量冲击的能力也越来越低,这时候就会考虑根据业务将单体应用拆成若干个功能独立的应用,单体应用拆为多个应用后,由于不同的应用开发对应的功能,所以多应用开发之间可以独立开发而不用去理解对方的业务,另外不同的应用模块只承受对应业务流量的压力,不会对其他应用模块造成影响,这时候多体的分布式系统就出现了,如下图2。
图2 多体应用
如上图在多体应用中业务模块A和B单独起了个应用,每个应用里面有自己的网关模块,如果业务模块多了,那么每个应用都有自己的网关模块,这样复用性不好,所以可以考虑把网关模块提起出来,单独作为一个应用来做服务路由,如下图3:
如上图当移动设备发起请求时候是具体发送到网关应用的,经过鉴权后请求会被转发到具体的后端服务应用上,对应前端移动设备来说他们不在乎也不知道后端服务器应用是一个还是多个,他们只能感知到网关应用的存在。
Zuul是Netflix开源的一个网关组件,在Netflix内部系统中Zuul被用来作为内部系统的门面,如下图是Zuul在Netflix内部使用的一个架构图:
如上图最上层的移动设备或者网站首先通过aws负载均衡器把请求路由到zuul网关上,zuul网关则负责把请求路由到具体的后端service上。
Zuul开源地址 https://github.com/Netflix/zuul
Zuul网关的核心是一系列的过滤器,这些过滤器可以对请求或者响应结果做一系列过滤,Zuul 提供了一个框架可以支持动态加载,编译,运行这些过滤器,这些过滤器是使用责任链方式顺序对请求或者响应结果进行处理的,这些过滤器直接不会直接进行通信,但是通过责任链传递的RequestContext参数可以共享一些东西。
虽然Zuul 支持任何可以在jvm上跑的语言,但是目前zuul的过滤器只能使用Groovy脚本来编写。编写好的过滤器脚本一般放在zuul服务器的固定目录,zuul服务器会开启一个线程定时去轮询被修改或者新增的过滤器,然后动态进行编译,加载到内存,然后等后续有请求进来,新增或者修改后的过滤器就会生效了。
在zuul中过滤器分为四种:
如下图为zuul1.0的工作原理:
如上图,当zuul接受到请求后,首先会由前置过滤器进行处理,然后在由路由过滤器具体把请求转发到后端应用,然后在执行后置过滤器把执行结果写会到请求方,当上面任何一个类型过滤器执行出错时候执行该过滤器。
本节作者使用zuul的版本:
...
....
总结:zuul1.0时候当zuul接受到一个请求后会同步执行前置过滤器、路由过滤器、后置过滤器,等执行完毕后在同步把结果返回为调用方,调用方在整个过程中是阻塞的。其实SpringBoot集成的zuul就是自己实现了个前置过滤器做选择路由,然后自己实现了个路由过滤器根据前置过滤器选择的路由具体做路由转发。
Netty作为高性能异步网络通讯框架,在bbo,rocketmq,sofa等知名开源框架中都有使用,如下图zuul2.0使用netty server作为网关监听服务器监听客户端发来的请求,然后把请求转发到前置过滤器(inbound filters)进行处理,处理完毕后在把请求使用netty client代理到具体的后端服务器进行处理,处理完毕后在把结果交给后者过滤器(outbound filters)进行处理,然后把处理结果通过nettyServer写回客户端。
...
总: 在zuul1.0时候客户端发起的请求后需要同步等待zuul网关返回,zuul网关这边对每个请求会分派一个线程来进行处理,这会导致并发请求数量有限。而zuul2.0使用netty作为异步通讯,可以大大加大并发请求量。
‘叁’ Zuul 路由中怎么配置多个地址
第一步:设置路由器无线参数:1、确定SSID并固定信道登录主路由器的管理界面,进入无线设置>>基本设置,在该页面确认SSID(无线名称),并固定信道,并点击保存。
至此无线WDS桥接设置完成,副路由器下的无线终端连接到zhangsan,可以正常访问网络。终端移动过程中,可以实现主、副路由器间的自动漫游。
‘肆’ zuul网关的作用配置Druid监控
1.统一入口:未全部为服务提供一个唯一的入口,网关起到外部和内部隔离的作用,保障了后台服务的安全性。2.鉴权校验:识别每个请求的权限,拒绝不符合要求的请求。3.动态路由:动态的将请求路由到不同的后端集群中。4.减少客户端与服务端的耦合:服务可以独立发展,通过网关层来做映射
‘伍’ 微服务框架之Spring Cloud简介
在了解 Spring Cloud 之前先了解一下微服务架构需要考量的核心关键点,如下图:
对于以上等核心关键点的处理,不需要我们重复造车轮, Spring Cloud 已经帮我们集成了,它使用 Spring Boot 风格将一些比较成熟的微服务框架组合起来,屏蔽掉了复杂的配置和实现原理,为快速构建微服务架构的应用提供了一套基础设施工具和开发支持。
Spring Cloud 所提供的核心功能包含:
Spring Cloud架构图
Spring Cloud子项目
Spring Cloud 旗下的子项目大致可以分为两类:
如下:
1. Spring Cloud 与 Spring Boot
Spring Boot 可以说是微服务架构的核心技术之一。通过在 Spring Boot 应用中添加 Spring MVC 依赖,就可以快速实现基于 REST 架构的服务接口,并且可以提供对 HTTP 标准动作的支持。而且 Spring Boot 默认提供 JackJson 序列化支持,可以让服务接口输入、输出支持 JSON 等。因此,当使用 Spring Cloud 进行微服务架构开发时,使用 Spring Boot 是一条必经之路。
2. Spring Cloud 与服务治理( Eureka )
服务治理是 Spring Cloud 的核心,在实现上其提供了两个选择,即 Consul 和 Netflix 的 Eureka 。
Eureka 提供了服务注册中心、服务发现客户端,以及注册服务的 UI 界面应用。
在 Eureka 的实现中,节点之间相互平等,有部分注册中心“挂掉”也不会对整个应用造成影响,即使集群只剩一个节点存活,也可以正常地治理服务。即使所有服务注册节点都宕机, Eureka 客户端中所缓存的服务实例列表信息,也可让服务消费者能够正常工作,从而保障微服务之间互相调用的健壮性和应用的弹性。
3. Spring Cloud 与客户端负载均衡( Ribbon )
Ribbon 默认与 Eureak 进行无缝整合,当客户端启动的时候,从 Eureka 服务器中获取一份服务注册列表并维护在本地,当服务消费者需要调用服务时, Ribbon 就会根据负载均衡策略选择一个合适的服务提供者实例并进行访问。
Spring Cloud 通过集成 Netflix 的 Feign 项目,为开发者提供了声明式服务调用,从而简化了微服务之间的调用处理方式。并且默认 Feign 项目集成了 Ribbon ,使得声明式调用也支持客户端负载均衡功能。
4. Spring Cloud 与微服务容错、降级( Hystrix )
为了给微服务架构提供更大的弹性,在 Spring Cloud 中,通过集成 Netflix 下子项目 Hystrix ,通过所提供的 @HystrixCommand 注解可以轻松为我们所开发的微服务提供容错、回退、降级等功能。此外, Hystrix 也默认集成到 Feign 子项目中。
Hystrix 是根据“断路器”模式而创建。当 Hystrix 监控到某服务单元发生故障之后,就会进入服务熔断处理,并向调用方返回一个符合预期的服务降级处理( fallback ),而不是长时间的等待或者抛出调用异常,从而保障服务调用方的线程不会被长时间、不必要地占用,避免故障在应用中的蔓延造成的雪崩效应。
而 Hystrix 的仪表盘项目( Dashboard )可以监控各个服务调用所消耗的时间、请求数、成功率等,通过这种近乎实时的监控和告警,可以及时发现系统中潜在问题并进行处理。
5. Spring Cloud 与服务网关( Zuul )
Spring Cloud 通过集成 Netflix 中的 Zuul 实现 API 服务网关功能,提供对请求的路由和过滤两个功能
路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础。
过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。
通过 Zuul ,可以将细粒度的服务组合起来提供一个粗粒度的服务,所有请求都导入一个统一的入口,对外整个服务只需要暴露一个 API 接口,屏蔽了服务端的实现细节。通过 Zuul 的反向代理功能,可以实现路由寻址,将请求转发到后端的粗粒度服务上,并做一些通用的逻辑处理。此外, Zuul 默认会与 Eureka 服务器进行整合,自动从 Eureka 服务器中获取所有注册的服务并进行路由映射,实现 API 服务网关自动配置。
6. Spring Cloud 与消息中间件( Stream )
Spring Cloud 为简化基于消息的开发,提供了 Stream 子项目,通过建立消息应用抽象层,构建了消息收发、分组消费和消息分片等功能处理,将业务应用中的消息收发与具体消息中间件进行解耦,使微服务应用开发中可以非常方便地与 Kafka 和 RabbitMQ 等消息中间件进行集成。
Spring Cloud Bus 基于 Stream 进行扩展,可以作为微服务之间的事件、消息总线,用于服务集群中状态变化的传播。
比如 Spring Cloud Config 借助 Bus ,可以实现配置的动态刷新处理。
7. Spring Cloud 与分布式配置中心( Config )
针对微服务架构下的配置文件管理需求, Spring Cloud 提供了一个 Config 子项目。 Spring Cloud Config 具有中心化、版本控制、支持动态更新和语言独立等特性。
在 Config 子项目中将微服务应用分为两种角色:配置服务器( Config Server )和配置客户端( Config Client )。使用配置服务器集中地管理所有配置属性文件,配置服务中心可以将配置属性文件存储到 Git 、 SVN 等具有版本管理仓库中,也可以存放在文件系统中。默认采用 Git 的方式进行存储,因此可以很容易地对配置文件进行修改,并实现版本控制。
8. Spring Cloud 与微服务链路追踪( Sleuth )
Spring Cloud 中的 Sleuth 子项目为开发者提供了微服务之间调用的链路追踪。
Sleuth 核心思想就是通过一个全局的 ID 将分布在各微服务服务节点上的请求处理串联起来,还原了调用关系,并借助数据埋点,实现对微服务调用链路上的性能数据的采集。
因此,通过 Sleuth 可以很清楚地了解到一个用户请求经过了哪些服务、每个服务处理花费了多长时间,从而可以对用户的请求进行分析。此外,通过将采集的数据发送给 Zipkin 进行存储、统计和分析,从而可以实现可视化的分析和展示,帮助开发者对微服务实施优化处理。
9. Spring Cloud 与微服务安全( Security )
Spring Cloud Security 为我们提供了一个认证和鉴权的安全框架,实现了资源授权、令牌管理等功能,同时结合 Zuul 可以将认证信息在微服务调用过程中直接传递,简化了我们进行安全管控的开发。
Spring Cloud Security 默认支持 OAuth 2.0 认证协议,因此单点登录也可以非常容易实现,并且 OAuth2.0 所生成的令牌可以使用 JWT 的方式,进一步简化了微服务中的安全管理。
10. Spring Cloud 的其他子项目
‘陆’ SpringCloud服务网关Zuul分析①分发
在SpringCloud中充当服务网关的角色,它包含了鉴权、流量转发、请求统计等等功能
Filter是Zuul的核心,用来实现对外服务的控制。Filter的生命周期有4个,分别是 “PRE”、“ROUTING”、“POST”、“ERROR” ,整个生命周期可以用下图来表示。
PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
ROUTING: 这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
POST: 这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
ERROR: 在其他阶段发生错误时执行该过滤器。 除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。
根据场景需要,我们也可以自定义一些filter,穿插在整个过程的某个阶段,只需要继承ZuulFilter,并且覆盖里面的4个方法就可以了.
application.properties中配置:
# 禁用一些Filter的配置:
zuul.FormBodyWrapperFilter.pre.disable= true
# 路由的配置:
# 配置需要被跳转的地址,/user/**的网址将被分发
zuul.routes.user.path=/user/**
# 重定向的地址:
zuul.routes.user.url=http://127.0.0.1:8081/
‘柒’ spring cloud 中的zuul怎么保证自身高可用
zuul多个节点启动,自身也可以作为服务,注册到eureka上。
或者也可以一组节点配置为upstream,通过nginx的负载均衡分布。
后面一种方式需要自己开发监控插件,在节点出错的时候,自动修改nginx的配置并reload,通过这个方式把节点去掉。在节点恢复之后,通过同样的方式重新挂载上去。
‘捌’ Zuul配置项中sensitiveHeaders和ignoredHeaders的不同
路由是微服务架构的不可或缺的一部分。例如:”/” 可能映射到你应用主页,/api/users映射到用户服务,/api/shop映射到购物服务。Zuul。Zuul是Netflix出品的一个基于JVM路由和服务端的负载均衡器。
Netflix uses Zuul for the following: * Authentication * Insights * Stress Testing * Canary Testing * Dynamic Routing * Service Migration * Load Shedding * Security * Static Response handling * Active/Active traffic management
Zuul的规则和过滤器允许使用各种基于JVM的语言,支持基于Java和Groovy。
注意:zuul.max.host.connections已经被两个新的属性替代:zuul.host.maxTotalConnections 和 zuul.host.maxPerRouteConnections,默认分别为200和20.
注意:默认所有routes的Hystrix隔离模式(ExecutionIsolationStrategy)是SEMAPHORE zuul.ribbonIsolationStrategy可以改为THREAD,如果这个隔离模式更好。
org.springframework.cloud and artifact id spring-cloud-starter-zuul。See the Spring Cloud Project page for details。
当一个UI应用想要代理调用一个或者多个后台服务的时候,Sping cloud创建了一个嵌入的Zuul proxy很方便的开发一个简单的案例。这个功能对于代理前端需要访问的后端服务非常有用,避免了所有后端服务需要关心管理CORS和认证的问题.
在Spring Boot主函数上通过注解 @EnableZuulProxy 来开启, 这样可以让本地的请求转发到适当的服务. 按照约定, 一个ID为”users”的服务会收到 /users 请求路径的代理请求(前缀会被剥离). Zuul使用Ribbon定位服务注册中的实例, 并且所有的请求都在hystrix的command中执行, 所以失败信息将会展现在Hystrix metrics中, 并且一旦断路器打开, 代理请求将不会尝试去链接服务.
注意:Zuul starter没有包含服务发现的客户端, 所以对于路由你需要在classpath中提供一个根据service IDs做服务发现的服务.(例如, eureka是一个不错的选择)
‘玖’ 服务网关Zuul
在前面的学习中,我们使用Spring Cloud实现微服务的架构基本成型,大致是这样的:
我们使用Spring Cloud Netflix中的Eureka实现了服务注册中心以及服务注册与发现;而服务间通过Ribbon或Feign实现服务的消费以及负载均衡;为了使得服务集群更为健壮,使用Hystrix的熔断机制 来避免在微服务架构中个别服务出现异常时引起的故障蔓延。
在该架构中,我们的服务集群包括:内部服务Service A和Service B,他们都会注册与订阅服务至Eureka Server,而Open Servc时一个对外的服务,通过负载均衡公开至服务调用方。我们把焦点聚集在对外服务这块,这种实现方式是否合理,有没有更好的实现方式呢?
这种架构不足之处:
对于上面的问题,最好的解决方法是——服务网关。
为了解决上面的问题,我们需要将权限控制这样的东西从我们的服务单元中抽离出去,而最适合这些逻辑的地方就是处于对外访问最前端的地方,我们需要一个更加强大的负载均衡器——服务网关。
服务网关是微服务架构中不可或缺的的部分。通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由、负载均衡之外,它还具备了权限控制等功能。Spring Cloud NetFlix中的Zuul就具备这样的功能。
Zuul是NetFlix开源的微服务网关,它可以和Eureka、Ribbon、Hystrix等组件配合使用。Zuul的核心是一些列的过滤器,这些过滤器可以完成以下功能。
Spring Cloud对Zuul进行了整合与增强。目前,Zuul使用的默认HTTP客户端是Apache HTTP Client,也可以使用使用其他的。
使用Zuul之后的架构如图所示:
从图中可以看出,客户端请求微服务时,先经过Zuul之后再请求,这样就可以将一些类似于校验的业务逻辑放到zuul中去完成,而微服务本身只需要关注自己的业务逻辑即可。
首先新建一个gateway模块,并且导入相关的依赖
然后再编写启动类增加@EnableZuulProxy注解。
接着编写application.yml文件,并添加路由规则
然后启动测试,发现可以通过zuul访问到商品微服务地址
在上面的配置中,我们通过路由规则的配置,访问到了商品微服务。但是如果商品微服务的地址发生变化,我们要修改配置问题。所以,我们应该通过走Eureka注册中心来获取地址。首先,我们需要添加Eureka依赖。
然后修改application.yml配置文件,将自己注册到注册中心。
随后,通过测试发现可以通过zuul访问商品微服务,一切正常。
过滤器是Zuul的重要组件。在我们的一般的单体应用中,也会使用过滤器过滤请求,或者完成相关的权限配置等,例如shiro框架就是用过滤器管理权限的。Zuul中的过滤器名为ZuulFilter:
ZuulFilter是一个抽象类,其实现类需要实现4个方法:
过滤器的执行流程如图所示:
需求:通过编写过滤器实现用户是否登录的检查
实现:通过判断请求中是否有token,如果有认为就是已经登录的,如果没有就认为时非法请求,响应401.
接下来,我们需要编写一个UserLoginZuulFilter,逻辑如下:
随后,我们打开浏览器进行测试,可以看到过滤器已经生效:
‘拾’ zuul+websocket+sockjs
需要实现前端页面->zuul网关->消息服务,建立websocket连接
使用 spring-cloud-netflix-zuul-websocket 实现zuul网关层对websocket的转发;
注意事项:
1.前端使用sockjs,注意地址前缀
2.后端注意开启跨域和指定sockjs协议:
3.zuul层配置:
注意:
参考: