Spring Cloud Zuul 快速入门
2021-07-03 17:07
标签:component ade proc bootstrap depend 监控 性能 auto pattern 为什么要有服务网关: 我们都知道在微服务架构中,系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?难道要一个个的去调用吗?很显然这是不太实际的,我们需要有一个统一的接口与这些微服务打交道,这就是我们需要服务网关的原因。 我们已经知道,在微服务架构中,不同的微服务可以有不同的网络地址,各个微服务之间通过互相调用完成用户请求,客户端可能通过调用N个微服务的接口完成一个用户请求。比如:用户查看一个商品的信息,它可能包含商品基本信息、价格信息、评论信息、折扣信息、库存信息等等,而这些信息获取则来源于不同的微服务,诸如产品系统、价格系统、评论系统、促销系统、库存系统等等,那么要完成用户信息查看则需要调用多个微服务,这样会带来几个问题: 如下图所示: 我们该如何解决这些问题呢?我们可以尝试想一下,不要让前端直接知道后台诸多微服务的存在,我们的系统本身就是从业务领域的层次上进行划分,形成多个微服务,这是后台的处理方式。对于前台而言,后台应该仍然类似于单体应用一样,一次请求即可,于是我们可以在客户端和服务端之间增加一个API网关,所有的外部请求先通过这个微服务网关。它只需跟网关进行交互,而由网关进行各个微服务的调用。 这样的话,我们就可以解决上面提到的问题,同时开发就可以得到相应的简化,还可以有如下优点: 这里可以联想到一个概念,面向对象设计中的门面模式,即对客户端隐藏细节,API网关也是类似的东西,只不过叫法不同而已。它是系统的入口,封装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、缓存、负载均衡、流量管控、路由转发等等。示意图: 总结一下,服务网关大概就是四个功能:统一接入、流量管控、协议适配、安全维护。而在目前的网关解决方案里,有Nginx+ Lua、Kong、Tyk以及Spring Cloud Zuul等等。这里以Zuul为例进行说明,它是Netflix公司开源的一个API网关组件,Spring Cloud对其进行二次封装做到开箱即用。同时,Zuul还可以与Spring Cloud中的Eureka、Ribbon、Hystrix等组件配合使用。 可以说,Zuul实现了两个功能,路由转发和过滤器: 服务网关的要素: Zuul的四种过滤器API: zuul前后置过滤器的典型应用场景: Zuul的核心是一系列过滤器,开发者通过实现过滤器接口,可以做大量切面任务,即AOP思想的应用。Zuul的过滤器之间没有直接的相互通信,而是通过本地ThreadLocal变量进行数据传递的。Zuul架构图: 在Zuul里,一个请求的生命周期: 本小节我们来学习如何使用服务网关,也就是Spring Cloud Zuul这个组件,首先新建一个项目,选择如下模块: pom.xml配置的依赖如下: 项目创建好后,将application.properties改为bootstrap.yml,编辑内容如下: 注:我这里使用了配置中心,若对此不熟悉的话,可以参考我另一篇文章:Spring Cloud Config - 统一配置中心 在启动类中,加上 完成以上配置后启动这个项目,我这里项目启动是正常的。然后我们来通过这个网关访问一下商品服务中获取商品列表的接口。如下: 访问地址说明: 只要是在eureka上注册的服务都能够通过zuul进行转发,例如我通过zuul来访问config的配置文件: 如上,可以看到,报错了,网关超时。这是因为默认情况下,zuul的熔断机制超时时间是2秒,当一个服务响应的时间较长就会报网关超时错误。 我们在配置文件中,加上如下超时时间的配置即可: ribbon.ReadTimeout, ribbon.SocketTimeout这两个就是ribbon超时时间设置,当在yml写时,应该是没有提示的,给人的感觉好像是不是这么配的一样,其实不用管它,直接配上就生效了。 还有zuul.host.connect-timeout-millis, zuul.host.socket-timeout-millis这两个配置,这两个和上面的ribbon都是配超时的。区别在于,如果路由方式是serviceId的方式,那么ribbon的生效,如果是url的方式,则zuul.host开头的生效。(此处重要!使用serviceId路由和url路由是不一样的超时策略) 如果你在zuul配置了熔断fallback的话,熔断超时也要配置,即hystrix那段配置。不然如果你配置的ribbon超时时间大于熔断的超时,那么会先走熔断,相当于你配的ribbon超时就不生效了。 现在重启项目,再次访问之前的地址,就不会出现网关超时的错误了: 之前我们访问的都是GET类型的接口,我们来看看POST类型的是否能够正常访问。如下: 每次请求某个服务的接口,都需要带上这个服务的名称。有没有办法可以自定义这个规则呢?答案是有的,在配置文件中,增加路由的自定义配置: 说明: 重启项目,测试如下: 在项目启动的时候,我们也可以在控制台中查看到zuul所有的路由规则: 如果我们有些服务的接口不希望对外暴露,只希望在服务间调用,那么就可以在配置文件中,增加路由排除的配置。例如我不希望 重启项目,这时访问就会报404了。如下: 还可以使用通配符进行匹配。如下示例: 我们在web开发中,经常会利用到cookie来保存用户的登录标识。但我们使用了zuul组件后,默认情况下,cookie是无法直接传递给服务的,因为cookie默认被列为敏感的headers。所以我们需要在配置文件中,将sensitiveHeaders的值置空。如下: 我们每次配置路由信息都需要重启项目,显得很麻烦,在线上环境也不能这样随便重启项目。所以我们得实现动态路由的功能,实现动态路由其实就利用一下我们之前实现的动态刷新配置文件的功能即可。首先把Zuul路由相关的配置剪切到git上,如下: 注:我这里使用了配置中心,若对此不熟悉的话,可以参考我另一篇文章:Spring Cloud Config - 统一配置中心 在pom.xml文件中,增加如下依赖项: 然后在bootstrap.yml中,增加rabbitmq的配置。如下: 最后在项目中创建一个config包,在该包中创建一个ZuulConfig配置类,用于加载配置文件中的配置。代码如下: 完成以上配置后,重启项目,即可实现动态路由了,例如我现在把myProduct改成yourProduct,如下: 此时无需重启项目,访问新的地址即可。如下: Spring Cloud Zuul 快速入门 标签:component ade proc bootstrap depend 监控 性能 auto pattern 原文地址:http://blog.51cto.com/zero01/2173327
Zuul:路由转发,排除和自定义
spring:
application:
name: api-gateway
cloud:
config:
discovery:
enabled: true
service-id: CONFIG
profile: dev
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
@EnableZuulProxy
注解,代码如下:package org.zero.springcloud.apigateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableZuulProxy
public class ApiGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}
}
/product
是需要访问的服务的名称/buyer/product/list
是商品服务中获取商品列表的接口地址zuul:
routes:
myProduct:
path: /myProduct/**
serviceId: product
listForOrder
被外部访问,则在配置文件中,增加如下配置即可:zuul:
...
ignored-patterns:
- /myProduct/buyer/product/listForOrder
- /product/buyer/product/listForOrder
zuul:
...
ignored-patterns:
- /**/buyer/product/listForOrder
Zuul:Cookie和动态路由
zuul:
...
routes:
myProduct:
path: /myProduct/**
serviceId: product
sensitiveHeaders: # 置空该属性的值即可
spring:
application:
name: api-gateway
cloud:
config:
discovery:
enabled: true
service-id: CONFIG
profile: dev
rabbitmq:
host: 127.0.0.1
port: 5672
username: admin
password: admin
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
package org.zero.springcloud.apigateway.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.stereotype.Component;
/**
* @program: api-gateway
* @description: 网关路由配置类
* @author: 01
* @create: 2018-08-25 15:51
**/
@Component
public class ZuulConfig {
@RefreshScope
@ConfigurationProperties("zuul")
public ZuulProperties zuulProperties(){
return new ZuulProperties();
}
}
Zuul的高可用