Zuul Api网关是一个更为智能、安全的服务,可以对我们内部服务进行包装,所有的外部访问都通过该服务进行过滤拦截校验、路由转发、负载均衡等功能。
Zuul和Eureka结合,默认会将服务名作为ContextPath的方式创建路由映射。
1、添加依赖pom.xml
org.springframework.cloud
spring-cloud-starter-zuul
1.3.5.RELEASE
2、添加配置文件 .properties
#取消自动配置路由,默认会为服务以serviceId 作为路由,避免不必要的服务对外开放
zuul.ignored-services=*
#过滤路径
zuul.routes.client-one.path=/one/**
#根据过滤路径配置路由地址
zuul.routes.client-one.url=http://192.168.2.83:8181/
3、启动类添加注解,开启zuul功能
@EnableZuulProxy
默认依赖 ribbon、hystrix
@EnableCircuitBreaker
@EnableDiscoveryClient
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ZuulProxyMarkerConfiguration.class)
public @interface EnableZuulProxy {
}
spring-cloud-starter-hystrix:该依赖在网关服务中实现对微服务转发时的保护,通过线程隔离、断路器,防止微服务的故障引发Api网关资源无法释放,影响整个对外服务。
spring-cloud-starter-ribbon:该依赖使网关服务在进行路由时对要转发的服务实现客户端的负载均衡、请求重试
通过上边的配置可知道,针对不同的服务有不同的路由地址,但是我们都知道每个子应用一般都会有多个实例,那么配置要转发的路径就会很麻烦。我们知道使用eureka-client每个应用在启动之后都会向eureka-server进行注册,并会存储注册中心上维护的实例列表在本地,那么依靠这个特性,我们把zuul也作为一个eureka-client进行注册,则会获取各个服务的实例清单,那么符合路由规则的请求就会转发到相应的实例上,通过ribbon进行负载均衡,只需
#配置注册eureka地址
eureka.client.service-url.defaultZone=http://192.168.2.83:7081/eureka/
##集成eureka后根据服务名进行路由
zuul.routes.client-demo.path=/demo/**
zuul.routes.client-demo.serviceId=clientdemo
1、添加config依赖
org.springframework.cloud
spring-cloud-starter-config
1.4.0.RELEASE
org.springframework.retry
spring-retry
org.springframework.boot
spring-boot-starter-aop
2、添加配置文件
#配置注册eureka地址
eureka.client.service-url.defaultZone=http://192.168.2.83:7081/eureka/
#配置-配置文件
#开启通过服务访问config
spring.cloud.config.discovery.enabled=true
#config服务名
spring.cloud.config.discovery.service-id=config-server
#配置文件${application}
spring.cloud.config.name=zuul-client
#仓库中通过profile定位配置文件
spring.cloud.config.profile=dev
#配置仓库文件分支
spring.cloud.config.label=dev
##开启配置文件的快速失败与重试
spring.cloud.config.fail-fast=true
##配置重试参数,一下配置的是默认值
#最大重试次数
spring.cloud.config.retry.max-attempts=6
#重试间隔,毫秒
spring.cloud.config.retry.initial-interval=1000
#重试乘数,下次重试的间隔 1.1*当前重试时间
spring.cloud.config.retry.multiplier=1.1
#最大重试时间,毫秒
spring.cloud.config.retry.max-interval=2000
##ribbon重试
#开启服务重试机制
spring.cloud.loadbalancer.retry.enabled=true
#请求连接超时时间,默认250
ribbon.ConnectTimeout=60000
#请求处理的超时时间,默认1000
ribbon.ReadTimeout=60000
#对虽有请求都进行重试,默认 true
ribbon.OkToRetryOnAllOperations=true
#切换实例的重试次数,默认 2
ribbon.MaxAutoRetriesNextServer=2
#对当前实例的重试次数,默认 1
ribbon.MaxAutoRetries=1
#开启feign断路器功能
feign.hystrix.enabled=true
#断路器超时时间,默认为2000,该时间要大于ribbon的时间,否则会触发重试机制,zuul服务设置的时间要大于等于其他应用配置的时间
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=60000
3、动态获取zuul配置
@RefreshScope --动态刷新配置
@RefreshScope
@ConfigurationProperties(prefix = "zuul")
public ZuulProperties zuulProperties(){
return new ZuulProperties();
}
4、把路由规则配置在配置文件中,通过调:/refresh 接口进行刷新配置,来实现动态路由。
zuul的另一个功能过滤,实现请求校验、服务聚合等功能,zuul过滤器包含四个基本方法:filterType(),fileOrder()、shouldFilter()、run();
要实现自定义zuul拦截器通过继承 ZuulFilter 并覆写上述的四个方法来实现
案例:
@Component
public class AccessFilter extends ZuulFilter{
/**
* @author:XingWL
* @description:过滤器类型,决定过滤器在请求的哪个生命周期中执行。
* pre--代表请求在被路由之前执行
* @date: 2019/4/26 15:06
*/
@Override
public String filterType() {
return "pre";
}
/**
* @author:XingWL
* @description:过滤器执行顺序,当请求在一个阶段中存在多个过滤器时,需要根据该方法的返回值来依次执行。
* @date: 2019/4/26 15:09
*/
@Override
public int filterOrder() {
return 0;
}
/**
* @author:XingWL
* @description:判断该过滤器是否需要被执行。默认关闭,实际应用中可以利用该函数指定顾虑器的有效范围
* @date: 2019/4/26 15:12
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* @author:XingWL
* @description:过滤器的具体逻辑
* @date: 2019/4/26 15:14
*/
@Override
public Object run() {
RequestContext ctx =RequestContext.getCurrentContext();//获取请求上下文
HttpServletResponse response=ctx.getResponse();//获取响应
HttpServletRequest request=ctx.getRequest();//获取请求
response.setCharacterEncoding("utf-8");
response.setHeader("Access-Control-Allow-Origin", "*"); //解决跨域访问报错,指定该响应的资源是否被允许与给定的origin共享
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");//允许通过的请求方式
response.setHeader("Access-Control-Allow-Credentials", "true");//表示是否可以将请求的响应 暴露给页面
response.setHeader("Access-Control-Max-Age", "3600"); //设置过期时间
/*
* Access-Control-Allow-Headers 用于preflight request(预检请求)中,
* 列出将会在正式请求Access-Control-Expose-Headers字段中出现的头部信息
*
* X-Requested-With ajax请求
*/
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,accessToken");
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // 支持HTTP 1.1.
// response.setHeader("Pragma", "no-cache"); // 支持HTTP 1.0. response.setHeader("Expires", "0");
//获取请求路径
String url = request.getRequestURL().toString();
Object accessToken=request.getHeader("accessToken");//从请求头获取参数
if(accessToken==null || "".equals(accessToken)){
ctx.setSendZuulResponse(false);//设置该请求不进行路由
ctx.setResponseStatusCode(401);//设置返回状态码
}
return null;
}