SpringCloud系列之Zuul網(wǎng)關(guān)和Zuul過濾器
Zuul網(wǎng)關(guān)
什么是Zuul網(wǎng)關(guān)?
Zuul是SpringCloud全家桶的微服務(wù)網(wǎng)關(guān)。所有從app或者網(wǎng)站(第三方)來的請求都會經(jīng)過Zuul到達后端的Netflix應(yīng)用程序。作為一個邊界性質(zhì)的應(yīng)用程序,Zuul提供了動態(tài)路由、監(jiān)控、彈性負載和安全功能。
Zuul底層利用filter實現(xiàn)如下功能:
- 認證和安全,識別每個需要認證的資源,拒絕不服務(wù)要求的請求。
- 性能檢測,在服務(wù)邊界追蹤并統(tǒng)計數(shù)據(jù),提供精確的生產(chǎn)視圖。
- 動態(tài)路由,根據(jù)需要將請求動態(tài)路由到后端集群。
- 壓力測試,逐漸增加對集群的流量以及了解其性能。
- 負載卸載,預(yù)先為每種類型的請求分配容量,當請求超過流量時自動丟棄。靜態(tài)資源處理,直接在邊界返回某種響應(yīng)。
- 靜態(tài)資源處理,直接在Zuul處理靜態(tài)資源并響應(yīng),而并非轉(zhuǎn)發(fā)這些請求到內(nèi)部集群中。
- 多區(qū)域彈性,跨越AWS區(qū)域進行請求路由,旨在實現(xiàn)ELB使用多樣化并保證邊緣位置與使用者盡可能接近。
Zuul網(wǎng)關(guān)Demo
引入jar包:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
配置文件:application.yml。
server:
port: 7004 # 端口
spring:
application:
name: zuul-getway # 服務(wù)名
eureka:
client:
service-url:
defaultZone: http://jack:666@localhost:8764/eureka/ # 需要注冊到eureka
instance:
instance-id: ${spring.application.name}:${server.port}
zuul:
routes:
order-service: /od/** # 對某個服務(wù)自定義路由規(guī)則
serviceId: order-service # 這個配置可以實現(xiàn)負載均衡,默認是輪詢
# 設(shè)置某些服務(wù)不要進行反向代理 進行路由,多個服務(wù)用逗號隔開
ignored-services: order-service, user-service
prefix: /api # 請求路徑的前綴
查看是否注冊到eureka。
Eureka注冊中心
訪問路徑:
localhost:7004/api/od/getOrder?token=1235。
(后面帶token是因為我配置了pre過濾器,下面會介紹)。
Zuul過濾器
Zuul四種過濾器類型,這些類型對應(yīng)請求的生命周期
- pre(前置):在請求被路由之前調(diào)用。可利用這種過濾器來實現(xiàn)身份認證、在集群中選擇請求的微服務(wù),記錄調(diào)試等。
- routing(路由):將請求路由到微服務(wù)。用于構(gòu)建發(fā)送給微服務(wù)的請求,并使用apache httpclient或netflix ribbon請求微服務(wù)。
- post(后置):在路由到微服務(wù)后執(zhí)行??捎糜陧憫?yīng)添加標準的http header、收集統(tǒng)計信息和指標、將響應(yīng)從微服務(wù)發(fā)送到客戶端。
- error(錯誤):在其他階段發(fā)送錯誤時執(zhí)行該過濾器。
注:除了默認的過濾器類型以外Zuul還允許創(chuàng)建自定義的過濾器類型。
如何禁用過濾器?
很簡單,只需設(shè)置zuul.ClassName.filterType.disable=true ,即可禁用SimpleClassName所對應(yīng)的過濾器。例如:zuul.TokenFilter.pre.disable=true; 即可禁用TokenFilter過濾器。
pre過濾器
例子: 鑒權(quán)認證。如果參數(shù)帶了token就允許訪問。
/**
* pre過濾器
* @Author Big.Hu
*/
@Component
public class TokenFilter extends ZuulFilter {
@Override
public Object run() {
System.err.println("執(zhí)行pre前置過濾器。。。。。。。。。");
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
StringBuffer requestURL = request.getRequestURL();
System.out.println("requestURL:" + requestURL);
// 獲取請求的參數(shù)
String token = request.getParameter("token");
if (StringUtils.isEmpty(token)) {
// 如果參數(shù)為空則過濾該請求,不對其進行路由
currentContext.setSendZuulResponse(false);
// 設(shè)置錯誤碼:401
currentContext.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
currentContext.set("SUCCESS", false);
} else {
// 不過濾該請求,對其進行路由
currentContext.setSendZuulResponse(true);
// 設(shè)置成功碼:200
currentContext.setResponseStatusCode(HttpStatus.SC_OK);
currentContext.set("SUCCESS", true);
}
System.out.println("token:" + token);
return null;
}
/**
* 當前filter類型:pre、post、route、error
*/
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
/**
* 表示當前filter優(yōu)先級
*/
@Override
public int filterOrder() {
return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
}
/**
* 是否執(zhí)行該過濾器?
**/
@Override
public boolean shouldFilter() {
return true;
}
}
POST過濾器
例: 在返回的時候設(shè)置一個cookie。
/**
* Post過濾器
* @Author Big.Hu
*/
@Component
public class PostFilter extends ZuulFilter {
/**
* POST過濾器:在route和error過濾器之后執(zhí)行
*/
@Override
public String filterType() {
return FilterConstants.POST_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
System.err.println("執(zhí)行Post過濾器。。。。。。。。。");
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletResponse response = currentContext.getResponse();
Cookie cookie = new Cookie("name", "Jack.Hu");
cookie.setMaxAge(60 * 60 * 24);
response.addCookie(cookie);
return null;
}
}
訪問路徑:
localhost:7004/api/od/getOrder。
(沒帶token參數(shù))請求被pre過濾器過濾掉了。
不帶token請求
帶上token參數(shù)請求成功!
帶token請求
再按f12看post過濾器設(shè)置的cookie。
查看cookie
控制臺:
控制臺