一、Zuul的路由功能
使用Spring初始化工具建立工程:
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.liaoxiang.zuul</groupId>
<artifactId>user-zuul</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>user-zuul</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</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>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
啟動類
@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
public class UserZuulApplication {
public static void main(String[] args) {
SpringApplication.run(UserZuulApplication.class, args);
}
}
路由的幾種配置
zuul:
routes:
user-service: #路由id,任意取
path: /user-service/** #映射路徑
serviceId: user-service #指定服務id
zuul:
routes:
user-service: /user-service/** #服務id: 路由路徑
預設的路由規則就是
服務名:服務名/**
,是以以上配置可以省略,當路徑不想使用服務名稱的時候就可以添加配置來改變預設的額規則:比如
zuul:
routes:
user-service: /user/** #服務id: 路由路徑
配置路由字首:localhost:10010/api/user/**
zuul:
prefix: /api #加字首
retryable: true
Zuul中也內建了Ribbon和Hystrix,整個配置如下
server:
port: 10010
spring:
application:
name: api-gateway
zuul:
routes:
user-service: /user-service/**
user-consumer: /user-consumer/**
prefix: /api #加字首
retryable: true
eureka:
client:
registry-fetch-interval-seconds: 5
service-url:
defaultZone: http://localhost:10086/eureka
ribbon:
ConnectTimeout: 250 # 連接配接逾時時間(ms)
ReadTimeout: 2000 # 通信逾時時間(ms)
OkToRetryOnAllOperations: true # 是否對所有操作重試
MaxAutoRetriesNextServer: 2 # 同一服務不同執行個體的重試次數
MaxAutoRetries: 1 # 同一執行個體的重試次數
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMillisecond: 6000 # 熔斷逾時時長:6000ms
浏覽器通路:http://localhost:10010/api/user-consumer/user/findUsers?ids=1,2,3,4
二、Zuul過濾器
使用場景:請求鑒權、異常處理、服務調用時長統計等
ZuulFilter是過濾器的頂級父類,其中定義的4個最重要的方法
public abstract ZuulFilter implements IZuulFilter{
abstract public String filterType();
abstract public int filterOrder();
boolean shouldFilter();// 來自IZuulFilter
Object run() throws ZuulException;// IZuulFilter
}
shouldFilter
:傳回一個
Boolean
值,判斷該過濾器是否需要執行。傳回true執行,傳回false不執行。
run
:過濾器的具體業務邏輯。
filterType
:傳回字元串,代表過濾器的類型。包含以下4種:
pre
:請求在被路由之前執行
route
:在路由請求時調用
post
:在route和errror過濾器之後調用
error
:處理請求時發生錯誤調用
filterOrder
:通過傳回的int值來定義過濾器的執行順序,數字越小優先級越高。
自定義過濾器,模拟鑒權
@Component
public class LoginFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 2;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
// 擷取請求參數中的token
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
//當微服務需要頭資訊時,要轉發頭資訊
String header = request.getHeader("Authorization");
if(header !=null && !"".equals(header)){
contxt.addZuulRequestHeader("Authorization", header);
}
// 擷取參數
String token = request.getParameter("token");
if (StringUtils.isEmpty(token)){
// 未登入
context.setResponseStatusCode(401);
// 不再繼續路由
context.setSendZuulResponse(false);
}
return null;
}
}
測試,不帶token參數
測試,帶上token參數