spring cloud zuul实践

一、 描述

Spring Cloud Zuul是基于Netflix开源的Zuul项目构建而成,它作为微服务架构中的网关服务,主要用于实现动态路由、负载均衡和请求过滤等功能。

  1. 动态路由:Zuul根据预设的路由规则将进来的请求路由到相应的服务实例上。路由规则可以通过配置文件或代码进行定义,接收到请求后,Zuul会解析请求的URL,并根据配置的路由规则找到对应的服务地址,将请求转发到目标服务。

  2. 负载均衡:Zuul内置了Ribbon负载均衡器,可以对请求进行负载均衡。当一个服务有多个实例时,Zuul可以使用负载均衡算法将请求均匀地分发到不同的实例上,以提高系统的性能和可扩展性。

  3. 请求过滤:Zuul支持自定义过滤器,在请求被路由之前或之后对请求进行处理。过滤器可以用于在路由前进行身份验证、请求统计、参数校验等操作,也可以在路由后处理响应结果,比如修改返回数据、添加自定义的响应头等。开发者可以根据需求创建不同类型的过滤器,并定义过滤器的执行顺序。

  4. 整合服务注册中心:Zuul可以与服务注册中心(如Zookeeper、Eureka)进行整合,实现动态路由和负载均衡。通过与服务注册中心交互,Zuul能够动态地获取服务实例的信息,并根据需要进行路由和负载均衡。

  5. 高可用和容错:Zuul支持配置多个实例运行在不同的机器上,以实现高可用性。当一个Zuul实例发生故障时,其他实例可以接管请求处理,确保系统的稳定性和容错性。

Spring Cloud Zuul通过动态路由、负载均衡和请求过滤等机制,提供了一个强大且灵活的网关服务。它能够统一管理微服务的入口,实现请求的转发和过滤,简化了微服务架构中的通信和调用方式,提高了系统的可伸缩性和可维护性。

      下面是使用Spring Cloud Zuul的一般实践步骤

二、添加依赖

引入zuul的依赖spring-cloud-starter-netflix-zuul

1     <dependency>
2       <groupId>org.springframework.cloud</groupId>
3       <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
4     </dependency>
View Code

三、创建启动类:

      创建一个启动类,并使用@EnableZuulProxy注解开启Zuul代理功能。

1 @SpringBootApplication
2 @EnableZuulProxy
3 public class GatewayApplication {
4 
5   public static void main(String[] args) {
6     SpringApplication.run(GatewayApplication.class, args);
7   }
8 
9 }
View Code

四、 配置

在配置文件(如application.yml)中定义Zuul的路由规则。可以使用Zuul的zuul.routes前缀来配置不同的路由规则。

 1 server:
 2   port: 9000
 3 management:
 4   endpoints:
 5     web:
 6       exposure:
 7         include: '*'
 8   server:
 9     port: 12345
