spring cloud --- Zuul --- 心得

spring boot      1.5.9.RELEASE

spring cloud    Dalston.SR1

1.前言

什么是 Zuul?

   Zuul是微服务网关,与Gateway类似 ,根据请求的url不同,路由到不同的服务上去,同时入口统一了,还能进行统一的身份鉴权、日志记录、分流等操作。也称为API网关 ,API是应用程序接口的意思 。

2.操作

(1)引入依赖

  <!-- zuul路由网关 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zuul</artifactId>
        </dependency>

完整pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.atguigu.springcloud</groupId>
        <!--    父级maven模块的工程名字-->
        <artifactId>microservicecloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo-my-cen-zuul</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo-my-cen-zuul</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

        <!-- actuator监控 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- zuul路由网关 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zuul</artifactId>
        </dependency>




    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
View Code

(2)启动类开启 zuul网关

 //注解@EnableZuulProxy是 @EnableZuulServer 的加强版 ,是个组合注解,包括了@EnableZuulServer 和@EnableEurekaClient 的功能,

//当然 ,添加@EnableEurekaClient也是没问题的,也可以不加

(3)application.properties文件配置信息

#本服务端口
server.port=114
# 本服务在服务注册中心的注册应用名
spring.application.name=service-zuul
#全局添加前缀,如 localhost:114/myzuul/test/bb ,用于识别是否需要转发路由操作
zuul.prefix=/myzuul
#//默认是false,这里是全局配置
#zuul.strip-prefix: //是否将这个代理前缀去掉
#
#忽略所有的,表示禁用默认路由,只认我们自己配置的路由.
zuul.ignored-services="*"
#
#忽略某些路径,起过略路径含有/admin/的请求
#zuul.ignoredPatterns= /**/admin/**
#
#设置路由,转接到分布式服务的消费者
zuul.routes.api-a.path=/test/**
zuul.routes.api-a.service-id=DEMO-MY-CEN-TEST
#zuul.routes.api-a.strip-prefix: //是否将这个代理前缀去掉,这里是局部设置,访问test服务可以不添加全局前缀
zuul.routes.api-b.path=/feign/**
zuul.routes.api-b.service-id=520LOVE
#
#向服务注册中心注册自己为服务,默认是注册,因此可以不写
#eureka.client.register-with-eureka=true
# 服务注册中心节点地址
eureka.client.service-url.defaultZone=http://localhost:7001/eureka/
View Code
设置路由 zuul.routes.api-a.path 里的 api-a是可以随便写的,但是只有不与其他的路由设置不重复就可以,一般会写成对应的服务名字

注意,/** 不是乱写的
看图

(4)到了关键性一步,写 拦截过滤的具体逻辑类

先看看目录结构

名字随意,但是,需要继承父类 ZuulFilter ,然后重写方法

完成源码

package com.example.demomycenzuul.myFilter;


import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.apache.commons.lang.StringUtils;

import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.logging.Logger;


//重写zuulFilter类,有四个重要的方法
@Component
public class AccessFilter extends ZuulFilter {

    //`filterType`:返回字符串,代表过滤器的类型。包含以下4种:
    //             - `pre`:请求在被路由之前执行
//                 - `routing`:在路由请求时调用
//                 - `post`:在routing和errror过滤器之后调用
//                 - `error`:处理请求时发生错误调用
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    //    `filterOrder`:通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高
    @Override
    public int filterOrder() {
        return 0;
    }

    //        `shouldFilter`:返回一个`Boolean`值,判断该过滤器是否需要执行。返回true执行,返回false不执行。
    @Override
    public boolean shouldFilter() {

        return true;
    }


    //    `run`:过滤器的具体业务逻辑。
    @Override
    public Object run() {
        System.out.println("进入zuul拦截");
        //获取上下文
        RequestContext ctx = RequestContext.getCurrentContext();
        //获取Request
        HttpServletRequest request = ctx.getRequest();
        //获取请求参数accessToken
        String accessToken = request.getParameter("accessToken");
        //使用String工具类
        if (StringUtils.isBlank(accessToken)) {
            ctx.setSendZuulResponse(false);  //进行拦截
            ctx.setResponseStatusCode(401);
            try {
                ctx.getResponse().getWriter().write("accessToken is empty,-------401");
            } catch (Exception e) {
            }
            return null;
        }
        return null;
    }

}
View Code

记住了啊,注解@Component 必须加上,不然因为没有注册bean导致找不到 ,@Component的使用可以看我的另一篇随笔

 3.测试

(1)提前注备一个注册中心端口7001 ,2 个服务提供者端口 8001、8003  ,2个服务消费者端口520 、565 ,以及这个zuul网关 端口114

需要注意的是 ,这些 端口都需要注册到 eureka 服务注册中心 7001里面 ,不然zuul找不到消费者实例

 

(2)输入网址 http://localhost:114/myzuul/test/bb ,/myzuul是zuul网关前缀,test是拦截路径,对应了服务消费者 DEMO-MY-CEN-TEST,

这都是在zuul的application 配置文件设置的

 

 浏览器响应

 被网关拦截,因为没有认证参数,被拒绝了路由

输入网址 http://localhost:114/myzuul/test/bb?accessToken=666 

 (3)因为8001、8003是集群 ,消费者565 的客户端均衡策略默认是轮询策略,

再次输入网址 http://localhost:114/myzuul/test/bb?accessToken=666 

 (4)访问消费者端口520 , 输入网址 http://localhost:114/myzuul/feign/bb?accessToken=666 

消费者520 的客户端均衡策略默认是最佳空闲策略BestAvailableRule, 因此让其调用服务提供者端口8003就不演示了

zuul网关成功拦截请求并做逻辑业务,然后成功转发相应的微服务并获取到结果

完美,撒花

--------------------------------------------

参考博文原址:

 https://blog.csdn.net/weixin_41133233/article/details/85166383?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-1

 https://blog.csdn.net/JinXYan/article/details/90736561

  

原文地址:https://www.cnblogs.com/c2g5201314/p/12892148.html