SpringCloud五大组件Zuul
介绍:
Zuul是Netflix开源的微服务网关,可以和Eureka、Ribbon、Hystrix等组件配合使用,Spring Cloud对Zuul进行了整合与增强,Zuul默认使用的HTTP客户端是Apache HTTPClient,也可以使用RestClient或okhttp3.OkHttpClient。 Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/user/info转发到到user服务。zuul默认和Ribbon结合实现了负载均衡的功能
第一步、我们先创建一个SpringBoot项目起名为:zuul,Pom配置如下:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<parent>
<groupId>主Pom的GroupId</groupId>
<artifactId>主Pom的ArtifactId</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.*.*</groupId>
<artifactId>zuul</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>zuul</name>
<description>project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.lezhu.cloud.LeZhuBootCloudZuulApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
二、ZuulApplication类加上注解@EnableZuulProxy,开启zuul的功能,代码如下:
@EnableZuulProxy
@EnableDiscoveryClient
@SpringBootApplication
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
三、application.yml配置如下:
spring:
application:
name: zuul-server
server:
port: 28580
eureka:
instance:
#开启IP注册
prefer-ip-address: true
#地址名称
instance-id: ${spring.cloud.client.ip-address}:${server.port}
#心跳
lease-renewal-interval-in-seconds: 5
#无心跳,十秒踢出
lease-expiration-duration-in-seconds: 10
#获取此实例的相对健康检查URL路径。 健康检查页面URL,然后构造出主机名和通信的类型 - 安全或不安全,如securePort和nonSecurePort规定。 它通常用于制造基于实例的健康做出明智的决策 - 例如,它可以被用来确定是否进行部署到整个服务器场或停止部署,而不会造成进一步的损害。
health-check-url-path: /actuator/health
client:
#表示的频率(以秒为单位)来从eureka服务器注册表的信息
registryFetchIntervalSeconds: 5
service-url:
defaultZone: ${EUREKA_SERVICE_URL:http://localhost:28001}/eureka/
zuul:
routes:
user:
path: /user/**
serviceId: user
max:
host:
connections: 5000
socket-timeout-millis: 60000
connect-timeout-millis: 60000
#未传递到下游请求敏感头的列表。 默认为“安全”组通常含有用户凭据头。 这是确定的,以消除那些从列表中,如果下游的服务是一样的系统作为代理的一部分,所以它们共享认证数据。
sensitive-headers:
#标志以确定是否代理转发的主机头。
add-host-header: true
###SpringCloud feign 默认开启支持ribbon
ribbon:
MaxAutoRetries: 1 #最大重试次数,当Eureka中可以找到服务,但是服务连不上时将会重试
MaxAutoRetriesNextServer: 1 #切换实例的重试次数
OkToRetryOnAllOperations: false # 对所有的操作请求都进行重试,如果是get则可以,如果是post,put等操作没有实现幂等的情况下是很危险的,所以设置为false
ConnectTimeout: 10000 #请求连接的超时时间
ReadTimeout: 10000 #请求处理的超时时间
### Hystrix 配置
##注意:建议 Ribbon 的超时时间不要大于 Hystrix 的超时时间
hystrix:
# 这样将会自动配置一个 Hystrix 并发策略插件的 hook,这个 hook 会将 SecurityContext 从主线程传输到 Hystrix 的命令。
# 因为 Hystrix 不允许注册多个 Hystrix 策略,所以可以声明 HystrixConcurrencyStrategy
# 为一个 Spring bean 来实现扩展。Spring Cloud 会在 Spring 的上下文中查找你的实现,并将其包装在自己的插件中。
shareSecurityContext: true
command:
default:
circuitBreaker:
# 当在配置时间窗口内达到此数量的失败后,进行短路。默认20个
requestVolumeThreshold: 1
# 触发短路的时间值,当该值设为5000时,则当触发 circuit break 后的5000毫秒内都会拒绝request
# 也就是5000毫秒后才会关闭circuit。默认5000
sleepWindowInMilliseconds: 15000
# 强制打开熔断器,如果打开这个开关,那么拒绝所有request,默认false
forceOpen: false
# 强制关闭熔断器 如果这个开关打开,circuit将一直关闭且忽略,默认false
forceClosed: false
execution:
isolation:
thread:
# 熔断器超时时间,默认:1000/毫秒
timeoutInMilliseconds: 50000
#要使用hystrix的超时fallback,必须设置:
timeout:
enabled: true
###设置feign客户端超时时间
feign:
client:
config:
default:
#建立连接所用的时间,适用于网络状况正常的情况下,两端连接所需要的时间
ConnectTimeOut: 5000
#指建立连接后从服务端读取到可用资源所用的时间
ReadTimeOut: 10000
四、网页输入:http://127.0.0.1:28580/user/user/userInfo?name=张三
五、番外篇,服务过滤
zuul不仅只是路由,并且还能过滤,做一些安全验证。
@Log4j2
@Component
public class PreSendForwardFilter extends ZuulFilter {
@Override
public String filterType() {
// 在路由之前进行过滤
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.FORM_BODY_WRAPPER_FILTER_ORDER - 1;
}
/**
* 核心过滤器
*
* @return boolean
*/
@Override
public boolean shouldFilter() {
// 获取请求上下文
RequestContext context = RequestContext.getCurrentContext();
// 获取到request
HttpServletRequest request = context.getRequest();
String user = request.getParameter("user");
String uri = request.getRequestURI();
// 若请求中包含/abc8080路径,且没有user请求参数,则无法通过过滤
// if(uri.contains("/abc8080") && StringUtils.isEmpty(user)) {
// log.warn("user用户为空");
// // 指定当前请求未通过zuul过滤,默认值为true
// context.setSendZuulResponse(false);
// context.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
// return false;
// }
return true;
}
/**
* 过滤通过后要执行的方法
*
* @return Object
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
String host = request.getRemoteHost();
String method = request.getMethod();
String uri = request.getRequestURI();
log.info("请求URI:{},HTTP Method:{},请求IP:{}", uri, method, host);
return null;
}
}