zoukankan      html  css  js  c++  java
  • springCloud初识5-网关 Zuul

    Zuul是Netlix开源的微服务网关,它可以和Eureka、Ribbon、 Hystrix 等组件配合使用。
    Zuul的核心是一系列的过滤器,这些过滤器可以完成以下功能。

    • 身份认证与安全:识别每个资源的验证要求,并拒绝那些与要求不符的请求。
    • 审查与监控:在边缘位置追踪有意义的数据和统计结果,从而带来精确的生产视图。
    • 动态路由:动态地将请求路由到不同的后端集群。
    • 压力测试:逐渐增加指向集群的流量,以了解性能。
    • 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求。
    • 静态响应处理:在边缘位置直接建立部分响应,从而避免其转发到内部集群。
    • 多区域弹性:跨越AWS Region进行请求路由,旨在实现ELB ( Elastic Load Balancing)使用的多样化,以及让系统的边缘更贴近系统的使用者。

    Spring Cloud对Zuul进行了整合与增强。目前,Zuul使用的默认HTTP客户端是Apache HTTP Client,也可以使用RestClient或者okhttp3.0kHttpClient。
    如果想要使用RestClient,可以设置ribbon.restclient.enabled=true;想要使用okhttp3.0kHttpClient,可以设置ribbon.okhttp.enabled=true。

    路由:分发给不同的微服务(通过服务名)
    负载均衡:分发同一个微服务的不同实例,减少单个压力

    zuul4种配置方式

    配置方式1:快速入门 (只是做了路径分发 通过路径可路由)

    1--新建项目,引入依赖

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

    2--覆盖默认配置

    server:  # 设置应用端口
      port: 10010
    spring:  # 设置应用即微服务名称
      application:
        name: xiaoai_zuul
    

    3--引导类启用zuul组件

    package com.xiaoai.zuul;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
    
    @SpringBootApplication
    @EnableZuulProxy  //启用zuul组件
    public class XiaoaiZuulApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(XiaoaiZuulApplication.class, args);
    	}
    }
    

    4--配置路由

    zuul:
      routes:
        service-provider: # 路由名称,可以随便写,习惯上用服务的名称,即之前自己定义的某个服务的名称。
          path: /service-provider/**
          url: http://localhost:8081
    

    --通过zuul访问配置好的服务,可以正常访问

    --如未配置消费端路由,zuul访问其url

    --配置消费服务端路由后,zuul访问其url

    server:
      port: 10010
    spring:
      application:
        name: xiaoai_zuul
    
    zuul:
      routes:
        service-provider:** # 路由名称,可以随便写,习惯上用服务的名称,即之前自己定义的某个服务的名称。
          path: /service-provider/**
          url: http://localhost:8081
        service-consumer: # 配置消费端路由
          path: /service-consumer/**
          url: http://localhost:80
    
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:10086/eureka
    
    

    配置方式2:zuul注册到eureka容器 (通过服务id可路由)

    1--引入eureka启动器

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

    2--把zuul注入eureka容器中,application配置文件配置

    spring:
      application:
        name: xiaoai_zuul
    
    eureka:
      client:
        service-url:
          defaultZone: http/localhost:10086/eureka
    

    3--引导类启用eureka

    package com.xiaoai.zuul;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
    
    @SpringBootApplication
    @EnableZuulProxy  //启用zuul组件
    @EnableDiscoveryClient  //启用eureka客户端
    public class XiaoaiZuulApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(XiaoaiZuulApplication.class, args);
    	}
    
    }
    
    

    4--配置文件可以修改路由,直接配置服务id即可

    server:
      port: 10010
    spring:
      application:
        name: xiaoai_zuul
    
    zuul:
      routes:
        service-provider: # 路由名称,可以随便写,习惯上用服务的名称,即之前自己定义的某个服务的名称。
          path: /service-provider/**
    #      url: http://localhost:8081  # 写死端口无法负载均衡
          serviceId: service-provider  # 把zuul注入到了eureka后,其可以拉取客户端服务,所以可以直接写服务id,即自己定义的名称,通过服务id,zuul也可以实现负载均衡
    
    eureka:
      client:
        service-url:
          defaultZone: http//localhost:10086/eureka
    

    --zuul访问提供服务端url可以正常访问

    配置方式3:路径直接配置在服务id后

    --application配置文件配置

    server:
      port: 10010
    spring:
      application:
        name: xiaoai_zuul
    
    zuul:
      routes:
        service-provider: /service-provider/** # 路由名称,可以随便写,习惯上用服务的名称,即之前自己定义的某个服务的名称。
    #      path: /service-provider/**
    #      url: http://localhost:8081
    #      serviceId: service-provider  # 把zuul注入到了eureka后,其可以拉取客户端服务,所以可以直接写服务id,即自己定义的名称,通过服务idzuul也可以实现负载均衡
    
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:10086/eureka
    

    --访问

    配置方式4: 加入eureka容器后 不配置任何路由 默认访问就是服务名加路径

    --配置如下

    server:
      port: 10010
    spring:
      application:
        name: xiaoai_zuul
    
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:10086/eureka
    
    

    --访问

    默认使用第三种配置方式,使用第三种可以修改路径 简化路径前缀 如配置:

    server:
      port: 10010
    spring:
      application:
        name: xiaoai_zuul
    
    zuul:
      routes:
        service-provider: /user/** # 路由名称,可以随便写,习惯上用服务的名称,即之前自己定义的某个服务的名称。 路径可以使用服务id也可以修改自定义,这里改为user
        service-consumer: /consumer/**
    
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:10086/eureka
    

    --访问

    在某个微服务中控制器减少一层路径 如提供端服务service-provider的控制类

    package com.xiaoai.service.controller;
    
    import com.xiaoai.service.pojo.User;
    import com.xiaoai.service.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class UserController {
    
        @Autowired
        private UserService userService;
    
        @GetMapping("{id}")
        public User queryUserById(@PathVariable("id")Long id) {
            return this.userService.queryUserById(id);
        }
    
    }
    
    

    zuul的application配置文件

    server:
      port: 10010
    spring:
      application:
        name: xiaoai_zuul
    zuul:
      routes:
        service-provider: /user/** # 路由名称,可以随便写,习惯上用服务的名称,即之前自己定义的某个服务的名称。
        service-consumer: /consumer/**
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:10086/eureka
    

    --访问

    网关前缀

    由于项目发布以后无法知道访问路径是否经过网关,可以在application配置文件中配置加入前缀来区分访问是否经过网关。如:

    server:
      port: 10010
    spring:
      application:
        name: xiaoai_zuul
    
    zuul:
      routes:
        service-provider: /user/** # 路由名称,可以随便写,习惯上用服务的名称,即之前自己定义的某个服务的名称。
        service-consumer: /consumer/**
        prefix: /api # 前缀用于区分访问是否经过网关,这里为api,可以自定义,默认一般使用api
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:10086/eureka
    
    

    --访问

    小结

    • 引入zuul的启动器
    • 配置:
      • zuul.routes.<路由名称>.path=/service-provider/** zuul.routes.<路由名称>.url=http://localhosta:8081
      • zuul.routes.<路由名称>.path=/service-provider/** zuul.routes.<路由名称>.serviceId=service-provider
      • zuul.routes.服务名称=/service-provider/**
      • 不用配置,默认就是服务id+路径
    • 引导类注解@EnableZuulProxy 开启zuul
    • 引导类@EnableDiscoveryClient 开启eureka客户端

    zuul过滤器

    Zuul作为网关的其中一个重要功能, 就是实现请求的鉴权。而这个动作我们往往是通过Zuul提供的过滤器来实现

    Zuul过滤器需实现接口:IZuulFilter

    • 方法shouldFilter() 返回值true执行run方法,false不执行
    • 方法run() 过滤器业务逻辑的方法,是否拦截在该方法判断
      默认有一些实现了IZuulFilter接口的类

    1--定义一个过滤器

    package com.xiaoai.zuul.filter;
    
    import com.netflix.zuul.ZuulFilter;
    import com.netflix.zuul.context.RequestContext;
    import com.netflix.zuul.exception.ZuulException;
    import org.apache.commons.lang.StringUtils;
    import org.apache.http.HttpStatus;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    
    @Component
    public class LoginFilter extends ZuulFilter{
    
    
        /**
         * 过滤器类型选择:pro route post error
         * @return
         */
        @Override
        public String filterType() {
            return "pre";
        }
    
        /**
         * 执行的顺序,返回值越小,优先级越高
         * @return
         */
        @Override
        public int filterOrder() {
            return 10;
        }
    
        /**
         * 是否执行该过滤器 即run方法
         * true==执行
         * false==不执行
         * @return
         */
        @Override
        public boolean shouldFilter() {
            return true;
        }
    
        /**
         * 编写过滤器的业务逻辑
         * @return
         * @throws ZuulException
         */
        @Override
        public Object run() throws ZuulException {
            //初始化context上下文对象,
            RequestContext context = RequestContext.getCurrentContext();
            //获取request对象
            HttpServletRequest request = context.getRequest();
            //获取参数
            String token = (String) request.getParameter("token");
            if (StringUtils.isBlank(token)){
                //拦截 ,这里表示不转发请求
                context.setSendZuulResponse(false);
                //响应状态码,401-身份未认证
                context.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
                //设置响应的提示
                context.setResponseBody("request error!");
            }
            //返回值为null,表示该过滤器什么都不做
            return null;
        }
    }
    
    

    2--访问

    springCloud初识小结

    • eureka
      • 注册中心
      • 微服务容器
    • ribbon
      • 负载均衡组件
      • eureka集成 feign集成 zuul集成
      • @LoadBalanced 开启负载均衡
      • this.restTemplate.getForObject("http://service-provider/user/"+id,User.class) 实现负载均衡
    • hystrix
      • 容错组件
      • 降级:检查每次请求,是否请求超时,或连接池已满
        • 引入hystrix启动器
        • 熔断时间,默认1s,
        • 在引导类上添加了一个注解: @EnableCircuitBreaker @SpringCloudApplication
        • 定义熔断方法:局部(要和被熔断的方法返回值和参数列表一致)全局 (返回值类型要被熔断的方法一致, 参数列表必须为空)
          • @HystrixCommand (fallbackMethod="局部熔断方法名"):声明被熔断的方法
          • @DefaultProperties (defaultFallback="全局熔断方法名")
      • 熔断:不再发送请求
        • close:闭合状态,所有请求正常方法
        • open:打开状态,所有请求都无法访问。如果在- -定时间内容,失败的比例不小于508或者次数不少于20次
        • half open: 半开状态,打开状态默认5s休眠期,在休眠期所有请求无法正常访问。过了休眠期会进入半开状态,放部分请求通过
    • feign
      • 引入openFeign启动器
      • feign.hystrix.enable=true,开启feign的熔断功能
      • 在引导类上@EnableFeignClients启用feign
      • 创建一一个接口,在接口添加eFeignClient (value="微服务id", fallback=实现类.class)
      • 在接口中定义一些方法,这些方法的书写方式跟之前controller类似
      • 创建了一个熔断类,实现feign接口,实现对应的方法,这些实现方法就是熔断方法
    • zuul
      • 网关,路由分发
      • 引入zuul的启动器
      • 配置:4种方式
        • zuul.routes.<路由名称>.path=/service-provider/** zuul.routes.<路由名称>.url=http://localhosta:8081
        • zuul.routes.<路由名称>.path=/service-provider/** zuul.routes.<路由名称>.serviceId=service-provider
        • zuul.routes.服务名称=/service-provider/**
        • 不用配置,默认就是服务id+路径
      • 引导类注解@EnableZuulProxy 开启zuul
      • 引导类@EnableDiscoveryClient 开启eureka客户端
      • 过滤器:
        • 创建一个类继承ZuulFilter基类
        • 重写四个方法
          • filterType: pro route post error
          • filterOrder:返回值越小优先值越高
          • shouldFilter:返回值判断是否执行run方法。true=执行 false=不执行
          • run:具体的拦截逻辑
  • 相关阅读:
    UltraEdit语法高亮解决办法
    tcpdump命令格式及使用
    VS tricks
    git ready
    [FirefoxPlugin]Print pages to Pdf
    Searching and Navigating Code in VS 2010 (VS 2010 and .NET 4.0 Series)
    How to avoid StepInto unnecessary code area?
    Search and Navigation Tips/Tricks with Visual Studio
    squashing commits with rebase
    【原创】钻石继承与虚继承
  • 原文地址:https://www.cnblogs.com/xiaoaiying/p/13437092.html
Copyright © 2011-2022 走看看