【微服务】SpringCould之zuul网关服务

发布于:2022-07-17 ⋅ 阅读:(166) ⋅ 点赞:(0)

网关地址重定向

1、微服务调用常见问题

常见的现象

  • 客户端会多次请求不同的微服务,增加了客户端的复杂性。

  • 存在跨域请求,在一定场景下处理相对复杂。

  • 认证复杂,每个服务都需要独立认证。

  • 难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通讯,那么重构将会很难实施。

  • 某些微服务可能使用了防火墙/浏览器不友好的协议,直接访问会有一定困难。

使用网关优点:

  • 易于监控。可在微服务网关收集监控数据并将其推送到外部系统进行分析。

  • 易于认证。可在微服务网关上进行认证。然后再将请求转发到后端的微服务,而无须在每个微服务中进行认证。

  • 减少了客户端与各个微服务之间的交互次数。

2、Zuul网关的主要作用

  1. 是类似于Nginx的网址重定向,但zuul的重定向的一般是整个spring cloud里在Eureka注册中心的模块。
  2. zuul更重要的功能为过滤请求。

3、创建zuul-server网关工程

配置zuul网关的依赖包

        <!--zuul-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
        <!--client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

4、zuul客户端配置

启动配置

启动类上加@EnableZuulProxy注解

@EnableZuulProxy //启用zuul代理
@SpringBootApplication
public class DmwZuulServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(DmwZuulServerApplication.class, args);
    }

}

配置application.yml文件

server:
  port: 6888

spring:
  application:
    name: zuul-server

eureka:
  client:
    service-url:
      defaultZone: http://${eureka.instance.hostname}:7777/eureka/
  instance:
    hostname: 192.168.1.1        #你本机的ip地址
zuul:
  routes:
    user-consumer: /user/**      

dm-user-consumer: /user/**   访问192.168.1.1:6888/user/userLogin会跳转到user-consumer这个消费者去调用userLogin这个路径的控制器。

**的意思是可以匹配任何多级目录的意思。

*为单级目录。

5、启动测试

访问:

http://192.168.1.1:6888/user/userLogin

消费者被调用表示成功。

收到结果: 提供者1 登录成功 

网关过滤器

1、过滤器的作用

过滤器本身并不生成请求和响应对象,它只提供过滤作用。如我们大觅网的支付功能,如果请求中不带token不允许它进入消费者。

2、zuul中的过滤器类型

  • PRE Filters(前置过滤器) :当请求会路由转发到具体后端服务器前执行的过滤器,比如鉴权过滤器,日志过滤器,还有路由选择过滤器
  • ROUTING Filters (路由过滤器):该过滤器作用是把请求具体转发到后端服务器上,一般是通过Apache HttpClient 或者 Netflix Ribbon把请求发送到具体的后端服务器上
  • POST Filters(后置过滤器):当把请求路由到具体后端服务器后执行的过滤器;场景有添加标准http 响应头,收集一些统计数据(比如请求耗时等),写入请求结果到请求方等。
  • ERROR Filters(错误过滤器):当上面任何一个类型过滤器执行出错时候执行该过滤器

3、zuul过滤器执行的步骤

4、增加过滤器

在zuul-server工程中增加过滤器

@Component
public class PreFillter extends ZuulFilter{
    @Override
    public String filterType() {
        //设置过滤器的类型有pre、route、post、error四种
        return FilterConstants.PRE_TYPE;  
    }

    @Override
    public int filterOrder() {
        //定义filter的顺序,数字越小表示顺序越高,越先执行  只有同类型的顺序才有意义
        return 1;  
    }

    @Override
    public boolean shouldFilter() {
        //表示是否需要执行该filter,true表示执行,false表示不执行
        return true; 
    }

    //filter需要执行的具体操作   此方法返回值扩展用,暂时无效
    @Override
    public Object run() {        
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest req = ctx.getRequest();

        String tokenStr = req.getHeader("token");
        if (null == tokenStr || "".equals(tokenStr)) {
            ctx.setSendZuulResponse(false);//不执行后面的过滤器
            ctx.setResponseStatusCode(401); //设置出错的代码
            ctx.setResponseBody("{\"msg\":\"401........\"}");
            return "access denied";
            
        }
        
        return "pass";
    }
}

5、重启测试

用Postman工具测试如下地址:

http://localhost:6888/user/dologin

通过发送token和取消token值测试变化。

 

多个过滤器控制执行

1、创建多个过滤器

假设现在有三个过滤器,A、B、C,如果我输入key=1,只执行过滤器A,输入key=2执行过滤器AB,输入key=3执行过滤器ABC三个。

先在dm-gateway-zuul中创建三个过滤器,让它们类型使用Pre的类型。过滤器名称是:PreFillter、SecondFilter、ThirdFilter三个类,实现ZuulFilter接口。

第一个类PreFillter:

@Component
public class PreFillter extends ZuulFilter{
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;  //设置过滤器的类型
    }

    @Override
    public int filterOrder() {
        return 1;  //过滤器执行的顺序   只有同类型的顺序才有意义
    }

    @Override
    public boolean shouldFilter() {
        return true; //是否启用过滤器   true表示启用
    }

    @Override
    public Object run() {
        //使用RequestContext多个过滤器之间共享数据
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest req = ctx.getRequest();

        String key = req.getParameter("key");
        System.out.println("access pre 1    key:"+key);
        if("1".equals(key)){
            ctx.setSendZuulResponse(false);
        }
        return null;
    }
}

第二个类SecondFilter:

@Component
public class SecondFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return 2;  //此处是2
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        //此处不是直接返回true,如果上一个过滤器ctx.setSendZuulResponse(false);此处返回false
        return ctx.sendZuulResponse();   
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest req = ctx.getRequest();

        String key = req.getParameter("key");
        System.out.println("access pre 2    key:"+key);
        if("2".equals(key)){
            ctx.setSendZuulResponse(false);
        }
        return null;
    }
}

第三个类ThirdFilter:

@Component
public class ThirdFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return 3;//此处是3
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        return ctx.sendZuulResponse();
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest req = ctx.getRequest();

        String key = req.getParameter("key");
        System.out.println("access pre 3    key:"+key);
        if("3".equals(key)){
            ctx.setSendZuulResponse(false);
        }
        return null;
    }
}

可以在application.yml文件中设置zuul.SecondFilter.pre.disable=true可以禁用过滤器, SecondFilter是要禁用的过滤器类名。pre是指过滤器类型。

2、重启测试

访问:

http://localhost:6888/user/dologin?key=1

控制台打印:

access pre 1    key:1

访问:

http://localhost:7600/user/userLogin?key=2

控制台打印:

access pre 1    key:2
access pre 2    key:2

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到