我的博客:程序員笑笑生,歡迎瀏覽博客曾撤!材鹦,搜索博客可添加微信公眾號(hào)蔗喂。
? ?上一章 SpringCloud 基礎(chǔ)教程(九)-Hystrix服務(wù)監(jiān)控(下)當(dāng)中再姑,我們深入了解Hystrix的服務(wù)監(jiān)控胳岂。實(shí)現(xiàn)了分布式環(huán)境下编整,監(jiān)控多個(gè)服務(wù)的信息,本章節(jié)將探索微服務(wù)的另一個(gè)組件乳丰,網(wǎng)關(guān)掌测。
前言
?什么是Zuul,Zuul可以說是一個(gè)大門,所有的來自前端的請(qǐng)求产园,經(jīng)過Zuul時(shí)汞斧,能夠?qū)崿F(xiàn)動(dòng)態(tài)路由轉(zhuǎn)發(fā),監(jiān)控淆两、安全的等邊緣服務(wù)應(yīng)用程序断箫。比如可以作為統(tǒng)一資源的訪問入口、負(fù)載均衡等秋冰。為什么需要需要這樣的一個(gè)組件呢仲义?Netflix開發(fā)這樣的產(chǎn)品是考慮到了以下的原因:api的多樣性和訪問量大能夠?qū)е潞芏嗟膯栴},無法預(yù)警。所以我們需要這樣的系統(tǒng)組件應(yīng)付這些情況埃撵。
一赵颅、Zuul 提供的功能
身份認(rèn)證和安全-可以識(shí)別訪問資源的每一個(gè)請(qǐng)求,拒絕不滿足的請(qǐng)求
洞察和監(jiān)控暂刘,跟蹤有意義的數(shù)據(jù)并統(tǒng)計(jì)饺谬,以便生成有意義的生產(chǎn)視圖
動(dòng)態(tài)路由,根據(jù)需要將請(qǐng)求動(dòng)態(tài)的路由到不同的后端集群谣拣,(最主要的功能)
壓力測(cè)試募寨,逐漸增加集群的流量,評(píng)估性能
限流森缠,為每一個(gè)請(qǐng)求分配容量拔鹰,并丟棄超過限制的請(qǐng)求
處理靜態(tài)響應(yīng),直接在邊緣處構(gòu)建響應(yīng)贵涵,而不是轉(zhuǎn)發(fā)給內(nèi)部集群
二列肢、Zuul 快速入門
?新建Maven項(xiàng)目,引入Zuul的依賴和Eureka的依賴宾茂,我們轉(zhuǎn)發(fā)請(qǐng)求是需要從Eureka中獲取服務(wù)的信息瓷马。Zuul的依賴默認(rèn)集成了hystrix和ribbon
<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>
?新建GateWayApplication啟動(dòng)類,添加@EnableZuulProxy注解跨晴,@SpringBootApplication欧聘、@EnableDiscoveryClient、@EnableCircuitBreaker三個(gè)注解:表示是一個(gè)SpringBoot程序坟奥,啟動(dòng)服務(wù)發(fā)現(xiàn)功能和服務(wù)熔斷功能树瞭,
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringCloudApplication
@EnableZuulProxy
public class GateWayApplication {
public static void main(String[] args) {
SpringApplication.run(GateWayApplication.class);
}
}
?當(dāng)然我們可以使用@SpringCloudApplication一個(gè)注解,從源碼上可以看出@SpringCloudApplication包含了@SpringBootApplication爱谁、@EnableDiscoveryClient晒喷、@EnableCircuitBreaker三個(gè)注解:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}
?配置applicaiton.yml,配置端口號(hào),配置連接Eureka的url访敌,配置zuul相關(guān)配置:
server:
port: 9876
eureka:
instance:
instance-id: gateway1
hostname: eureka7001.com #服務(wù)端的實(shí)例名稱
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
zuul:
ignored-services: "*"
routes:
server-provider:
path: /server-provider/*
?在routes下有以下幾種的配置
第一種:
zuul:
ignored-services: "*"
routes:
server-provider: #配置服注冊(cè)在Eureka的服務(wù)名稱凉敲,指的是服務(wù)中spring.application.name的配置
#將/server-provider/開頭的都轉(zhuǎn)發(fā)到服務(wù)名為server-provider的服務(wù)上,
path: /server-provider/*
第二種:
zuul:
ignored-services: "*"
routes:
server-a: #名稱隨便起
#將/server-provider/開頭的都轉(zhuǎn)發(fā)到服務(wù)名為server-provider的服務(wù)上寺旺,
path: /server-provider/*
#配置服注冊(cè)在Eureka的服務(wù)名稱爷抓,指的是服務(wù)中spring.application.name的配置
serviceId: server-provider
第三種:
zuul:
ignored-services: "*"
routes:
server-b: #名稱隨便起
#將/server-provider/開頭的都轉(zhuǎn)發(fā)到url為 http://localhost:5168/ #的服務(wù)上,
path: /server-provider/*
#配置服注冊(cè)在Eureka的服務(wù)名稱阻塑,指的是服務(wù)中spring.application.name的配置
url: http://localhost:5168/ #不通過Eureka
?接下來蓝撇,我們啟動(dòng)Eureka中心,2個(gè)服務(wù)提供者: server-provider陈莽,啟動(dòng)Zuul網(wǎng)關(guān)服務(wù)渤昌,查看Eureka監(jiān)控頁面:
然后我們通過以下的URL訪問:http://localhost:9876/server-provider/sayHello?name=1 虽抄,可以看到我們通過了Zuul網(wǎng)關(guān)實(shí)現(xiàn)了路由,服務(wù)提供方也能返回請(qǐng)求的結(jié)果独柑,并實(shí)現(xiàn)了負(fù)載均衡:
三迈窟、Zuul過濾器
3.1 過濾器簡介
?上文我們實(shí)現(xiàn)了簡單的路由轉(zhuǎn)發(fā),除了路由轉(zhuǎn)發(fā)忌栅,在實(shí)際的企業(yè)應(yīng)用中车酣,需要結(jié)合不同的需求實(shí)現(xiàn)不同的功能,Zuul可以通過過濾器來實(shí)現(xiàn)接口權(quán)限驗(yàn)證索绪、限流湖员、統(tǒng)計(jì)等。Zuul定義了4種不同的過濾器類型:
我們可以理解為在請(qǐng)求的不同時(shí)間分別調(diào)用:
- pre:這種過濾器在請(qǐng)求被轉(zhuǎn)發(fā)之前調(diào)用瑞驱,一般用來實(shí)現(xiàn)身份驗(yàn)證等
- routing:這種路由是用來路由到不同的后端服務(wù)的破衔,底層可以使用httpclient或者ribbon請(qǐng)求微服務(wù)
- post:當(dāng)請(qǐng)求轉(zhuǎn)發(fā)到微服務(wù)以后,會(huì)調(diào)用當(dāng)前類型的過濾器钱烟。通常用來為響應(yīng)天啊及標(biāo)椎的HTTP Header、收集統(tǒng)計(jì)信息嫡丙,等
- error:當(dāng)發(fā)生錯(cuò)誤是執(zhí)行的過濾器
3.2 自定義過濾器實(shí)現(xiàn)Token驗(yàn)證
?自定義過濾器需要集成com.netflix.zuul.ZuulFilter類拴袭,并實(shí)現(xiàn)其抽象的方法達(dá)到所需要的目的,這里我們簡單的實(shí)現(xiàn)通過Token的驗(yàn)證:
import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*驗(yàn)證token
*/
@Component
public class TokenFilter extends ZuulFilter {
private Logger logger=LoggerFactory.getLogger(TokenFilter.class);
/**
* 返回過濾器類型 "pre" / "route" / "post" / “ error”
*
* @return
*/
@Override
public String filterType() {
return "pre";
}
/**
* 過濾器的順序曙博,不同的過濾器順序可以相同
*
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 判斷是否要執(zhí)行 true表示執(zhí)行 run方法
*
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 當(dāng) shouldFilter() 返回true時(shí)候
* 執(zhí)行run中的具體邏輯拥刻、返回值在當(dāng)前的版本中沒有意義
*
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
HttpServletResponse response = context.getResponse();
//獲取header中的token
String token = request.getHeader("token");
JSONObject jsonObject=new JSONObject();
//如果token為空,設(shè)置返回狀態(tài)為401父泳,返回json的信息
if (StringUtils.isEmpty(token)) {
context.setSendZuulResponse(false);
context.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
jsonObject.put("code",401);
jsonObject.put("msg","UNAUTHORIZED");
context.setResponseBody(jsonObject.toJSONString());
logger.info("msg:{}",jsonObject);
} else {
//否則執(zhí)行請(qǐng)求
logger.info("msg:{}","ok");
return null;
}
return null;
}
}
- filterType:返回過濾器類型 "pre" / "route" / "post" / “ error”
- filterOrder:過濾器的順序
- shouldFilter:為true時(shí)候般哼,執(zhí)行run方法
- run:具體的邏輯,在方法中我們可以獲取到RequestContext對(duì)象惠窄,通過該對(duì)象獲取請(qǐng)求頭的信息蒸眠,并設(shè)置返回信息
?接下來,我們啟動(dòng)相應(yīng)的服務(wù)杆融,并發(fā)送請(qǐng)求楞卡,如果沒有token,則返回如下的信息:
這樣我們就能實(shí)現(xiàn)一個(gè)簡單的通過Token的過濾驗(yàn)證了脾歇。
?對(duì)于啟用/禁用過濾器蒋腮,我們不可能去修改過濾器的代碼,我們可以通過配置文件配置進(jìn)行過濾的控制藕各,在applicaiton.yml中我們可以這樣配置:
zuul:
#過濾器的名稱
TokenFilter:
pre :
#true表示禁用
disable : true
3.3 請(qǐng)求重試
?當(dāng)Zuul轉(zhuǎn)發(fā)失敗時(shí)池摧,可以通過配置使Ribbon的客戶端進(jìn)行重試,默認(rèn)是false
zuul:
retryable: true
3.4 敏感Header的過濾
?在請(qǐng)求的轉(zhuǎn)發(fā)過程中激况,默認(rèn)會(huì)轉(zhuǎn)發(fā)HTTP的Header信息作彤,有時(shí)候我們不希望這些信息被轉(zhuǎn)發(fā)膘魄,比如Cookie,token宦棺,我們可以通過sensitiveHeaders配置瓣距,多項(xiàng)之間用逗號(hào)隔開:
zuul:
sensitive-headers: Cookie,token
3.5 設(shè)置統(tǒng)一的前綴
zuul:
prefix: /api
四、總結(jié)
?本章分享了Zuul組件在微服務(wù)架構(gòu)中擔(dān)任的角色代咸,并通過示例的方式實(shí)現(xiàn)了通過Token簡單的過濾請(qǐng)求蹈丸,當(dāng)然Zuul的功能不知于此,Zuul經(jīng)歷過各大互聯(lián)網(wǎng)公司的檢驗(yàn)呐芥,能夠和Spring Cloud生態(tài)完美的融合逻杖,是微服務(wù)不可或缺的一個(gè)關(guān)鍵節(jié)點(diǎn)。
----END----
以就是本期的分享思瘟,你還可以關(guān)注公眾號(hào): 程序員笑笑生荸百,關(guān)注更多精彩內(nèi)容!
SpringCloud基礎(chǔ)教程(一)-微服務(wù)與SpringCloud
SpringCloud基礎(chǔ)教程(二)-服務(wù)發(fā)現(xiàn) Eureka
SpringCloud基礎(chǔ)教程(三)-Eureka進(jìn)階
SpringCloud 基礎(chǔ)教程(四)-配置中心入門
SpringCloud基礎(chǔ)教程(五)-配置中心熱生效和高可用
SpringCloud 基礎(chǔ)教程(六)-負(fù)載均衡Ribbon
SpringCloud 基礎(chǔ)教程(七)-Feign聲明式服務(wù)調(diào)用
SpringCloud 基礎(chǔ)教程(八)-Hystrix熔斷器(上)
SpringCloud 基礎(chǔ)教程(九)-Hystrix服務(wù)監(jiān)控(下)
SpringCloud 基礎(chǔ)教程(十)-Zull服務(wù)網(wǎng)關(guān)
更多精彩內(nèi)容滨攻,請(qǐng)期待...
本文由博客一文多發(fā)平臺(tái) OpenWrite 發(fā)布够话!