Zuul API 网关

Zuul

1.集成了Ribbon

2.集成了Hystrix(流量防卫兵)

3.就相当于一个代理

4.基于过滤器

5.统一的请求入口

6.统一权限校验

使用步骤:

1.先建spring模块

2.pom.xml 添加 zuul + eureka client + sp01-commons

3.yml

zuul:
    route:
        item-service: /item-service/**
        user-service: /user-service/**
        order-service: /oreder-service/**

4.启动类添加注解: @EnableZuulProxy

统一的权限校验:

1.首先去先建一个AccessFilter 继承ZuulFilter(过滤器的父类)

2.按规则实现

3.添加@Component 注解

4.zuul默认有5个过滤器

5.重写ZuulFilter中的4个抽象方法

filterType(返回值为String):设置这个过滤器的类型 

(return "pre" ;return FilterConstants.PRE_TYPE;这两种都可以指定过滤器类型)

filterOrder(返回类型:int): 设置过滤器的执行顺序(只能往后加过滤器,不能往这五个之前加)retrun 就是顺序

shouldFliter(返回类型:Boolean) :针对当前请求是否执行下面的过滤

run(Object):对应的过滤代码

完成拦截器:(举个栗子,只有登录了带有token才可以去访问商品服务)

1.设定过滤器类型为pre

2.设置该浏览器执行顺序为6

3.分析业务,当请求商品服务的时候,要对其进行判断权限,请求其他模块的时候不需要进行验证直接访问,所以我们要在shouldFilfter中进行业务逻辑的书写,通过RequsetContext对象获去上下文对象(通过该对象的.getCurrentContext()可以获取上下文返回值类型为RequestContext)紧接着通过上下文信息对象去获取serviceId也就是服务名,【上下文对象.get(FilterConstants.SERVICE_ID_KEY)获取到对应的服务名,返回值是Object,要强转为String类型】,最后比对ServiceId是否等于商品服务对应的服务名,若相同返回true,执行run方法,若不相等返回false,直接放行    

4.完成run方法,这个方式是当shouldFliter为true的时候才会调用,根据业务,我们首先也要获取上下文对象,(重复上个方法的操作),但我们这次要比对的是token的值是否有,通过上下文对象的方法getRequest()获取请求的信息对象(返回值是一个HttpServletRequest类型),通过这个请求信息对象使用方法getParameter("要获取的信息名")在这个业务就要这样写【getParameter("token")返回值是一个String】

        StringUtils的两个Api:

                .isBlank可以判断一个字符串是否为 null / ""(空串) /  "  "(里面只有空格)  符合返回TRUE, 反之返回False

                .isEmpty可以判断一个字符串是否为 null 与  空串  返回一样Boolean类型,规则同上

5.还是在run方法中去判断token是否存在于这个请求中,通过StringUtils.isBlank(token)去做判断

若是空的或者为null就去阻止这个请求后续的调用通过:

currentContext/*该请求的上下文信息对象*/.setSendZuulResponse(false);  //false表示阻止,true表示放行

做完上述操作,要对返回客户端的数据进行定义,第一步告诉客户端返回的数据是啥类型的

currentContext/*(该请求的上下文信息对象)*/.addZuulResponseHeader("Context-type","application/json;charset=utf8"); 
/*"Context-type","application/json;charset=utf8"这段代码的意义在于写响应的头,确定了返回值类型为json,编译用utf8*/

第二步:将响应转换为json格式的字符串进行传递给前端,我们使用的是通用服务里的JsonResult对象进行封装,其有一个静态方法,.build(状态码,提示信息)返回值类型为String。

第三步:currentContext/*(该请求的上下文信息对象)*/.setResponseBody(json)

上一步方法在于设置响应体里的东西 。注意:这个run方法有个return,当前zuul版本没有使用这个返回值,返回啥都是无效的,就是反不返回都可以,作者为了zuul后续版本的更新

  • 默认启用负载均衡
  • 默认不启用重试
    • 在网关启用重试会使后台服务压力倍增,大面积出现故障‘’
    • 启用重试(不推荐)1.添加依赖:spring-retry依赖  2.yml配置 zuul.retryable = true

Hystrix(与sentinel功能类似)

