Spring Cloud Zuul路由网关(学习总结)
一、简介
Spring Cloud Zuul主要的功能是:路由跳转以及路由过滤,本文主要讲解了这两方面的内容。在实际项目中,zuul中可能也会有相对复杂的逻辑,通常在zuul前面还有一个nginx反向代理,前端直接访问nginx,让nginx给我们代理到网关服务,网关服务再路由到具体的服务提供者上。zuul默认集成了ribbon实现了负载均衡功能。
二、准备工程
a. zuul-eureka-server,端口1111
b.zuul-service:服务提供者,端口2222
c.zuul-api-gateway:网关服务,端口3333
本文不对eureka服务注册中心的搭建做过多讲解,主要讲解api-gateway网关服务的搭建过程。
三、新建zuul-service服务提供者工程
zuuk-service也只是一个比较简答的服务提供者,主要是要暴露一个接口给外部进行访问。主要代码如下:
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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.springcloud.wsh</groupId><artifactId>springcloud_zuul_service</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>springcloud_zuul_service</name><description>服务提供者</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.2.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><spring-cloud.version>Camden.SR6</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
启动类:
@SpringBootApplication
@EnableDiscoveryClient
public class SpringcloudZuulServiceApplication {public static void main(String[] args) {SpringApplication.run(SpringcloudZuulServiceApplication.class, args);}
}
ZuulServiceController:
/*** @Title: ZuulServiceController* @ProjectName springcloud_zuul_api_gateway* @Description: 对外提供接口服务* @Author WeiShiHuai* @Date 2018/9/14 14:16*/
@RestController
public class ZuulServiceController {private static Logger logger = LoggerFactory.getLogger(ZuulServiceController.class);@Value("${server.port}")private String port;@RequestMapping("/getInfo/{name}")public String getInfo(@PathVariable("name") String name) {String info = "hello " + name + " ,i am from zuul service,port = " + port;logger.info(info);return info;}}
四、新建zuul-api-gateway工程
首先引入zuul的依赖,具体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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.springcloud.wsh</groupId><artifactId>springcloud_api_gateway</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>springcloud_api_gateway</name><description>Spring Cloud Zuul服务网关</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.2.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><spring-cloud.version>Camden.SR6</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-zuul</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
五、启动类加上@EnableZuulProxy注解
@EnableZuulProxy注解主要是用于开启zuul路由转发以及路由过滤功能。
/*** @Description: api网关启动类* @Author: WeiShiHuai* @Date: 2018/9/14 14:22* Zuul的主要功能是路由转发和过滤器* 通常情况下,可以在网关服务进行权限控制等,将具体业务逻辑与权限控制分开,有利于解耦; Zuul也可以实现对服务的负载均衡* Zuul主要作用是请求转发,和过滤,请求转发是做了负载均衡。Zuul也需要做一次集群,因为 Zuul是网关,可能需要做很复杂的逻辑,比如查数据库,还有静态资源,在最外一层需要再一个zuul或者nginx去路由。* 通常情况下由nginx做第一层比较好,第二层的一些例如权限等校验交由zuul处理* 路由配置方式: a、path-url方式 b、path-serviceId方式,推荐使用path-serviceId方式,方便后期网关服务维护*/
@SpringBootApplication
@EnableDiscoveryClient
//@EnableZuulProxy注解用于开启Zuul路由功能(反向代理)
@EnableZuulProxy
public class SpringcloudApiGatewayApplication {public static void main(String[] args) {SpringApplication.run(SpringcloudApiGatewayApplication.class, args);}
}
六、application.yml配置路由匹配规则
zuul的路由规则主要有两种配置方式,path-url以及path-serviceId两种方式,但是path-url不利于维护,要具体制定某个服务的url,其实在微服务中,每个服务都注册到eureka服务注册中心上,这个时候其实可以通过serviceId直接找到具体指向的服务。推荐使用path-serviceId方式配置。
server:port: 3333
spring:application:name: api-gateway
eureka:client:service-url:defaultZone: http://localhost:1111/eureka/
#服务路由:推荐使用serviceId方式配置路由,方便后期维护
zuul:routes:zuul-service-url:#通过path/url方式配置路由: 以/zuul-service-url开头的请求都转发到zuul-servicepath: /zuul-service-url/**url: http://localhost:2222/#通过path/serviceId方式配置路由: 以/zuul-service-serviceId开头的请求都转发到zuul-servicezuul-service-serviceId:path: /zuul-service-serviceId/**#对应注册到Eureka中的serviceIdserviceId: zuul-service
#通过配置以上路由,前台我们访问地址:
# http://localhost:3333/zuul-service-url/getInfo/weixiaohuai
# >>>>>路由到(实际请求的地址)>>>>>
# http://localhost:2222/getInfo/weixiaohuai# http://localhost:3333/zuul-service-serviceId/getInfo/weixiaohuai
# >>>>>路由到(实际请求的地址)>>>>>
# http://localhost:2222/getInfo/weixiaohuai
#通过配置以上路由,前台我们访问地址:
a. path-url方式:
# http://localhost:3333/zuul-service-url/getInfo/weixiaohuai
# >>>>>路由到(实际请求的地址)>>>>>
# http://localhost:2222/getInfo/weixiaohuai
b. path-serviceId方式:
# http://localhost:3333/zuul-service-serviceId/getInfo/weixiaohuai
# >>>>>路由到(实际请求的地址)>>>>>
# http://localhost:2222/getInfo/weixiaohuai
七、启动项目
分别启动eureka-servier、zuul-service、zuul-api-gateway
我们通过浏览器访问
http://localhost:3333/zuul-service-url/getInfo/weixiaohuai
可以看到,网关已经帮我们路由到zuul-service服务,成功返回数据,这是path-url方式。
接着我们访问
http://localhost:3333/zuul-service-serviceId/getInfo/weixiaohuai
可以看到,网关同样帮我们路由到了zuul-service服务,成功返回数据,这是path-serviceId方式。
以上就完成了zuul路由跳转的功能,接下来我们谈谈zuul路由过滤的功能,在实际项目中,通常需要进行权限校验的功能,这里模拟验证url中是否传username以及password参数并且校验是否正确。zuul路由过滤是通过过滤器实现的,通常继承ZuulFilter类,并且实现其中的方法即可。
ZuulFilter中方法的介绍:
a. filterType:指定过滤器的类型,可选择的值有:
pre:在路由之前执行
routing:在路由的时候执行
post:在路由完成之后执行
error:路由发生错误时执行
b. filterOrder:指定过滤器的执行顺序,数字越大,优先级越低
c. shouldFilter:是否需要过滤,return true表示需要执行该过滤器
d. run:过滤器的具体实现逻辑
下面我们创建一个校验用户名的AccessUsernameZuulFilter:
/*** @Title: AccessUsernameZuulFilter* @ProjectName springcloud_zuul_api_gateway* @Description: 校验用户名的Zuul过滤器* @Author WeiShiHuai* @Date 2018/9/14 15:02*/@Component
public class AccessUsernameZuulFilter extends ZuulFilter {private static Logger logger = LoggerFactory.getLogger(AccessUsernameZuulFilter.class);private static final String USER_NAME = "weixiaohuai";/*** 过滤器类型* pre:在路由之前执行 routing:在路由的时候执行 post:在路由完成之后执行 error:路由发生错误时执行** @return*/@Overridepublic String filterType() {return "pre";}/*** 过滤器的执行顺序* 数字越大,优先级越低** @return*/@Overridepublic int filterOrder() {return 0;}/*** 是否需要过滤,true表示过滤,false表示不过滤** @return*/@Overridepublic boolean shouldFilter() {return true;}/*** 过滤器具体校验逻辑,如权限校验等等* 实际项目中可以进行数据库查询权限数据库等等** @return*/@Overridepublic Object run() {RequestContext requestContext = RequestContext.getCurrentContext();HttpServletRequest request = requestContext.getRequest();//获取请求url中的usernameString username = request.getParameter("username");//说明用户名不为空且正确if (null != username && USER_NAME.equals(username)) {//表示让Zuul进行路由跳转requestContext.setSendZuulResponse(true);//设置响应码requestContext.setResponseStatusCode(200);logger.info("welcome,the username is valid!!");//记录这个过滤器的状态requestContext.set("isSuccess", true);return null;} else { //用户名不正确//表示让Zuul过滤这个请求,不进行路由跳转requestContext.setSendZuulResponse(false);requestContext.setResponseStatusCode(401);//记录这个过滤器的状态requestContext.set("isSuccess", false);logger.info("sorry,the username is not valid, please try again!!");requestContext.setResponseBody("sorry,the username is not valid, please try again!!");return null;}}
}
注意:
//表示让Zuul进行路由跳转requestContext.setSendZuulResponse(true);//表示让Zuul过滤这个请求,不进行路由跳转
requestContext.setSendZuulResponse(false);//设置响应码
requestContext.setResponseStatusCode(200);
八、创建校验密码的过滤器AccessPasswordZuulFilter
跟校验用户名的类似,注意在shouldFilter()方法中拿到全局保存的isSuccess变量,由于标识该过滤器是否需要被执行,如果用户名都没校验通过,显然不需要执行密码的校验。
/*** @Title: AccessPasswordZuulFilter* @ProjectName springcloud_zuul_api_gateway* @Description: 校验密码的Zuul过滤器* @Author WeiShiHuai* @Date 2018/9/14 15:37*/@Component
public class AccessPasswordZuulFilter extends ZuulFilter {private static Logger logger = LoggerFactory.getLogger(AccessPasswordZuulFilter.class);private static final String PASSWORD = "123456";/*** 过滤器类型* pre:在路由之前执行 routing:在路由的时候执行 post:在路由完成之后执行 error:路由发生错误时执行** @return*/@Overridepublic String filterType() {return "pre";}/*** 过滤器的执行顺序* 数字越大,优先级越低** @return*/@Overridepublic int filterOrder() {return 1;}/*** 是否需要过滤,true表示过滤,false表示不过滤** @return*/@Overridepublic boolean shouldFilter() {RequestContext requestContext = RequestContext.getCurrentContext();//获取上一个过滤器保存的过滤器状态,如果返回false,则说明上一个过滤器没有成功,则无需执行后面的过滤器,直接返回结果return (boolean) requestContext.get("isSuccess");}/*** 过滤器具体校验逻辑,如权限校验等等* 实际项目中可以进行数据库查询权限数据库等等** @return*/@Overridepublic Object run() {RequestContext requestContext = RequestContext.getCurrentContext();HttpServletRequest request = requestContext.getRequest();//获取请求url中的passwordString password = request.getParameter("password");//说明密码不为空且正确if (null != password && PASSWORD.equals(password)) {//表示让Zuul进行路由跳转requestContext.setSendZuulResponse(true);//设置响应码requestContext.setResponseStatusCode(200);//记录这个过滤器的状态requestContext.set("isSuccess", true);logger.info("welcome,the password is valid!!");return null;} else { //用户名不正确//表示让Zuul过滤这个请求,不进行路由跳转requestContext.setSendZuulResponse(false);requestContext.setResponseStatusCode(401);//记录这个过滤器的状态requestContext.set("isSuccess", false);logger.info("sorry,the password is not valid, please try again!!");requestContext.setResponseBody("sorry,the password is not valid, please try again!!");return null;}}
}
九、启动类注入过滤器Bean
@SpringBootApplication
@EnableDiscoveryClient
//@EnableZuulProxy注解用于开启Zuul路由功能(反向代理)
@EnableZuulProxy
public class SpringcloudApiGatewayApplication {public static void main(String[] args) {SpringApplication.run(SpringcloudApiGatewayApplication.class, args);}@BeanAccessUsernameZuulFilter accessUsernameZuulFilter() {return new AccessUsernameZuulFilter();}@BeanAccessPasswordZuulFilter accessPasswordZuulFilter() {return new AccessPasswordZuulFilter();}
}
十、启动项目
分别启动eureka-server、zuul-service、zuul-api-gateway
我们浏览器访问http://localhost:3333/zuul-service-url/getInfo/weixiaohuai或者http://localhost:3333/zuul-service-serviceId/getInfo/weixiaohuai,如下图
可以看到,如果url中没有传入username或者password参数的话,返回我们自定义的错误信息
a. 如果我们访问http://localhost:3333/zuul-service-url/getInfo/weixiaohuai?username=weixiaohuai,这时候校验用户名的过滤器已经通过,被校验密码的过滤器拦截了,提示密码不合法
b. 如果我们访问http://localhost:3333/zuul-service-url/getInfo/weixiaohuai?password=123456,同样确实username参数,如下图返回用户名不合法的错误
c. 如果我们访问http://localhost:3333/zuul-service-url/getInfo/weixiaohuai?username=weixiaohuai&password=123456,这时候路由就成功跳转到zuul-service中
至此,zuul路由过滤功能已经实现完成。在实际项目中,需要结合权限验证框架进行实现,这里只是演示zuul过滤器的一些用法。本文是作者在学习过程中的一些总结,文章仅供参考,希望大家一起学习,共同进步。
Spring Cloud Zuul路由网关(学习总结)相关推荐
- Spring Cloud Zuul API 网关服务
API 网关是一个更为智能的应用服务器,它的定义类似于面向对象设计模式中的 Facade 模式,它的存在就像是整个微服务架构系统的门面一样,所有的外部客户端访问都需要经过它来进行调度和过滤.它除了要实 ...
- Spring Cloud Zuul中使用Swagger汇总API接口文档
有很多读者问过这样的一个问题: 虽然使用Swagger可以为Spring MVC编写的接口生成了API文档,但是在微服务化之后,这些API文档都离散在各个微服务中,是否有办法将这些接口都整合到一个文档 ...
- Spring Cloud Zuul防DDOS攻击
前一段时间,公司的短信服务经常收到预警,当时初步猜测我们的短信服务受到了攻击,于是想到了两种实现方案. 方案一: 采用nginx防止DDOS(网上有很多案例可以借鉴) 方案二: 采用Spring Cl ...
- Spring Cloud Zuul中使用Swagger汇总API接口文档 1
有很多读者问过这样的一个问题:虽然使用Swagger可以为Spring MVC编写的接口生成了API文档,但是在微服务化之后,这些API文档都离散在各个微服务中,是否有办法将这些接口都整合到一个文档中 ...
- 《深入理解 Spring Cloud 与微服务构建》第十章 路由网关 Spring Cloud Zuul
<深入理解 Spring Cloud 与微服务构建>第十章 路由网关 Spring Cloud Zuul 文章目录 <深入理解 Spring Cloud 与微服务构建>第十章 ...
- API 网关服务:Spring Cloud Zuul(二):路由详解、Cookie 与头信息
实践出于<Spring Cloud 微服务实战> - 瞿永超 著 路由详解 传统路由配置 传统路由配置就是在不依赖于服务发现机制的情况下,通过在配置文件中具体指定每个路由表达式与服务实 ...
- SpringCloud学习系列之七 ----- Zuul路由网关的过滤器和异常处理
前言 在上篇中介绍了SpringCloud Zuul路由网关的基本使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由 ...
- Spring Cloud Zuul网关 Filter、熔断、重试、高可用的使用方式
时间过的很快,写springcloud(十):服务网关zuul初级篇还在半年前,现在已经是2018年了,我们继续探讨Zuul更高级的使用方式. 上篇文章主要介绍了Zuul网关使用模式,以及自动转发机制 ...
- Spring Cloud(四) API网关Zuul
前文回顾: Spring Cloud(一)Eureka Server-单体及集群搭建 Spring Cloud(二) 配置Eureka Client Spring Cloud(三) 熔断器Hystri ...
- Spring Cloud Zuul网关 Filter、熔断、重试、高可用的使用方式。
时间过的很快,写springcloud(十):服务网关zuul初级篇还在半年前,现在已经是2018年了,我们继续探讨Zuul更高级的使用方式. 上篇文章主要介绍了Zuul网关使用模式,以及自动转发机制 ...
最新文章
- 《数据科学:R语言实现》——3.12 估计缺失数据
- leetcode两数之和
- python logging模块使用教程
- linux创建逻辑目录,Linux创建逻辑卷
- java canvas旋转_在HTML5 Canvas上将图像旋转90度
- openssh 加固
- 【优化算法】社会群体优化算法(SGO)【含Matlab源码 1449期】
- android 执行Shell命令
- 【实习之T100开发】帆软报表笔记
- ExtremeComponents源码解析(一)
- 最最简单的使用DW编程软件
- 菜鸟学R语言(方差分析)
- F.dropout()与nn.dropout()
- 盛迈坤电商:店铺推广的技巧分享
- 纯css3卡通火龙果
- [Python]安装/升级pip/pip3
- 禁止win7系统flash插件自动更新教程【系统天地】
- Content-Type四种常见取值application/x-www-form-urlencoded,multipart/form-data,application/json,text/xml
- 【ThreeJS基础教程-初识Threejs】1.3 右手坐标系
- Python数据处理与分析小项目-分析员工过早离职原因
热门文章
- 怎么看蛋白质编码序列_墨鱼的“墨汁”可以吃吗,它有什么营养?看完就明白,涨知识了...
- Otsu‘s Thresholding的工作原理
- C/C++[PAT B1022]D进制的A+B
- python append和extend_Python中append和extend区别
- 对于Y=Hx的H细节的一些讨论
- NLP系列(2)_用朴素贝叶斯进行文本分类(上)
- python urllib2详解及实例
- 【OpenGL 实验一】图元的生成+区域填充
- linux内核event原理,linux epoll epoll的原理;struct epoll_event 为什么要这样设计
- 攻防世界 ics-05 write up