Spring Cloud Zuul - API网关服务
解决微服务中前置校验【冗余】的问题。
可以将于业务无关的校验等剥离出独立项目,由Zuul进行统一调用前置过滤拦截请求。【感觉有点像AOP,不过这个级别就大了】
基础搭建
- 创建新项目feign-consumer
pom.xml
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Brixton.SR5</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
主类注释:
@EnableZuulProxy @SpringCloudApplication public class FeignConsumerApplication { public static void main(String[] args) { SpringApplication.run(FeignConsumerApplication.class, args); } }
配置文件:
spring.application.name=api-getaway server.port=5555 eureka.client.service-url.defaultZone=http://localhost:1111/eureka/ #传统配置 并不适用 #zuul.routes.api-a-url.path=/api-a-url/** #zuul.routes.api-a-url.url=http://localhost:8080/ # 面向服务路由 e.g. http://localhost:5555/api-a/hello 会跳转到 hello-server/hello http://localhost:1234/hello【hello-server地址】 zuul.routes.api-a.path=/api-a/** zuul.routes.api-a.serviceId=hello-service zuul.routes.api-b.path=/api-b/** zuul.routes.api-b.serviceId=feign-consumer #另一种写法【一样的效果】 #zuul.routes.hello-service=/api-a/**
到这里已经完成了,简单的API面向服务的路由配置跳转。
e.g. http://localhost:5555/api-a/hello 会跳转到 hello-server/hello 既 http://localhost:1234/hello【hello-server地址】
请求过滤 【核心功能】
栗子:
AccessFilter:
public class AccessFilter extends ZuulFilter{
/*过滤类型,决定在请求的哪个阶段执行,pre表示被路由之前执行*/
/* pre:路由前 ; routing :路由请求时 ; post :在routing 和 error 之后 ; error:处理请求时发生错误时 ;*/
@Override
public String filterType() {
return "pre";
}
/*过滤器的执行顺序,根据返回值依次执行*/
@Override
public int filterOrder() {
return 0;
}
/*判断过滤器是否需要执行*/
@Override
public boolean shouldFilter() {
return true;
}
/*过滤器具体逻辑代码*/
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
//log.info("send {} request tpo {}",request.getMethod(),request.getRequestURL().toString());
System.out.println("send {"+request.getMethod()+"} request tpo {"+request.getRequestURL().toString()+"}");
Object accessToken = request.getParameter("accessToken");
if (accessToken == null){
ctx.setSendZuulResponse(false); /*设置不进行路由*/
ctx.setResponseStatusCode(401); /*设置返回错误码*/
return null;
}
System.out.println("access token ok");
return null;
}
}
主类【增加】:
@Bean
public AccessFilter accessFilter(){
return new AccessFilter();
}
OK 这样就可以了。http://localhost:5555/api-a/hello?accessToken=11111 访问这个地址才会进行路由
如果没有参数?accessToken=11111 则不进行路由 ,返回错误码401 【HTTP ERROR 401】
默认路由配置
在所有都没有配置的情况下,Zuul是会自动进行路由的。默认的规则是
zuul.routes.hello-service=/hello-service/**
所以默认情况下【不进行路由配置】,测试的项目http://localhost:5555/hello-service/hello?accessToken=11111 这个是可以被路由的
为此,如果不想进行自动路由,则需要使用 一下配置:
zuul.ignored-services=* #b表示对所有路由都不自动创建路由规则
zuul.ignored-patterns = /**/hello/** # 不对此规则地址进行路由 【忽略表达式】
自定义路由映射规则
比如,要把helloservice-v1,helloservice-v 路由为/v1/helloservice/** 【默认是/helloservice-v/**这个样子的】
需要在主类中添加:
@Bean
public PatternServiceRouteMapper serviceRouteMapper(){
return new PatternServiceRouteMapper(
"(?<name>^.+)-(?<version>v.+$)",
"${version}/${name}");
}
使用的是正则表达式匹配!
路径配置说明:
? 任意单个字符
* 任意多个字符
** 任意数量字符,支持多级目录
由于配置路径取决于规则保存顺序,而由于properties配置内容无法保证有序,为保证优先顺序,需要使用YAML文件配置。
路由前缀
zuul.prefix=/api
Cookie 与头信息
敏感信息
Zuul 在请求路由时,会过滤HTTp请求头信息中的敏感信息。包括:cookie,set-cookid,Authorization,属性,常用于web应用的Spring Security 和 Shiro等安全框架都搞不定,要做一些参数的修改配置。
全局参数为空覆盖默认值:【不推荐使用】
zuul.sensitiveHeaders=
指定路由开启自定义敏感头
zuul.routes.<router>.customSensitiveHeaders=true
将指定路由的敏感头试着为空
zuul.routes.<touter>.sensitiveHeaders=
重定向
Netflix 1.2.x版本配置:
zuul.addHostHeader=true
Hystrix 和 Ribbon 支持
Zuul 本身就有hystrix 和 ribbon 的功能,配置什么的也就那样,这里忽略。。。。。(ノ`Д)ノ
过滤器
zuul 默认就有好多的过滤器,对请求信息进行过滤等操作。
禁用过滤器
zuul.AccessFilter[过滤器名].pre[过滤器类型].disable = true
动态配置 【核心】
这里要用到 Spring Cloud Config 分布式配置中心 还没看,不懂怎么玩 之后再补上
这里加上配置中心之后可以做到动态路由、动态过滤器的
动态路由
在学习了spring-cloud-config 之后,发现其实这个动态路由只要把zuul连到服务架构上,并使用config的远程配置即可。
不同的地方在于,启动类要添加一下东东,其他地方与正常的config-client一样了
@Bean
@RefreshScope
@ConfigurationProperties("zuul")
public ZuulProperties zuulProperties(){
return new ZuulProperties();
}
动态过滤器
> 这个要使用到zull,eureka,groovy 来配置,感觉好麻烦,需要使用的时候再研究好了
小杭 20180314