zuul使用

本文介绍了Spring Cloud中使用Zuul实现服务网关的相关内容。服务网关可解决前端调用后端多微服务的复杂性及权限认证问题。详细阐述了Zuul的实现功能,如查看路由和过滤器信息、忽略微服务、配置路由前缀等,还说明了代码结构、编写方法及功能实现的具体配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

感谢来源https://huan1993.iteye.com/blog/2424676

我们知道我们前台要展示数据给用户看,这中间可能涉及到从后端的多个微服务进行获取数据。比如获取用户信息需要用到用户微服务、获取商品信息需要获取商品微服务、创建订单需要调用订单微服务,而各个微服务可能分布在各个机器上,前端要获取到数据就必须要知道各个微服务的地址,这给前端增加开发的复杂性。一段后端的某个微服务地址改变了,前端可能还要修改。而且后端各个微服务权限认证也不好认证,那么有没有一种好的解决办法呢?服务网关就正好可以解决这个问题,在 spring cloud 中使用的就是zuul来实现服务网关。我们来看一下有了服务网关后,前端程序调用后端服务。

    由上可知,当存在服务网关,前端程序通过服务网关调用后台服务,同时我们也可以在网关层进行各种操作,比如限流、权限校验等。

 

实现功能

      1、查看 zuul 中配置好的路由和过滤器信息

      2、忽略所有微服务或某些微服务

      3、忽略所有为服务,只路由指定的微服务

      4、通过path和url访问到具体的某台机器上

      5、脱离eureka进行访问,并使之具有负载均衡和隔离的机制等

      6、转发前是否去掉路由前缀

      7、为所有路由都增加一个通过的前缀

      8、忽略某些路径不进行路由

      9、敏感头的传递(比如Cookie等)全局设置和某个微服务设置

     10、忽略头

     11、spring security 在classpath 下会忽略的头

     12、本地调换和路由的优先级

     13、配置网关超时

     14、重写 Location 头

     15、文件上传处理

 

代码结构

 

Java代码 

 收藏代码

  1. eureka-server  
  2.     |- 服务注册中心  
  3.     zuul  
  4.         product-provider-8202  
  5.         product-provider-8203  
  6.             |- 服务提供者  
  7.         product-consumer-8201  
  8.             |- 服务消费者  
  9.         product-gateway-8204  
  10.             |- 网关程序,演示网关路由的各种配置  

 

代码编写

一、服务提供者、服务消费者、注册中心,没有什么需要特别注意的,略。

二、服务网关的编写

       1、创建网关工程

       2、引入 zuul 的依赖

       3、启动类上增加 @EnableZuulProxy 注解

       4、yml 文件上注册到 eureka 上

 

三、eureka服务启动界面

功能实现

 1、查看 zuul 中配置好的路由和过滤器信息

      当我们启动了zuul 的网关之后,想知道当前zuul代理了那些路由,访问的路径又是那些或者我们自己写了一个zuul的filter,想知道它当前位于zuul的filter的那个位置时,该如何查询。

       访问路径: http://网关地址:端口/routes  访问路由的简单信息

                          http://网关地址:端口/routes?format=details  访问路由的详细信息

                          http://网关地址:端口/filters 访问zuul中使用了那些过滤器。

       yml文件配置:

Yml代码 

 收藏代码

  1. management:  
  2.   security:  
  3.     enabled: false  # 默认值是 true, 为true的话那么页面上可能会报没有权限访问  

       不进行配置,访问上面的2个端点会报没有权限访问。

 

 2、忽略所有微服务或某些微服务

        默认情况下,只要引入了zuul后,就会自动一个默认的路由配置,但有些时候我们可能不想要默认的路由配置规则,想自己进行定义

        忽略所有微服务:(后面写 * )

 

Yml代码 

 收藏代码

  1. zuul:  
  2.   ignored-services: "*"  

 

        忽略某些微服务:(直接写微服务的名字=>可以理解为spring.application.name的值,多个以都好分隔)

 

Yml代码 

 收藏代码

  1. zuul:  
  2.   ignored-services: product-provider,product-consumer-8201  

 

 3、忽略所有为服务,只路由指定的微服务


     访问: http://gatewayhost:port/product/selectOne ===> 转发到 product-provider上的selectOne

 

