SpringCloud學習筆記(6):使用Zuul構建服務閘道器
簡介
Zuul是Netflix提供的一個開源的API閘道器伺服器,SpringCloud對Zuul進行了整合和增強。服務閘道器Zuul聚合了所有微服務介面,並統一對外暴露,外部客戶端只需與服務閘道器互動即可。相對於內部服務而言,能夠防止其被外部客戶端直接訪問而暴露服務的敏感資訊,起到了保護作用。除此之外,Zuul還可以實現身份認證、資料監控、動態路由等功能。
專案介紹
- sc-parent,父模組(請參照SpringCloud學習筆記(1):Eureka註冊中心)
- sc-eureka,註冊中心(請參照SpringCloud學習筆記(1):Eureka註冊中心)
- sc-provider,提供者(請參照SpringCloud學習筆記(1):Eureka註冊中心)
- sc-gateway,服務閘道器
使用Zuul構建服務閘道器
1.在父模組下建立子模組專案sc-gateway,pom.xml:
<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>com.cf</groupId> <artifactId>sc-parent</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>sc-gateway</artifactId> <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> </dependencies> </project>
2.建立啟動類gateway.GatewayApplication:
package gateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @SpringBootApplication @EnableZuulProxy public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } }
@EnableZuulProxyh和@EnableZuulServer:
@EnableZuulProxy是@EnableZuulServer的超集,@EnableZuulProxy包含@EnableZuulServer匯入的所有過濾器。
@EnableZuulProxy使用反向代理,@EnableZuulServer不使用任何代理。
3.建立application.yml:
server:
port: 8088
spring:
application:
name: sc-gateway
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8080/eureka/
zuul:
routes:
sc-provider: /sp/** #將serviceId為sc-provider的服務對映到/sp/**路徑
4.測試
依次啟動註冊中心sc-eureka、提供者sc-provider、閘道器sc-gateway,以下是通過Zuul訪問提供者和直接訪問提供者的結果:
其他常用配置
1.忽略指定服務
zuul:
ignored-services: serviceId1,serviceId2 #忽略服務serviceId1,serviceId2
2.忽略所有服務,只代理指定的服務
zuul:
ignored-services: '*' #*為忽略所有服務,只代理sc-provider服務
routes:
sc-provider: /sp/**
3.指定訪問路徑字首,設定之後只能通過帶字首訪問
zuul:
prefix: /yc
routes:
sc-provider: /sp/**
4.指定服務的url
zuul:
routes:
sc-provider:
path: /sp/**
url: http://localhost:8081 #指定服務sc-provider的url,不從Eureka註冊中心獲取。
這種配置方式不會作為HystrixCommand執行,也不會使用Ribbon來平衡多個url的負載。要實現這些目標,可以使用靜態伺服器列表(listOfServers)或者指定serviceId。
5.指定敏感Header,防止敏感Header外洩
zuul:
routes:
sc-provider:
path: /sp/**
sensitiveHeaders: Cookie,Set-Cookie,Authorization #將會覆蓋全域性zuul.sensitiveHeaders的值
url: http://localhost:8081
如果要設定全域性的敏感Header可以設定zuul.sensitiveHeaders的值。Cookie,Set-Cookie,Authorization為sensitiveHeaders的預設值,如果不想設定敏感header,可以把sensitiveHeaders設定成空列表:
zuul:
routes:
sc-provider:
path: /sp/**
sensitiveHeaders:
url: http://localhost:8081
6.忽略Header
zuul:
ignoredHeaders: Header1, Header2 #Header1和Header2將不會傳播到其他的微服務中
Zuul的路由端點
當@EnableZuulProxy和Spring Boot Actuator配合使用時,Zuul會暴露一個路由管理端點/routes,通過這個路由端點可以檢視到Zuul當前對映的路由列表資訊。
1.修改sc-gateway的pom.xml,新增Spring Boot Actuator依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2.修改sc-gateway的application.yml,開啟/routes端點的訪問:
management:
endpoints:
web:
exposure:
include: 'routes'
3.訪問/routes端點
依次啟動註冊中心sc-eureka、提供者sc-provider、閘道器sc-gateway,然後訪問http://localhost:8088/actuator/routes/details,顯示路由列表資訊如下:
Zuul過濾器
Zuul的核心是一系列過濾器,它們能夠在HTTP請求和響應路由期間執行一系列操作。Zuul提供了一個框架來動態讀取、編譯和執行這些過濾器,過濾器之間不直接通訊,它們通過對每個請求惟一的RequestContext共享資料。
1.Zuul過濾器型別
- PRE Filters:在請求路由到具體的服務之前執行。
- ROUTING Filters:用於將請求路由到微服務。
- POST Filters:在請求路由到微服務之後執行。
- ERROR Filters:在其他階段發生錯誤時執行。
2.Zuul過濾器特性
- Type:Zuul過濾器的型別,決定過濾器在請求的哪個階段起作用。
- Execution Order:規定過濾器的執行順序,值越小,越先執行。
- Criteria:Filter執行所需的條件。
- Action:如果滿足條件,則執行的操作。
3.Zuul請求生命週期圖
4.自定義Zuul過濾器
新建類gateway.filter.MyZuulFilter:
package gateway.filter;
import javax.servlet.http.HttpServletRequest;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
public class MyZuulFilter extends ZuulFilter{
/**
* 具體執行邏輯
*/
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
if (request.getParameter("name") != null) {
System.out.println("你好," + request.getParameter("name"));
}
return null;
}
/**
* 判斷你該過濾器是否要執行
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 過濾器執行順序
*/
@Override
public int filterOrder() {
return 1;
}
/**
* 過濾器型別
*/
@Override
public String filterType() {
return "pre";
}
}
啟動類GatewayApplication中新增配置:
@Bean
public MyZuulFilter MyZuulFilter(){
return new MyZuulFilter();
}
依次啟動註冊中心sc-eureka、提供者sc-provider、閘道器sc-gateway,然後訪問http://localhost:8088/sp/book/list?name=小明,MyZuulFilter過濾器將會執行,控制檯輸出:你好,小明