Zuul Api网关是一个更为智能、安全的服务,可以对我们内部服务进行包装,所有的外部访问都通过该服务进行过滤拦截校验、路由转发、负载均衡等功能。
Zuul和Eureka结合,默认会将服务名作为ContextPath的方式创建路由映射。
构建Zuul网关
1、添加依赖pom.xml
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-zuul -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
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
通过上边的配置可知道,针对不同的服务有不同的路由地址,但是我们都知道每个子应用一般都会有多个实例,那么配置要转发的路径就会很麻烦。我们知道使用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
结合config实现动态路由
1、添加config依赖
<!--config客户端依赖-->
<!--https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-config-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
<!--连接重试-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
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();
- filterType:返回字符串代表不同的过滤器类型,包含四种过滤器:
pre:请求被路由之前调用。
routing:在路由请求时调用。
post:在routing和error之后被调用。
error:在处理请求发生异常时调用。 - filterOrder:通过int值来定义过滤器执行顺序,数值越小越先执行。
- shouldFilter:返回boolean值标识该过滤器是否执行。
- 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;
}
zuul优化
环境:spring cloud-F 、spring boot 2.0.7、
第一步:优化内嵌服务器tomcat
server:
tomcat:
accept-count: 1000 ##当达到最大线程时,加入
max-threads: 1000 ##windows 最大2000;linux 环境最大 1000
min-spare-threads: 500
connection-timeout: 60000
第二步:优化zuul
zuul:
ratelimit:
enabled: false
semaphore:
max-semaphores: 20000
host:
max-per-route-connections: 500
max-total-connections: 6000
connect-timeout-millis: 70000
socket-timeout-millis: 60000
第三步:优化ribbon负载均衡
ribbon: ##默认是restclient
okhttp:
enabled: true
http:
client:
enabled: false
MaxConnectionsPerHost: 500
MaxTotalConnections: 2000
ConnectTimeout: 60000
ReadTimeout: 60000
添加依赖
<!-- okhttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
参考:
https://blog.csdn.net/liuminglei1987/article/details/104282000
https://blog.csdn.net/zhousenshan/article/details/89811378
http://www.seotest.cn/jishu/42839.html
https://blog.csdn.net/songhaifengshuaige/article/details/74188106