zuul配置接《spingcloud(feign的配置)(三)》
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.xym</groupId>
<artifactId>xym-zuul</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
</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>Finchley.SR2</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 启动类的配置
@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient //此处测试不加也可以用
public class XymZuulApp {
public static void main(String[] args) {
SpringApplication.run(XymZuulApp.class,args);
}
}
- 配置路由映射
server:
port: 3000
spring:
application:
name: xym-zuul
zuul:
routes:
service-provide:
path: /service-provide/**
url: http://127.0.0.1:8081
- 请求效果展示
zuul面向微服务的路由
- 添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
- 配置路由映射
- 第二种配置
zuul:
routes:
service-provide:
path: /service-provide/**
serviceId: service-provide
- 第三种配置
zuul:
routes:
service-provide: /service-provide/**
- 第四种配置
不配置默认时通过服务ID访问的
#zuul:
#routes:
#service-provide: /service-provide/**
#path:
#url: http://127.0.0.1:8081
#serviceId: service-provide
效果都是这样
- 配置zuul网关的前缀
zuul:
prefix: /api
zuul过滤器的配置
Zuul作为网关的其中一个重要功能,就是实现请求的鉴权。而这个动作我们往往是通过Zuul提供的过滤器来实现的。
- ZuulFilter
ZuulFilter是过滤器的顶级父类。在这里我们看一下其中定义的4个最重要的方法:
public abstract ZuulFilter implements IZuulFilter{
abstract public String filterType();
abstract public int filterOrder();
boolean shouldFilter();// 来自IZuulFilter
Object run() throws ZuulException;// IZuulFilter
}
-
shouldFilter:返回一个Boolean值,判断该过滤器是否需要执行。返回true执行,返回false不执行。
-
run:过滤器的具体业务逻辑。
-
filterType:返回字符串,代表过滤器的类型。包含以下4种:
- pre:请求在被路由之前执行
- route:在路由请求时调用
- post:在route和errror过滤器之后调用
- error:处理请求时发生错误调用
-
filterOrder:通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高。
-
过滤器执行生命周期
这张是Zuul官网提供的请求生命周期图,清晰的表现了一个请求在各个过滤器的执行顺序。
正常流程:
- 请求到达首先会经过pre类型过滤器,而后到达route类型,进行路由,请求就到达真正的服务提供者,执行请求,返回结果后,会到达post过滤器。而后返回响应。
异常流程:
-
整个过程中,pre或者route过滤器出现异常,都会直接进入error过滤器,在error处理完毕后,会将请求交给POST过滤器,最后返回给用户。
-
如果是error过滤器自己出现异常,最终也会进入POST过滤器,将最终结果返回给请求客户端。
-
如果是POST过滤器出现异常,会跳转到error过滤器,但是与pre和route不同的是,请求不会再到达POST过滤器了。
-
自定义过滤器
@Component
public class LoginFilter extends ZuulFilter {
//四种类型 pre route error post
@Override
public String filterType() {
return "pre";
}
//返回值越小优先级越高
@Override
public int filterOrder() {
return 0;
}
//是否执行该过滤器,true执行run方法,false 不执行run方法
@Override
public boolean shouldFilter() {
return true;
}
//
@Override
public Object run() throws ZuulException {
//初始化context上下文对象
RequestContext currentContext = RequestContext.getCurrentContext();
//获取request
HttpServletRequest request = currentContext.getRequest();
String token = request.getParameter("token");
System.out.println(token);
if(StringUtils.isEmpty(token)){
currentContext.setSendZuulResponse(false);
currentContext.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
currentContext.setResponseBody("request error!");
}
//返回值为null表示什么都不做
return null;
}
}
- zuul默认集成了hystrix和ribbon
Zuul中默认就已经集成了Ribbon负载均衡和Hystix熔断机制。但是所有的超时策略都是走的默认值,比如熔断超时时间只有1S,很容易就触发了。因此建议我们手动进行配置:
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000 # 设置hystrix的超时时间为6000ms
- 在zuul网关中解决跨域问题
-
第一种解决方式
@Configuration public class ConfigCorsFilter { @Bean public CorsFilter corsFilter(){ CorsConfiguration cc = new CorsConfiguration(); //设置允许源的时候一定要用加上协议名称 cc.addAllowedOrigin("http://manage.leyou.com");//只有配置允许的源才能配置带cookie信息 cc.setAllowCredentials(true); //如果allowedOrigin配置*此项不起作用 cc.addAllowedHeader("*"); cc.addAllowedMethod("*"); UrlBasedCorsConfigurationSource ubcs = new UrlBasedCorsConfigurationSource(); ubcs.registerCorsConfiguration("/**",cc); return new CorsFilter(ubcs); } }
-
springboot的第二种解决方式
@Configuration public class MyWebMVCConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**").allowedMethods("*") .allowedHeaders("*").allowedOrigins("*"); } }
- 第三种解决办法
@CrossOrigin //在方法中添加注解
这三种方式依次越来越简单,但是起作用的时机,是有差别的,第一种方式利用的是过滤器,起作用时机最早,拦截器有可能被过滤器拦截导致没有执行到对应拦截器,方法上的注解更是这样.因此建议使用第一种,虽然它最麻烦.