10 zuul:
11   routes:
12     configserver:
13       path: /myConfig/**
14       serviceId: config
15     user:
16       path: /myUser/**
17       serviceId: provider
18   ignored-patterns: #忽略指定的路由
19     - /config/**
20     - /gateway/**
21   sensitive-headers:
22 #  ignore-local-service: true # 忽略原来自身的路由。比如,true: 原来的config/xxx/xxx不可再访问
View Code

上述配置将/myConfig/**的请求转发到config服务,将/myUser/**的请求转发到provider服务。

还可以将网关注册到注册中心实现高可用。创建bootstrap.yml文件

 1 spring:
 2   application:
 3     name: gateway
 4   cloud:
 5     zookeeper:
 6       discovery:
 7         register: true
 8         enabled: true
 9       connect-string: 192.168.3.100:2181
10     config:
11       discovery:
12         service-id: config
13         enabled: true
View Code

五、配置过滤器

 通过zuul添加过滤器,对请求进行拦截或校验等等

 1 package com.mike.study.gateway.fiter;
 2 
 3 import com.netflix.zuul.ZuulFilter;
 4 import com.netflix.zuul.context.RequestContext;
 5 import com.netflix.zuul.exception.ZuulException;
 6 import org.apache.commons.lang.StringUtils;
 7 import org.springframework.http.HttpStatus;
 8 import org.springframework.stereotype.Component;
 9 
10 import javax.servlet.http.HttpServletRequest;
11 
12 import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER;
13 import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
14 
15 /**
16  * @Classname ParameterFilter
17  * @Created by Michael
18  * @Date 2023/7/12
19  * @Description 自定义过滤器
20  */
21 @Component
22 public class ParameterFilter extends ZuulFilter {
23   /**
24    * 前置过滤
25    * @return
26    */
27   @Override
28   public String filterType() {
29     return PRE_TYPE;
30   }
31 
32   /**
33    * 数值越小,优先级越高
34    * @return
35    */
36   @Override
37   public int filterOrder() {
38     return PRE_DECORATION_FILTER_ORDER - 1;
39   }
40 
41   @Override
42   public boolean shouldFilter() {
43     return true;
44   }
45 
46   @Override
47   public Object run() throws ZuulException {
48 
49     // 获取请求对象
50     RequestContext context = RequestContext.getCurrentContext();
51     HttpServletRequest request = context.getRequest();
52     // 获取地址栏传入的参数
53     String token = request.getParameter("token");
54     System.out.println("token ===>"+token);
55     //模拟校验token,没有token则终止转发
56     if (StringUtils.isEmpty(token)) {
57       context.setSendZuulResponse(false);
58       context.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
59     }
60     return null;
61   }
62 }
ParameterFilter.java

以上代码时在转发请求服务前,对参数进行校验,如果没有token参数,则停止转发,并且返回401错误

六、测试

测试网关转发主要需要请求发起方,网关和请求处理方。这里在原来demo的基础上,增加网关,所以看到有配置中心,以往的文章有项目的搭建介绍。如果不想那么复杂,可以去掉配置中心,将配置放置各个module即可,项目组如下

 

准备请求发起方,即consumer,controller通过feign框架请求网关,网关转发请求provider。consumer的controller如下

 1 import com.mike.study.orderconsumer.client.UserClient;
 2 import com.mike.study.orderconsumer.vo.UserVo;
 3 import org.springframework.web.bind.annotation.GetMapping;
 4 import org.springframework.web.bind.annotation.PathVariable;
 5 import org.springframework.web.bind.annotation.RequestParam;
 6 import org.springframework.web.bind.annotation.RestController;
 7 
 8 import javax.annotation.Resource;
 9 
10 /**
11  * @Classname UserRuttingController
12  * @Created by Michael
13  * @Date 2023/7/9
14  * @Description feign框架调用provider api
15  */
16 @RestController
17 public class UserRuttingController {
18   @Resource
19   private UserClient userClient;
20 
21   @GetMapping("warp/user/2.1/{id}")
22   public UserVo getUser(@PathVariable("id") Integer userId, @RequestParam("token") String token) {
23     System.out.println("使用feign框架调用provide的api");
24     return userClient.getUser(userId, token);
25   }
26 }
controller

Feign接口

 1 import com.mike.study.orderconsumer.vo.UserVo;
 2 import org.springframework.cloud.openfeign.FeignClient;
 3 import org.springframework.web.bind.annotation.GetMapping;
 4 import org.springframework.web.bind.annotation.PathVariable;
 5 import org.springframework.web.bind.annotation.RequestParam;
 6 
 7 /**
 8  * @Classname UserFeigClient
 9  * @Created by Michael
10  * @Date 2023/7/9
11  * @Description feign client
12  */
13 
14 @FeignClient("gateway")
15 public interface UserClient {
16 
17   @GetMapping("myUser/user/{id}")
18   public UserVo getUser(@PathVariable("id") Integer userId,@RequestParam("token") String token);
19 }
UserClient

以上Feign接口配合注册中心zookeeper使用,访问的网关地址,而不是直接请求服务提供者的api。

provider module简单提供一个api查询用户信息。

六、测试结果

positive case:token参数有值

 negative case:token参数i为空

 

总结,就是consumer不再直接请求provider server,而是通过zuul作为中转站,这样做的好处很多,比如,对consumer的请求进行拦截过滤,验证,降流等等。

posted @ 2023-07-13 11:48  天晴修屋顶  阅读(86)  评论(0编辑  收藏  举报