四、通过path和url访问到具体的某台机器上

   有时候我们测试的时候需要访问到具体的某台机器上,而不希望负载均衡到别的机器上或者需要访问到第三方的某台机器上。

Yml代码 

 收藏代码

  1. zuul:  
  2.   routes:  
  3.     product-provider:  
  4.       path: /product/**  
  5.       url: http://localhost:8202/  


 

   注意:

           1、product-provider 这个值可以随便写,即使是一个不存在的值

           2、这种方式访问不会作为 HystrixCommand 来进行访问。

           3、url 里面也不可以写多个url

 

 五、脱离eureka进行访问,并使之具有负载均衡和隔离的机制等


 运行结果:

  

六、转发前是否去掉路由前缀


 

七、为所有路由都增加一个通过的前缀

       有些时候我们系统所有的路由都有一个统一的前缀进行访问,此时就可以使用 zuul.prefix 进行统一添加。


 

八、忽略某些路径不进行路由

         有些时候,我们某些微服务的某些地址不希望被第三方客户调用到,需要被隐藏起来,此时就可以使用网关路由这些url不进行路由。

Java代码 

 收藏代码

  1. zuul:  
  2.   ignored-patterns: /**/selectOne/**  
  3.   routes:  
  4.     product-provider: /product/**  

    注意: 这个忽略是全局忽略,即对所有的微服务都进行忽略

 

九、敏感头的传递(比如Cookie等)全局设置和某个微服务设置

        有些时候我们微服务上游可能想传递一些请求头到下游的服务,比如Token、Cookie等值,默认情况下,zuul 不会将 Cookie,Set-Cookie,Authorization 这三个头传递到下游服务,如果需要传递,就需要忽略这些敏感头。

 

全局和局部设置敏感头:

 运行结果:

  注意:

1、可以看到访问 product 路由时,是可以获取到 敏感头中 cookie 的信息的,访问 consumer 路由无法获取到。

2、如果下游服务启用了hystrix,那么 RequestInterceptor 要想从 ThreadLocal 中获取request的值,需要将隔离策略修改成信号量。

 

十、忽略头 (链接

       有些时候,我们不想将某个头传递到其它所有的微服务中,就可以使用忽略头,忽略头是全局配置的,如果想在某个服务中忽略某个头,可以使用敏感头忽略。

Java代码 

 收藏代码

  1. zuul:  
  2.   routes:  
  3.     product-provider:  
  4.       path: /product/**  
  5.       serviceId : product-provider  
  6.   ignored-headers: token  # 全局忽略头,忽略 token 这个请求头,不向下游服务传递这个token请求头  

   zuul.ignored-headers: token 表示被zuul路由的服务都不会传递 token 这个请求头。

 

十一、spring security 在classpath 下会忽略的头

    当我们的 spring security 在classpath中,zuul 会为我们增加一个默认的 spring security 相关的忽略头,如果我们不想要忽略,将 zuul. ignore-security-headers: false 就可以了。

Java代码 

 收藏代码

  1. # spring security 在classpath 下会忽略的头  
  2. zuul:  
  3.   routes:  
  4.     product-provider:  
  5.       path: /product/**  
  6.       serviceId : product-provider  
  7.   ignore-security-headers: false  # 为true会忽略spring security安全头,如果下游需要用到需要设置成false  


 

十二、本地调换和路由的优先级

       有些时候,我们页面上访问到的某些路径,想让网关直接进行处理,而不是直接转发到后端的服务上,此时就可以使用到路由的跳转。  有些时候  /product/ext/** 想路由到  product-provider-ext 服务上,

/product/** 想路由到 product-provider 服务上,此时在 yml 文件中顺序配置即可。

 

 

十三、配置网关超时


  

   如果是通过 url 进行配置的,那么需要设置下面这个超时时间

 

十四、重写 Location 头

        如果Zuul面向Web应用程序,那么当Web应用程序通过http状态代码3XX重定向时,可能需要重写Location头,否则浏览器将最终重定向到Web应用程序的url而不是Zuul url。

 

十五、文件上传处理

      在微服务中,有时候我们经常需要用到文件的上传,当使用了服务网关 zuul 后,对于小的文件是可以上传成功的,那么对于大的文件就会报错,此处应该如何处理呢?

      对于大文件的上传,我们需要绕过 Spring 的 DispatcherServlet。在 spring cloud zuul 中我们只需要在路由的前面加上 /zuul( zuul.servletPath) 前缀即可。

   从上图中可以看到,对于大文件的上传,是加上了  /zuul  的前缀的。

 

完整代码

   服务网关配置代码: https://gitee.com/huan1993/spring-cloud-parent/tree/master/zuul

<think>我们之前讨论了Eureka与Nginx的结合,现在用户询问的是Eureka和Zuul使用方法。根据提供的引用,Zuul是Netflix开源的API网关,可以与Eureka服务注册中心集成,实现动态路由、负载均衡、安全验证等功能。 用户需求:了解如何使用Eureka和Zuul。 我们将分步骤讲解: 1. 搭建Eureka Server 2. 创建微服务并注册到Eureka 3. 搭建Zuul网关 4. 配置Zuul路由规则 5. 高级功能(如过滤器、Swagger集成) 注意:引用中提到了Zuul可以集成Eureka,并且能够进行请求拦截(如token验证)以及Swagger的聚合配置。 --- ### 一、Eureka Server 搭建 1. **创建Spring Boot项目** 使用Spring Initializr(https://start.spring.io/)创建项目,选择依赖: - Eureka Server 2. **配置application.yml** ```yaml server: port: 8761 eureka: client: register-with-eureka: false # 自身不注册到其他Eureka fetch-registry: false # 不获取其他Eureka的服务列表 ``` 3. **启用Eureka Server** 在启动类添加注解: ```java @SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } } ``` 4. **启动并访问** `http://localhost:8761` 进入Eureka控制台。 --- ### 二、微服务注册到Eureka 1. **微服务配置** ```yaml spring: application: name: user-service # 服务名称 eureka: client: service-url: defaultZone: http://localhost:8761/eureka # Eureka地址 ``` 2. **启用服务发现** 启动类添加注解(可选,如果使用RestTemplate或Feign则需要): ```java @SpringBootApplication @EnableDiscoveryClient // 或 @EnableEurekaClient public class UserServiceApplication { ... } ``` --- ### 三、Zuul网关搭建 1. **创建Zuul项目** 选择依赖: - Zuul - Eureka Discovery Client(用于从Eureka获取服务) 2. **配置application.yml** ```yaml server: port: 8080 spring: application: name: zuul-gateway eureka: client: service-url: defaultZone: http://localhost:8761/eureka # 注册到Eureka zuul: routes: user-service: /user/** # 将/user/**的请求路由到user-service order-service: /order/** # 将/order/**的请求路由到order-service ``` 3. **启用Zuul代理** 启动类添加注解: ```java @SpringBootApplication @EnableZuulProxy public class ZuulGatewayApplication { public static void main(String[] args) { SpringApplication.run(ZuulGatewayApplication.class, args); } } ``` --- ### 四、动态路由与负载均衡 - **动态路由**:Zuul自动从Eureka获取服务实例列表,无需硬编码IP。 - **负载均衡**:Zuul内置Ribbon,默认轮询策略。 > 访问示例: > `http://localhost:8080/user/1` → 自动转发到`user-service`的某个实例的`/1`接口。 --- ### 五、过滤器实现(Token验证示例) Zuul的核心功能之一是通过过滤器(Filter)实现请求拦截。 1. **创建Pre过滤器** ```java public class TokenFilter extends ZuulFilter { @Override public String filterType() { return "pre"; // 前置过滤器 } @Override public int filterOrder() { return 0; } @Override public boolean shouldFilter() { return true; // 始终执行 } @Override public Object run() throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); // 检查token参数 String token = request.getParameter("token"); if (token == null || !token.equals("valid_token")) { ctx.setSendZuulResponse(false); // 拦截请求 ctx.setResponseStatusCode(401); ctx.setResponseBody("Access denied: token is invalid"); } return null; } } ``` 2. **注册过滤器** 在启动类添加: ```java @Bean public TokenFilter tokenFilter() { return new TokenFilter(); } ``` > 此时所有请求必须携带`token=valid_token`参数,否则返回401[^1]。 --- ### 六、Swagger文档聚合 当微服务使用Swagger时,Zuul可聚合所有服务的Swagger文档(引用[3]示例)。 1. **添加依赖** ```xml <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> ``` 2. **配置Swagger资源提供者** ```java @Component @Primary public class DocumentationConfig implements SwaggerResourcesProvider { @Override public List<SwaggerResource> get() { List<SwaggerResource> resources = new ArrayList<>(); // 从Eureka获取的服务列表动态生成,此处简化 resources.add(swaggerResource("用户服务", "/user-service/v2/api-docs", "2.0")); resources.add(swaggerResource("订单服务", "/order-service/v2/api-docs", "2.0")); return resources; } private SwaggerResource swaggerResource(String name, String location, String version) { SwaggerResource resource = new SwaggerResource(); resource.setName(name); resource.setLocation(location); resource.setSwaggerVersion(version); return resource; } } ``` 3. **访问聚合文档** `http://localhost:8080/swagger-ui.html` --- ### 七、常见问题 1. **路由配置不生效** - 检查服务名是否与Eureka注册名一致(大小写敏感)。 - 确认Zuul已连接到Eureka(查看日志)。 2. **过滤器不执行** - 确保过滤器被Spring容器管理(`@Component`或`@Bean`)。 - 检查`filterType()`返回值是否正确(pre/route/post/error)。 3. **超时问题** 调整Zuul的超时设置: ```yaml zuul: host: connect-timeout-millis: 5000 socket-timeout-millis: 10000 ``` --- ### 八、备选方案:Spring Cloud Gateway > Zuul 1.x已进入维护模式,建议新项目使用Spring Cloud Gateway(基于WebFlux,支持异步非阻塞)。 | 特性 | Zuul 1.x | Spring Cloud Gateway | |--------------|---------------|----------------------| | 性能 | 阻塞IO | 非阻塞异步 | | 依赖 | Servlet | Netty/WebFlux | | 功能扩展 | Filter | Predicate/Filter | | 学习曲线 | 低 | 中高 | 迁移示例: ```yaml spring: cloud: gateway: routes: - id: user-service uri: lb://user-service # lb表示从注册中心负载均衡 predicates: - Path=/user/** ``` --- ### 总结流程图 ```mermaid graph LR 客户端 -->|请求| Zuul网关 Zuul网关 -->|动态路由| Eureka注册中心 Eureka注册中心 -->|返回服务实例| Zuul网关 Zuul网关 -->|转发请求| 微服务实例 微服务实例 -->|返回响应| Zuul网关 Zuul网关 -->|返回客户端| 客户端 ``` §§相关问题§§ 1. Zuul和Spring Cloud Gateway的主要区别是什么? 2. 如何在Zuul中实现限流? 3. Eureka服务注册发现的工作原理?</think>### Eureka 与 Zuul 结合实现微服务调用指南 Eureka 是服务注册与发现中心,Zuul 是 API 网关,两者结合可实现动态路由、负载均衡和安全控制。以下是完整实现方案: --- #### 一、核心架构 ```mermaid graph LR A[客户端] --> B(Zuul网关) B --> C{Eureka注册中心} C --> D[微服务A] C --> E[微服务B] ``` 1. **服务注册**:微服务启动时向 Eureka 注册信息(IP、端口) 2. **动态路由**:Zuul 从 Eureka 获取服务列表实现请求路由 3. **统一入口**:所有外部请求通过 Zuul 网关访问后端服务[^1] --- #### 二、环境搭建步骤 ##### 1. 创建 Eureka Server **依赖配置** (pom.xml): ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> ``` **启动类配置**: ```java @SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } } ``` **配置文件** (application.yml): ```yaml server: port: 8761 eureka: client: register-with-eureka: false # 不注册自身 fetch-registry: false # 不获取注册表 ``` --- ##### 2. 创建 Zuul 网关 **依赖配置** (pom.xml): ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> ``` **启动类配置**: ```java @SpringBootApplication @EnableZuulProxy public class ZuulGatewayApplication { public static void main(String[] args) { SpringApplication.run(ZuulGatewayApplication.class, args); } } ``` **配置文件** (application.yml): ```yaml server: port: 8080 spring: application: name: zuul-gateway eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ # 连接Eureka[^2] zuul: routes: user-service: /users/** # 用户服务路由规则 order-service: /orders/** # 订单服务路由规则 ``` --- ##### 3. 创建微服务(以用户服务为例) **配置文件** (application.yml): ```yaml server: port: 8081 spring: application: name: user-service # 服务名称必须唯一 eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ # 注册到Eureka ``` --- #### 三、核心功能实现 ##### 1. 动态路由与负载均衡 Zuul 自动从 Eureka 获取服务实例并实现负载均衡: ```java // 通过服务名访问其他微服务 @RestController public class OrderController { @GetMapping("/user-info") public String getUserInfo() { // 直接使用服务名访问 return restTemplate.getForObject( "http://user-service/users/123", // 服务名而非IP String.class ); } } ``` ##### 2. 请求过滤(Token验证) ```java public class TokenFilter extends ZuulFilter { @Override public String filterType() { return "pre"; // 前置过滤器 } @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); // 检查Token参数 if (request.getParameter("token") == null) { ctx.setSendZuulResponse(false); // 拦截请求 ctx.setResponseStatusCode(401); ctx.setResponseBody("Access denied: token is required"); } return null; } } ``` 注册过滤器:`@Bean public TokenFilter tokenFilter() { return new TokenFilter(); }`[^1] --- ##### 3. Swagger 文档聚合 ```java @Primary @Component public class SwaggerConfig implements SwaggerResourcesProvider { @Override public List<SwaggerResource> get() { List<SwaggerResource> resources = new ArrayList<>(); // 添加用户服务文档 resources.add(swaggerResource("用户服务", "/user-service/v2/api-docs", "2.0")); // 添加订单服务文档 resources.add(swaggerResource("订单服务", "/order-service/v2/api-docs", "2.0")); return resources; } private SwaggerResource swaggerResource(String name, String location, String version) { SwaggerResource resource = new SwaggerResource(); resource.setName(name); resource.setLocation(location); resource.setSwaggerVersion(version); return resource; } } ``` 访问统一文档:`http://zuul-host:port/swagger-ui.html`[^3] --- #### 四、高级配置 ##### 1. 路由重写 ```yaml zuul: routes: user-service: path: /api/users/** serviceId: user-service stripPrefix: false # 保留完整路径 ``` ##### 2. 熔断降级 ```java @Bean public ZuulFallbackProvider userServiceFallback() { return new ZuulFallbackProvider() { @Override public String getRoute() { return "user-service"; // 指定服务 } @Override public ClientHttpResponse fallbackResponse() { return new ClientHttpResponse() { @Override public HttpStatus getStatusCode() { return HttpStatus.SERVICE_UNAVAILABLE; } @Override public String getStatusText() { return "Service Unavailable"; } // 自定义降级响应体 @Override public InputStream getBody() { return new ByteArrayInputStream("用户服务暂不可用".getBytes()); } }; } }; } ``` ##### 3. 请求限流 ```java @Bean public RateLimiter zuulRateLimiter() { return new RateLimiter() { @Override public boolean isAllowed(String route, String key) { // 每秒钟允许10个请求 return rateLimiter.tryAcquire(10, TimeUnit.SECONDS); } }; } ``` --- #### 五、最佳实践 1. **命名规范**: - 服务名使用小写(`user-service` 而非 `UserService`) - 路径前缀与服务名保持一致 2. **安全建议**: ```yaml zuul: sensitive-headers: Cookie,Set-Cookie # 屏蔽敏感头信息 add-proxy-headers: true ``` 3. **性能优化**: ```yaml zuul: host: max-per-route-connections: 20 # 单路由最大连接数 max-total-connections: 200 # 总连接数 socket-timeout-millis: 10000 # 超时设置 ``` --- #### 六、常见问题排查 | 问题现象 | 解决方案 | |---------|----------| | 服务未注册到Eureka | 检查`spring.application.name`和`defaultZone`配置 | | Zuul路由404错误 | 确认服务名与`zuul.routes`配置匹配 | | Swagger文档加载失败 | 检查`@Primary`注解和资源路径配置[^3] | | 过滤器不生效 | 确认`filterType()`返回正确类型(pre/post等) | > **注意**:Zuul 1.x 已进入维护模式,新项目建议使用Spring Cloud Gateway [^1]: Zuul 提供请求拦截和预处理能力 [^2]: Zuul 通过 Eureka 客户端获取服务注册信息 [^3]: 通过自定义 SwaggerResourcesProvider 实现文档聚合
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值