Zuul 屬于Netflix旗下一款產(chǎn)品,而Spring很好對(duì)其做了整合
Zuul是一個(gè)邊緣服務(wù)近弟,提供動(dòng)態(tài)路由缅糟、監(jiān)控、彈性祷愉、安全性等等窗宦。相關(guān)的用法赦颇、信息、操作方式等 請(qǐng)查看WIKI https://github.com/Netflix/zuul/wiki
Spring Cloud Netflix的文檔:
https://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/2.1.0.M3/single/spring-cloud-netflix.html
一赴涵、Getting Start最簡(jiǎn)單的配置
java文件
@EnableZuulProxy
public class ZuulConfig {
}
yml文件
zuul:
routes:
pltf-client:
path: /pltf/client/**
service-id: pltf-client
二媒怯、對(duì)于yml的改進(jìn)
1、最傳統(tǒng)的路由
zuul.routes.client.path=/client/**
zuul.routes.client.url=http://localhost:1166/
2髓窜、面向服務(wù)的路由
如果每次都要寫(xiě)一串url的話感覺(jué)很繁瑣扇苞,所以用service-id來(lái)代替,這里的service-id就是注冊(cè)服務(wù)當(dāng)中的 service-id
zuul.routes.client.path=/client/**
zuul.routes.client.service-id=client
3寄纵、通配符路由
有這樣一個(gè)場(chǎng)景鳖敷,由于業(yè)務(wù)的擴(kuò)展,版本的升級(jí)程拭,服務(wù)存在不同的版本定踱。比如我們有這樣的命名:client-v1、client-v2恃鞋,默認(rèn)情況下崖媚,Zuul自動(dòng)為服務(wù)創(chuàng)建的路由表達(dá)式會(huì)采用服務(wù)名做前綴,針對(duì)client就會(huì)產(chǎn)生/client-v1,/client-v2兩個(gè)路徑來(lái)做映射恤浪,但這樣生成的表達(dá)式規(guī)則較為單一畅哑,不利于路徑規(guī)則的管理。通常,對(duì)于上面這種情況水由,我們希望是生成的路徑為/v1/client荠呐,/v2/client。我們可以通過(guò)自定義路由規(guī)則來(lái)實(shí)現(xiàn)绷杜,具體代碼如下:
@Bean
public PatternServiceRouteMapper serviceRouteMapper(){
return new PatternServiceRouteMapper(
"(?<name>^.+)-(?<version>v.+$)",
"${version}/${name}");
}
4直秆、Zuul的過(guò)濾器
四種過(guò)濾器:
- PRE:該類型的filters在Request routing到源web-service之前執(zhí)行”廾耍可以進(jìn)行一些權(quán)限認(rèn)證圾结,日志記錄,或者額外給Request增加一些屬性供后續(xù)的filter使用
- ROUTING: 該類型的filters用于把Request routing到源web-service齿诉,源web-service是實(shí)現(xiàn)業(yè)務(wù)邏輯的服務(wù)筝野。這里使用HttpClient請(qǐng)求web-service
- POST: 該類型的filters在ROUTING返回Response后執(zhí)行。用來(lái)實(shí)現(xiàn)對(duì)Response結(jié)果進(jìn)行修改粤剧,收集統(tǒng)計(jì)數(shù)據(jù)以及把Response傳輸會(huì)客戶端;
- ERROR: 上面三個(gè)過(guò)程中任何一個(gè)出現(xiàn)錯(cuò)誤都交由ERROR類型的filters進(jìn)行處理歇竟。
Zuul過(guò)濾器具有以下關(guān)鍵特性:
- Type(類型):Zuul過(guò)濾器的類型,這個(gè)類型決定過(guò)濾器在哪個(gè)階段執(zhí)行抵恋,例如:pre焕议,post等階段;
- Execution Order(執(zhí)行順序):規(guī)定了過(guò)濾器的執(zhí)行順序弧关,Order的值越小盅安,越先執(zhí)行唤锉;
- Criteria(標(biāo)準(zhǔn)):Filters執(zhí)行所需條件
- Action(行動(dòng)):如果符合執(zhí)行條件,則執(zhí)行Action(具體邏輯代碼)
@Sl4j
public class MyPreFilter extends ZuulFilter {
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info("{} AccessUserNameFilter request to {}", request.getMethod(), request.getRequestURL().toString());
// 獲取請(qǐng)求的參數(shù)
String username = request.getParameter("username");
// 如果請(qǐng)求的參數(shù)不為空别瞭,且值為demo時(shí)窿祥,則通過(guò)
if(null != username && username.equals("demo")) {
// 對(duì)該請(qǐng)求進(jìn)行路由
ctx.setSendZuulResponse(true);
ctx.setResponseStatusCode(200);
// 設(shè)值,讓下一個(gè)Filter看到上一個(gè)Filter的狀態(tài)
ctx.set("isSuccess", true);
return null;
}else{
// 過(guò)濾該請(qǐng)求蝙寨,不對(duì)其進(jìn)行路由
ctx.setSendZuulResponse(false);
// 返回錯(cuò)誤碼
ctx.setResponseStatusCode(401);
// 返回錯(cuò)誤內(nèi)容
ctx.setResponseBody("{\"result\":\"username is not correct!\"}");
ctx.set("isSuccess", false);
return null;
}
}
@Override
public boolean shouldFilter() {
// 是否執(zhí)行該過(guò)濾器晒衩,此處為true,說(shuō)明需要過(guò)濾
return true;
}
/**
* 指定該Filter執(zhí)行的順序(Filter從小到大執(zhí)行)
* DEBUG_FILTER_ORDER = 1;
* FORM_BODY_WRAPPER_FILTER_ORDER = -1;
* PRE_DECORATION_FILTER_ORDER = 5;
* RIBBON_ROUTING_FILTER_ORDER = 10;
* SEND_ERROR_FILTER_ORDER = 0;
* SEND_FORWARD_FILTER_ORDER = 500;
* SEND_RESPONSE_FILTER_ORDER = 1000;
* SIMPLE_HOST_ROUTING_FILTER_ORDER = 100;
* SERVLET_30_WRAPPER_FILTER_ORDER = -2;
* SERVLET_DETECTION_FILTER_ORDER = -3;
*/
@Override
public int filterOrder() {
// 優(yōu)先級(jí)為0墙歪,數(shù)字越大听系,優(yōu)先級(jí)越低
return org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
}
@Override
public String filterType() {
// 前置過(guò)濾器
return org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
}
}