【笔记】Zuul学习笔记

前言

Zuul API 网关,为微服务应用提供统一的对外访问接口。
Zuul 还提供过滤器,对所有微服务提供统一的请求校验。

引入依赖

  • 编辑pom.xml配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</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-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

配置

  • 编辑application.yml配置文件,配置路由转发规则
  • 以下配置为默认配置,可以不写,根据注册中心自动配置,但是有可能配置不全,所以最好手动配置
1
2
3
4
zuul:
routes:
item-service: /item-service/**
user-service: /user-service/**

启动类

  • 启动类添加@EnableZuulProxy注解启动Zuul
1
2
3
4
5
6
7
@EnableZuulProxy
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

统一权限校验

  • 通过Zuul过滤器,可以判断用户是否有权限访问后台服务,如果没有权限可以阻止用户继续访问

添加过滤器

  • 继承ZuulFilter类,添加@Component注解,Zuul会对过滤器自动配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@Component
public class AccessFilter extends ZuulFilter {

// 设置过滤器类型:pre,routing,post,error
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}

// 设置过滤器的顺序号,前置过滤器默认有5个过滤器
@Override
public int filterOrder() {
return 6;
}

// 对客户端的当前请求进行判断,针对当前请求,是否要执行过滤代码
@Override
public boolean shouldFilter() {

// 获取调用的服务id
RequestContext context = RequestContext.getCurrentContext();
String serviceId = (String) context.get(FilterConstants.SERVICE_ID_KEY);
// 判断是不是 item-service (忽略大小写)
return "item-service".equalsIgnoreCase(serviceId);
}

// 过滤代码
@Override
public Object run() throws ZuulException {

// 获取request对象
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();

// 接收token参数
String token = request.getParameter("token");
// 如果token为空
if (StringUtils.isBlank(token)) {
// 阻止访问,不再向后台服务转发
context.setSendZuulResponse(false);

// 设置向客户端的响应
context.addZuulResponseHeader("Content-Type", "application/json");
context.setResponseBody(JsonResult.err().msg("not login").toString());
}

// 在当前Zuul版本中,这个返回值没有任何作用
return null;
}
}

Zuul集成Ribbon

  • 默认启用Ribbon的负载均衡
  • 默认不启用重试,Zuul不推荐启用重试

启用重试

添加依赖

  • 编辑pom.xml配置文件
1
2
3
4
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>

配置

  • 编辑application.yml配置文件,启用Ribbon重试
1
2
zuul:
retryable: true
  • 可以配置重试参数,有默认参数,可以根据需要进行调整

Zuul集成Hystrix

  • 0配置,已经启用了Hystrix

添加降级代码

  • 实现FallbackProvider接口,在子类中实现降级代码
  • Zuul的自动配置,会自动配置降级类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@Component
public class ItemFB implements FallbackProvider {

// 针对哪个服务进行降级,返回服务的id,如果返回`*`或者`null`,表示针对所有服务都进行降级
@Override
public String getRoute() {
return "item-service";
}

// 设置向客户端返回的降级响应
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK;
}

@Override
public int getRawStatusCode() throws IOException {
return HttpStatus.OK.value();
}

@Override
public String getStatusText() throws IOException {
return HttpStatus.OK.getReasonPhrase();
}

@Override
public void close() {

}

// 响应体
@Override
public InputStream getBody() throws IOException {
String json = JsonResult.ok().msg("失败").toString();
return new ByteArrayInputStream(json.getBytes("UTF-8"));
}

// 响应头
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json;charset=UTF-8");
return headers;
}
};
}
}

完成