SpringCloud(6) ------>Zuul网关配置

一、什么是zuul网关

  Zuul相当于是第三方调用(app应用端和PC端)和服务提供方之间的防护门。作为前端服务(Edge Service也称边缘服务,前端服务的作用是对后端服务做必要的聚合和裁剪后暴露给外部不同的设备,如PCPad或者Phone),Zuul旨在实现动态路由,监控,弹性和安全性。

二、zuul网关能做什么

(1)- 权限控制和安全性--为每个请求提供身份认证,并拒绝不满足条件的请求。

(2)- 预警和监控--跟踪前端有意义的请求和统计数据,以便我们准确了解生产环境运行状况。

(3)- 动态路由--根据需求将请求动态地路由到不同的后端集群。

(4)- 压力测试--逐渐增大到集群的流量,以便进行性能评估。

(5)- 负载均衡--为每种类型的请求分配容量并丢弃超过限额的请求。

三、SpringCloud配置Zuul网关

1、向Pom文件添加依赖

复制代码
  <!--客户端eureka-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--网关zuul-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
        <!--熔断与降级hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-netflix-hystrix</artifactId>
        </dependency>
        <!--监视和管理应用程序Springboot,查看路由-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
复制代码

2、application.yml

复制代码
spring:
  application:
    name: zuul-proxy

server:
  port: 20000

#注册中心相关配置
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    instance-id: ${spring.cloud.client.ip-address}:${server.port}

#网关配置
zuul:
#    LogFilter:    #自定义过滤器的名称
#      pre:        #自定义过滤器类型
#      disable: true  # 是否禁用 
  prefix: /api/      #前缀
  routes:   #路由规则
    user:
      path: /u/**
      url: http://localhost:9000    #远程服务必须有url
    word:
      path: /w/**
      url: http://localhost:9001
  # 关闭那些服务的默认路由
  ignored-services: user,word

  add-host-header: true
  #不对敏感资源做拦截
  sensitive-headers:
  ignored-headers:
  host:
    socket-timeout-millis: 4000 # 请求的处理时间
    connect-timeout-millis: 4000 # 请求的链接时间
#开启路由端点
management:
  endpoints:
    web:
      exposure:
        include: 'routes'
复制代码

3、启动类

在启动类上添加@EnableZuulProxy注解

@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
public class ZuulApp {
    public static void main(String[] args){
        SpringApplication.run(ZuulApp.class,args);
    }
}

4、查看路由访问接口

  通过链接地址http://localhost:端口/actuator/routes 查看简单路由信息

  通过链接地址http://localhost:端口/actuator/routes/details 查看详细路由信息

5、自定义网关过滤器

  继承ZuulFilter

复制代码
package com.donleo.zuul.filter;

import com.alibaba.fastjson.JSONObject;
import com.donleo.zuul.common.CommonResult;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.apache.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * 自定义网关过滤器
 *
 * @author liangd
 * @since 2021-01-12 18:52
 */
@Component
public class LogFilter extends ZuulFilter {
    /**
     * 过滤器的类型。可选值有:
     * pre - 前置过滤
     * route - 路由后过滤
     * error - 异常过滤
     * post - 远程服务调用后过滤
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * 同种类的过滤器的执行顺序。
     * 按照返回值的自然升序执行。
     * 值越小,级别越高
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 哪些请求会被过滤
     *
     */
    @Override
    public boolean shouldFilter() {
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
        String requestURI = request.getRequestURI();
        //只有/api/w 开头的会被过滤
        return requestURI.startsWith("/api/w");
        //true 默认所有请求都会过滤
        //return true;
    }

    @Override
    public Object run() {
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
        String remoteAddr = request.getRemoteAddr();
        String remoteHost = request.getRemoteHost();
        String requestURI = request.getRequestURI();

        //可以在此处进行日志、鉴权等
        if (requestURI.startsWith("/api/w")) {
            currentContext.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
            String method = request.getMethod();//方法额类型
            System.out.println(remoteAddr + "," + remoteHost + "访问了:" + requestURI + "方法:" + method);
            //设置为false,表示不进行路由,如果这个请求被拦截,这个方法后面的逻辑不需要执行了
            currentContext.setSendZuulResponse(false);
            //表示没有权限访问
            currentContext.setResponseBody(JSONObject.toJSONString(CommonResult.forbidden("")));
        }
        return null;
    }
}
 
复制代码

6、网关熔断降级服务配置

复制代码
@Component
public class ServerProviderFallback implements FallbackProvider {
    /**
     * getRoute方法的返回值就是要监听的挂掉的微服务的名字
     * 如果需要所有服务都走这个熔断回退,则return "*" 或 return null
     */
    @Override
    public String getRoute() {
        return "*";
    }

    /**
     * 当服务无法执行的时候,返回托底信息
     */
    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {
            /**
             *  ClientHttpResponse的fallback的状态码
             */
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK;
            }

            /**
             * ClientHttpResponse的fallback的状态码
             */
            @Override
            public int getRawStatusCode() throws IOException {
                return this.getStatusCode().value();
            }

            /**
             * ClientHttpResponse的fallback的状态码
             */
            @Override
            public String getStatusText() throws IOException {
                return this.getStatusCode().getReasonPhrase();
            }

            @Override
            public void close() {

            }

            /**
             * 设置响应体信息
             */
            @Override
            public InputStream getBody() throws IOException {
                String content = "服务不可用,请与管理员联系";
                return new ByteArrayInputStream(content.getBytes());
            }

            /**
             * 设置响应头信息
             */
            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                MediaType mt = new MediaType("application", "json", Charset.forName("utf-8"));
                headers.setContentType(mt);
                return headers;
            }
        };
    }
}
复制代码

7、过滤器的生命周期

8、过滤器的种类

  • pre:在请求被路由到目标服务前执行,比如权限校验、打印日志等功能;
  • routing:在请求被路由到目标服务时执行,这是使用Apache HttpClient或Netflix Ribbon构建和发送原始HTTP请求的地方;
  • post:在请求被路由到目标服务后执行,比如给目标服务的响应添加头信息,收集统计数据等功能;
  • error:请求在其他阶段发生错误时执行。

9、其它过滤器

过滤器名称

过滤类型

优先级

过滤器的作用

ServletDetectionFilter

pre

-3

检测当前请求是通过DispatcherServlet处理运行的还是ZuulServlet运行处理的。

Servlet30WrapperFilter

pre

-2

对原始的HttpServletRequest进行包装。

FormBodyWrapperFilter

pre

-1

将Content-Type为application/x-www-form-urlencoded或multipart/form-data的请求包装成FormBodyRequestWrapper对象。

DebugFilter

route

1

根据zuul.debug.request的配置来决定是否打印debug日志。

PreDecorationFilter

route

5

对当前请求进行预处理以便执行后续操作。

RibbonRoutingFilter

route

10

通过Ribbon和Hystrix来向服务实例发起请求,并将请求结果进行返回。

SimpleHostRoutingFilter

route

100

只对请求上下文中有routeHost参数的进行处理,直接使用HttpClient向routeHost对应的物理地址进行转发。

SendForwardFilter

route

500

只对请求上下文中有forward.to参数的进行处理,进行本地跳转。

SendErrorFilter

post

0

当其他过滤器内部发生异常时的会由它来进行处理,产生错误响应。

SendResponseFilter

post

1000

利用请求上下文的响应信息来组织请求成功的响应内容。

 

参考:https://www.cnblogs.com/jing99/p/11696192.html

 

posted @   donleo123  阅读(276)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示