zuul路由网关

强颜欢笑 提交于 2020-11-19 05:45:25
  zuul作为网关组件,主要用来管理api请求接口(统一对外暴露,负载均衡),身份认证,流量监控等。它是通过servlet来实现的,核心是一系列过滤器,可以在请求的发起跟相应返回阶段进行一系列的处理。
------------------------------------------------------------------------------------------------------------------------
原理简介
  过滤器分类:
    PRE过滤器:在请求路由到具体的服务之前执行,可以用作安全验证,例如身份验证,参数验证等;
    ROUTING过滤器:用于将请求路由到具体的微服务实例,默认情况下使用http client进行网络请求;
    POST过滤器:在请求被路由到微服务后执行,一般用作收集统计信息,及将响应传输到客户端;
    ERROR过滤器:在其他过滤器发生错误时执行;
  zuul采用了动态读取、编译和运行这些过滤器。过滤器之间不能直接通信,而是通过RequestContext对象共享数据,每个请求都会创建一个RequestContext对象。zuul请求的生命周期如图:
 
  request请求进入zuul网关后,先进入pre 类别的过滤器,进行一系列验证操作或判断,然后交给routing filter进行路由转发,转发到具体的微服务实例进行逻辑处理并返回数据;当具体的服务处理完成后,最后又post filters进行处理,该类型的过滤器处理完成后,将response信息返回给客户端。
demo搭建
  pom主要内容:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
  zuul功能开启:
  在启动类加注解@EnableZuulProxy跟@EnableEurekaClient,启用相应功能。
  yml文件配置:
server:
  port: 5000
spring:
  application:
    name: zuul-demo
eureka:
  client:
    registerWithEureka: true
    fetchRegistry: true
    serverUrl:
      defaultZone: http://127.0.0.1:8761/eureka
zuul:
  routes:
    smsapi:
      path: /sms/**
      serviceId: sms-module
    consumerapi:
      path: /consumertest/**
      serviceId: consumer-module
 
  routes下的smsapi是路由名字,随便起,可以配置多个,每个要配相应的规则。path表示要匹配的url路径,/sms/**表示匹配包含sms的url,将其路由到sms-module服务。第二个consumerapi是路由名,path跟serviceId同上。配置完成后,我们分别启动eureka-server,跟两个服务sms-module跟consumertest,其中sms-module启用三个实例(只需要启动一个服务多个实例即可测试)。
zuul默认结合ribbon的负载均衡测试:
  各个服务启动后服务实例信息如下:
 
   访问zuul进行测试,可以看到能正常返回结果:
 
   url中包含两个sms的原因是sms-module的controller的RequestMapping为sms:
 
   多次访问,可以发现zuul对sms-module的请求会分到不同的实例中,说明zuul默认集成了ribbon做了负载均衡处理。
自定义过滤器测试:
  既然zuul的主要功能之一是对请求进行拦截校验,那我们就做一个对请求进行校验的例子。比如很多网站都有token授权,我们不做token授权,做一个对url参数进行校验的filter,原理是类似的。
  filter代码:
@Component
public class MyFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }
    @Override
    public int filterOrder() {
        return 0;
    }
    //是否走过滤逻辑
    @Override
    public boolean shouldFilter() {
        return true;
    }
    //判断url中是否包含参数testParam,不包含则拦截请求
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String testParam = request.getParameter("testParam");
        if( null == testParam){
            System.out.println("缺失关键参数,驳回请求");
            ctx.setSendZuulResponse(false);//是否把该请求转发给具体服务
            ctx.setResponseStatusCode(401);
            try {
                ctx.getResponse().getWriter().write("qing  jiancha  canshu  shifou  wanzheng");
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
        return null;
    }
}
  自定义过滤器只需要继承ZuulFilter并实现4个方法即可。四个方法解释:
    filterType:同开头的过滤器分类,分为4中过滤器。
    filterOrder:执行顺序或者优先级,返回int数值,数值越小优先级越高。
    shoudlFilter:是否走过滤器逻辑,true则会走run方法,false不会。
    run:过滤器主要逻辑处理方法。
  还是同样的请求,发现添加过滤器后被拦截了:
  加上参数后再次请求,可以通过并返回正常数据:
 
熔断器测试:
  zuul作为netflix的组件,可以与hystrix结合实现熔断器功能,zuul实现熔断功能需要实现ZuulFallbackProvider接口。该接口有两个方法:
  getRoute:用于指导熔断功能用于哪些微服务;
  fallbackResponse:进入熔断功能时只需的逻辑;
  代码:
@Component
public class MyFallbackProvider implements ZuulFallbackProvider {
    @Override
    public String getRoute() {
        return "sms-module"; //匹配所有,用“*”
    }
    @Override
    public ClientHttpResponse fallbackResponse() {
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {return HttpStatus.OK;}
            @Override
            public int getRawStatusCode() throws IOException {return 200;}
            @Override
            public String getStatusText() throws IOException { return "OK";}
            @Override
            public void close() {}
            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream("{\"msg\":\"error, 少年,你的程序出异常了,这里是失败回调函数\"}".getBytes());
//                return new ByteArrayInputStream("少年,你的程序出异常了,这里是失败回调函数".getBytes());
            }
            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                return headers;
            }
        };
    }
}
   停掉sms-module的相关实例,再次访问:
 
------------------------------------------------------------------------------------------------------------------------
这样吧先。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!