Zuul是Netlix开源的微服务网关,它可以和Eureka、Ribbon、 Hystrix 等组件配合使用。
Zuul的核心是一系列的过滤器,这些过滤器可以完成以下功能。
- 身份认证与安全:识别每个资源的验证要求,并拒绝那些与要求不符的请求。
- 审查与监控:在边缘位置追踪有意义的数据和统计结果,从而带来精确的生产视图。
- 动态路由:动态地将请求路由到不同的后端集群。
- 压力测试:逐渐增加指向集群的流量,以了解性能。
- 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求。
- 静态响应处理:在边缘位置直接建立部分响应,从而避免其转发到内部集群。
- 多区域弹性:跨越AWS Region进行请求路由,旨在实现ELB ( Elastic Load Balancing)使用的多样化,以及让系统的边缘更贴近系统的使用者。
Spring Cloud对Zuul进行了整合与增强。目前,Zuul使用的默认HTTP客户端是Apache HTTP Client,也可以使用RestClient或者okhttp3.0kHttpClient。
如果想要使用RestClient,可以设置ribbon.restclient.enabled=true;想要使用okhttp3.0kHttpClient,可以设置ribbon.okhttp.enabled=true。
路由:
分发给不同的微服务(通过服务名)
负载均衡:
分发同一个微服务的不同实例,减少单个压力
zuul4种配置方式
配置方式1:快速入门 (只是做了路径分发 通过路径可路由)
1--新建项目,引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
2--覆盖默认配置
server: # 设置应用端口
port: 10010
spring: # 设置应用即微服务名称
application:
name: xiaoai_zuul
3--引导类启用zuul组件
package com.xiaoai.zuul;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableZuulProxy //启用zuul组件
public class XiaoaiZuulApplication {
public static void main(String[] args) {
SpringApplication.run(XiaoaiZuulApplication.class, args);
}
}
4--配置路由
zuul:
routes:
service-provider: # 路由名称,可以随便写,习惯上用服务的名称,即之前自己定义的某个服务的名称。
path: /service-provider/**
url: http://localhost:8081
--通过zuul访问配置好的服务,可以正常访问
--如未配置消费端路由,zuul访问其url
--配置消费服务端路由后,zuul访问其url
server:
port: 10010
spring:
application:
name: xiaoai_zuul
zuul:
routes:
service-provider:** # 路由名称,可以随便写,习惯上用服务的名称,即之前自己定义的某个服务的名称。
path: /service-provider/**
url: http://localhost:8081
service-consumer: # 配置消费端路由
path: /service-consumer/**
url: http://localhost:80
eureka:
client:
serviceUrl:
defaultZone: http://localhost:10086/eureka
配置方式2:zuul注册到eureka容器 (通过服务id可路由)
1--引入eureka启动器
<!--引入eureka-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2--把zuul注入eureka容器中,application配置文件配置
spring:
application:
name: xiaoai_zuul
eureka:
client:
service-url:
defaultZone: http/localhost:10086/eureka
3--引导类启用eureka
package com.xiaoai.zuul;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableZuulProxy //启用zuul组件
@EnableDiscoveryClient //启用eureka客户端
public class XiaoaiZuulApplication {
public static void main(String[] args) {
SpringApplication.run(XiaoaiZuulApplication.class, args);
}
}
4--配置文件可以修改路由,直接配置服务id即可
server:
port: 10010
spring:
application:
name: xiaoai_zuul
zuul:
routes:
service-provider: # 路由名称,可以随便写,习惯上用服务的名称,即之前自己定义的某个服务的名称。
path: /service-provider/**
# url: http://localhost:8081 # 写死端口无法负载均衡
serviceId: service-provider # 把zuul注入到了eureka后,其可以拉取客户端服务,所以可以直接写服务id,即自己定义的名称,通过服务id,zuul也可以实现负载均衡
eureka:
client:
service-url:
defaultZone: http//localhost:10086/eureka
--zuul访问提供服务端url可以正常访问
配置方式3:路径直接配置在服务id后
--application配置文件配置
server:
port: 10010
spring:
application:
name: xiaoai_zuul
zuul:
routes:
service-provider: /service-provider/** # 路由名称,可以随便写,习惯上用服务的名称,即之前自己定义的某个服务的名称。
# path: /service-provider/**
# url: http://localhost:8081
# serviceId: service-provider # 把zuul注入到了eureka后,其可以拉取客户端服务,所以可以直接写服务id,即自己定义的名称,通过服务idzuul也可以实现负载均衡
eureka:
client:
serviceUrl:
defaultZone: http://localhost:10086/eureka
--访问
配置方式4: 加入eureka容器后 不配置任何路由 默认访问就是服务名加路径
--配置如下
server:
port: 10010
spring:
application:
name: xiaoai_zuul
eureka:
client:
serviceUrl:
defaultZone: http://localhost:10086/eureka
--访问
默认使用第三种配置方式,使用第三种可以修改路径 简化路径前缀 如配置:
server:
port: 10010
spring:
application:
name: xiaoai_zuul
zuul:
routes:
service-provider: /user/** # 路由名称,可以随便写,习惯上用服务的名称,即之前自己定义的某个服务的名称。 路径可以使用服务id也可以修改自定义,这里改为user
service-consumer: /consumer/**
eureka:
client:
serviceUrl:
defaultZone: http://localhost:10086/eureka
--访问
在某个微服务中控制器减少一层路径 如提供端服务service-provider的控制类
package com.xiaoai.service.controller;
import com.xiaoai.service.pojo.User;
import com.xiaoai.service.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("{id}")
public User queryUserById(@PathVariable("id")Long id) {
return this.userService.queryUserById(id);
}
}
zuul的application配置文件
server:
port: 10010
spring:
application:
name: xiaoai_zuul
zuul:
routes:
service-provider: /user/** # 路由名称,可以随便写,习惯上用服务的名称,即之前自己定义的某个服务的名称。
service-consumer: /consumer/**
eureka:
client:
serviceUrl:
defaultZone: http://localhost:10086/eureka
--访问
网关前缀
由于项目发布以后无法知道访问路径是否经过网关,可以在application配置文件中配置加入前缀来区分访问是否经过网关。如:
server:
port: 10010
spring:
application:
name: xiaoai_zuul
zuul:
routes:
service-provider: /user/** # 路由名称,可以随便写,习惯上用服务的名称,即之前自己定义的某个服务的名称。
service-consumer: /consumer/**
prefix: /api # 前缀用于区分访问是否经过网关,这里为api,可以自定义,默认一般使用api
eureka:
client:
serviceUrl:
defaultZone: http://localhost:10086/eureka
--访问
小结
- 引入zuul的启动器
- 配置:
- zuul.routes.<路由名称>.path=/service-provider/** zuul.routes.<路由名称>.url=http://localhosta:8081
- zuul.routes.<路由名称>.path=/service-provider/** zuul.routes.<路由名称>.serviceId=service-provider
- zuul.routes.服务名称=/service-provider/**
- 不用配置,默认就是服务id+路径
- 引导类注解@EnableZuulProxy 开启zuul
- 引导类@EnableDiscoveryClient 开启eureka客户端
zuul过滤器
Zuul作为网关的其中一个重要功能, 就是实现请求的鉴权。而这个动作我们往往是通过Zuul提供的过滤器来实现
Zuul过滤器需实现接口:IZuulFilter
- 方法shouldFilter() 返回值true执行run方法,false不执行
- 方法run() 过滤器业务逻辑的方法,是否拦截在该方法判断
默认有一些实现了IZuulFilter接口的类
1--定义一个过滤器
package com.xiaoai.zuul.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component
public class LoginFilter extends ZuulFilter{
/**
* 过滤器类型选择:pro route post error
* @return
*/
@Override
public String filterType() {
return "pre";
}
/**
* 执行的顺序,返回值越小,优先级越高
* @return
*/
@Override
public int filterOrder() {
return 10;
}
/**
* 是否执行该过滤器 即run方法
* true==执行
* false==不执行
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 编写过滤器的业务逻辑
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
//初始化context上下文对象,
RequestContext context = RequestContext.getCurrentContext();
//获取request对象
HttpServletRequest request = context.getRequest();
//获取参数
String token = (String) request.getParameter("token");
if (StringUtils.isBlank(token)){
//拦截 ,这里表示不转发请求
context.setSendZuulResponse(false);
//响应状态码,401-身份未认证
context.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
//设置响应的提示
context.setResponseBody("request error!");
}
//返回值为null,表示该过滤器什么都不做
return null;
}
}
2--访问
springCloud初识小结
- eureka
- 注册中心
- 微服务容器
- ribbon
- 负载均衡组件
- eureka集成 feign集成 zuul集成
- @LoadBalanced 开启负载均衡
- this.restTemplate.getForObject("http://service-provider/user/"+id,User.class) 实现负载均衡
- hystrix
- 容错组件
- 降级:检查每次请求,是否请求超时,或连接池已满
- 引入hystrix启动器
- 熔断时间,默认1s,
- 在引导类上添加了一个注解: @EnableCircuitBreaker @SpringCloudApplication
- 定义熔断方法:局部(要和被熔断的方法返回值和参数列表一致)全局 (返回值类型要被熔断的方法一致, 参数列表必须为空)
- @HystrixCommand (fallbackMethod="局部熔断方法名"):声明被熔断的方法
- @DefaultProperties (defaultFallback="全局熔断方法名")
- 熔断:不再发送请求
- close:闭合状态,所有请求正常方法
- open:打开状态,所有请求都无法访问。如果在- -定时间内容,失败的比例不小于508或者次数不少于20次
- half open: 半开状态,打开状态默认5s休眠期,在休眠期所有请求无法正常访问。过了休眠期会进入半开状态,放部分请求通过
- feign
- 引入openFeign启动器
- feign.hystrix.enable=true,开启feign的熔断功能
- 在引导类上@EnableFeignClients启用feign
- 创建一一个接口,在接口添加eFeignClient (value="微服务id", fallback=实现类.class)
- 在接口中定义一些方法,这些方法的书写方式跟之前controller类似
- 创建了一个熔断类,实现feign接口,实现对应的方法,这些实现方法就是熔断方法
- zuul
- 网关,路由分发
- 引入zuul的启动器
- 配置:4种方式
- zuul.routes.<路由名称>.path=/service-provider/** zuul.routes.<路由名称>.url=http://localhosta:8081
- zuul.routes.<路由名称>.path=/service-provider/** zuul.routes.<路由名称>.serviceId=service-provider
- zuul.routes.服务名称=/service-provider/**
- 不用配置,默认就是服务id+路径
- 引导类注解@EnableZuulProxy 开启zuul
- 引导类@EnableDiscoveryClient 开启eureka客户端
- 过滤器:
- 创建一个类继承ZuulFilter基类
- 重写四个方法
- filterType: pro route post error
- filterOrder:返回值越小优先值越高
- shouldFilter:返回值判断是否执行run方法。true=执行 false=不执行
- run:具体的拦截逻辑