1、SpringCloud全家桶—注册中心Eureka搭建
2、SpringCloud全家桶—注册中心Eureka高可用环境搭建
3、SpringCloud全家桶—客户端负载均衡Ribbon
4、SpringCloud全家桶—OpenFeign
5、SpringCloud全家桶—断路器Hystrix
6、SpringCloud全家桶—HystrixDashboard配置与基础功能演示
7、SpringCloud全家桶—Zuul网关
1、什么是Zuul?
Zuul是一种基于7层的应用程序网关,它提供了动态路由、监控、服务容错、安全等方面的保障,是微服务中的统一入口,由这个入口来管理所有请求调用的路径。
2、为什么要使用Zuul
项目服务中各种各样的请求随时可能导致生产环境故障而没有预警,因此我们需要一个允许我们快速改变行为以对这些情况做出反应的系统。
Zuul使用了各种不同类型的过滤器,这使我们能够快速,灵活地将功能应用于边缘服务。这些过滤器帮助我们执行以下功能:
-
身份验证和安全性-识别每种资源的身份验证要求,并拒绝不满足要求的请求。
-
洞察和监控-在边缘跟踪有意义的数据和统计信息,以便为我们提供准确的生产视图。
-
动态路由-根据需要将请求动态路由到不同的后端群集。
-
压力测试-逐渐增加到群集的流量以评估性能。
-
减载-为每种类型的请求分配容量,并丢弃超出限制的请求。
-
静态响应处理-直接在边缘构建一些响应,而不是将其转发到内部集群
3、快速开始
3.1、基本配置
依赖jar包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
启动类,@EnableZuulProxy包含了eureka客户端注册
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
配置文件,注册到注册中心,即可完成最简单的网关搭建。
server:
port: 9000
spring:
application:
name: myZuul
eureka:
client:
service-url:
defaultZone: http://eurekaServer1.com:18001/eureka/
instance:
instance-id: ${spring.cloud.client.ip-address}:${server.port}
prefer-ip-address: true
启动两个order微服务,一个接口返回getOrderInfo ok 1,一个接口返回getOrderInfo ok 2,通过zuul访问实现负载均衡。
order:19201
@GetMapping("/getOrderInfo")
public String getOrderInfo() {
return "getOrderInfo ok 1";
}
order:19202
@GetMapping("/getOrderInfo")
public String getOrderInfo() {
return "getOrderInfo ok 2";
}
查看注册中心服务列表,注册成功。
通过网关访问服务,因为没有任何网关配置,所以默认访问路径为:服务名+接口路径。
实现负载均衡。
3.2、自定义微服务访问路径
zuul:
routes:
# 自定义名称
order-service:
path: /order-service/**
service-id: order
3.3、添加访问前缀
zuul:
routes:
# 自定义名称
order-service:
path: /order-service/**
service-id: order
# 访问前缀
prefix: /api
# 转到后台服务时移除前缀
strip-prefix: true
如果配置为false,url地址会拼接上api。
3.4、敏感Header
order服务新增一个接口,获取token。
@RequestMapping("/token")
public String getToken(HttpServletRequest req){
String token = req.getHeader("token");
return "token:"+token;
}
通过网关访问获得token
禁止传播token配置
zuul:
routes:
# 自定义名称
order-service:
path: /order-service/**
service-id: order
prefix: /api
strip-prefix: true
# 不向微服务传播header中的token
sensitive-headers: token
order服务获取不到token了。
3.5、过滤器
Zuul的大部分功能都是通过过滤器实现。
Zuul中一共包含了4种过滤器,分别如下:
- Pre filters: 在请求被路由之前调用,可利用这种过滤器实现身份验证。选择微服务,记录日志。
- Route filters:在将请求路由到微服务调用,用于构建发送给微服务的请求,并用http clinet(或者ribbon)请求微服务。
- Post filters:在调用微服务执行后,将微服务的响应写入当前响应,可用于添加header,记录日志,将响应发给客户端。
- Error filters:在其他阶段发生错误是,走此过滤器。
只演示一个前置拦截器,其他拦截器使用方式一样,通过一个FilterConstants.PRE_TYPE区分。
@Component
public class PreFilter extends ZuulFilter {
/**
* 过滤器是否生效
*/
@Override
public boolean shouldFilter() {
//获取上下文
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
String uri = request.getRequestURI();
System.out.println("PreFilter uri:" + uri);
//只有此接口/api/order-service/userOrder/token才被拦截
String checkUri = "/api/order-service/userOrder/token";
if (checkUri.equalsIgnoreCase(uri)) {
return true;
}
return false;
}
/**
* 过滤器生效后执行逻辑
* @return
*/
@Override
public Object run() {
System.out.println("执行PreFilter拦截处理!");
//获取上下文
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
String token = request.getHeader("token");
System.out.println("PreFilter 获取token:" + token);
if (StringUtils.isEmpty(token)) {
requestContext.setSendZuulResponse(false);// 过滤该请求,不对其进行路由
requestContext.setResponseStatusCode(401);// 返回错误码
requestContext.setResponseBody("token is empty");// 返回错误内容
} else {
requestContext.setSendZuulResponse(true);// 对该请求进行路由
requestContext.setResponseStatusCode(200);
}
return null;
}
@Override
public String filterType() {
//前置过滤器
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
//优先级,数字越大,优先级越低
return 0;
}
}
调用普通接口,不走拦截器处理逻辑。
调用需要被拦截的接口:/api/order-service/userOrder/token
token为空时,请求不通过。
加入token后,请求通过。