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>
(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/
设置路由 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; } }
记住了啊,注解@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