系统容错和限流工具 (两个手段降级限流)

  • 容错 - 通过降级来容错  容错是处理错误的,执行降级
  • 限流 - 通过熔断来限流  过热保护,断开链路
    • 流量过大,后台服务出现故障,通过熔断,限制后台服务的流量
    • 熔断的条件:自动触发的
      • 10秒内,达到20次请求,就会认为请求过大 (要首先满足,才回去检查下一个条件)
      • 50%出错,执行降级代码
    • 断路器(全自动打开与关闭,不需要任何配置)打开后(拉闸),会进入半开状态,尝试向后台服务发一次客户端请求
      • 调用成功,关闭断路器(合闸)
      • 调用失败,继续保持打开状态(拉闸)

Zuul集成了Hystrix实现容错(降级)

Zuul默认已经启用了Hystrix 

怎么实现降级呢:

        1.在zuul网关这个服务中新建一个降级类,实现FallbackProvider 接口

        2.添加@Component注解 将这个降级类加入到spring容器进行管理

        3.这个降级类中里面要实现接口的两个方法 getRoute是指定要进行过滤的类

    /*
     * 设置对那个服务应用进行降级
     * item-service  只针对一个服务降级
     * “*”  所有服务都应用当前降级类
     *  null 所有服务都应用当前降级类
     * 
        */
    @Override
    public String getRoute() {
        return "item-service";
    }




    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {

            //状态码   HttpStatus  状态码 + 状态信息
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.INTERNAL_SERVER_ERROR;
            }
            //  RawStatusCode 单独返回上面的状态码
            @Override
            public int getRawStatusCode() throws IOException {

                return HttpStatus.INTERNAL_SERVER_ERROR.value();
            }
            //StatusText 单独返回HttpStatus 中的状态信息
            @Override
            public String getStatusText() throws IOException {
                return HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase();
            }

            @Override
            public void close() {
//                用来关闭InputStream
//                ByteArrayInputStream 不占用底层系统资源,不需要关闭,在JVM内存里面的Byte数组
            }

            @Override
            public InputStream getBody() throws IOException {
                String json = JsonResult.build(500, "调用后台服务出错", null).toString();
                //将json封装到一个输入流中,使用ByteArrayInputStream
                ByteArrayInputStream s = new ByteArrayInputStream(json.getBytes("UTF-8"));
                return s;
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders h = new HttpHeaders();
                h.add("Content-type", "application/json;charset=UTF-8");
                return h;
            }
        };
    }
  • zuul的自动配置,会自动发现降级类的实例,自动完成配置

Hystrix数据监控

1.用actuator(导入zuul时已经导入了)暴露Hystrix的监控数据  默认是输出health 和 info等级

        1.健康状态

        2.spring容器中的所有对象

        3.spring mvc 的所有路径

        4.java虚拟机的堆内存镜像

        5.hystrix利用actuator暴露了自己的监控日志数据

请求:http://localhost:3001/actuator  显示actuator的目录,里面有对应的网址可以查看数据

Hystrix Dashboard 监控图表

1.新建Spirng模块:sp07-hysrtix-dashboard

2.在Dashboard服务中添加依赖:hystrix-dashboard  并且让其称为父项目的子项目

3.yml  允许抓取的服务器列表

4.启动类注解:@EnableHystrixDashboard

访问:http://localhost:4001/hystrix  就可以去看到进行监控的服务的图表,但当服务没有访问的时候也不会自动显示

网关也要高可用,

知识点:想要监控多个服务器的日志,怎么办,引入Turbine,这个组件可以从多个服务器抓取日志进行聚合

怎么使用Turbine:

1.新建Turbine模块

2.pom.xml

                1.添加turbine依赖    

                  spring-cloud-starter-netflix-turbine

                2.添加Eureka依赖(因为要去注册表获取服务的地址,才能实现监控)

                                spring-cloud-starter-netflix-eureka-client

3.yml配置

        1.聚合的服务: zuul (若有多个服务逗号隔开)

        2.为聚合后的数据进行命名: new String("default")(默认的就是default,格式必须这么写)

pring:
  application:
    name: turbin

server:
  port: 5001

eureka:   #添加eureka客户端的配置
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka

turbine:  #设定turbine要聚合的服务   
  app-config: zuul  #服务多了就用逗号隔开
  cluster-name-expression: new String("default")

4.启动类注解: @EnableTurbine

        1.聚合日志的地址:  http://localhost:5001/turbine.stream

             

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值