在微服務的架構下,各個服務一般會有各自的網絡地址,在這樣的情況下外部客戶端的調用可能會形成雜亂無章的局面。這時候我們就可以使用微服務網關Zuul這個組件,我們讓所有的客戶端請求全部請求Zuul,再由Zuul統一的去請求各個服務。
一、Zuul簡介
Zuul是Netflix開源的微服務網關,他可以和Eureka,Ribbon,Hystrix等組件配合使用。Zuul組件的核心是一系列的過濾器,這些過濾器可以完成以下功能:
- 身份認證和安全: 識別每一個資源的驗證要求,並拒絕那些不符的請求
- 審查與監控:
- 動態路由:動態將請求路由到不同後端集羣
- 壓力測試:逐漸增加指向集羣的流量,以瞭解性能
- 負載分配:爲每一種負載類型分配對應容量,並棄用超出限定值的請求
- 靜態響應處理:邊緣位置進行響應,避免轉發到內部集羣
- 多區域彈性:跨域AWS Region進行請求路由,旨在實現ELB(ElasticLoad Balancing)使用多樣化
Spring Cloud對Zuul進行了整合和增強。目前,Zuul使用的默認是Apache的HTTP Client,也可以使用Rest Client,可以設置ribbon.restclient.enabled=true.。
二、創建一個api-gateway工程
這裏我們使用IntelliJ IDEA進行展示。
1.首先創建一個Zuul項目
使用IDEA創建一個項目
中間有一步我們選擇Zuul選項和SpringBoot版本,如圖
然後下一步就可以創建好了
2.添加@EnableZuulProxy註解
這個註解只需要在springboot工程的啓動application類上就好了
@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
public class ApiGetwayApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGetwayApplication.class, args);
}
然後在配置文件中添加config的配置,具體可以見小白學SpringCloud(三):統一配置中心(config)。然後就可以使用Zuul工程的路由了,依次運行Eureka、Config、Client客戶端、Zuul。
我們先來隨便訪問一下client端的env接口
然後我們通過zuul服務的端口+項目名/接口名這種方式來訪問一下這個接口
可以看到,同樣訪問到了結果。
另外,我們也可以在配置文件中更加細粒度控制路由路徑:
# 表示只要HTTP請求是 /client1開始的,就會轉發到服務id爲client1的服務上面
zuul:
routes:
client1:
path:/client1/** // 路由路徑
serviceId: client1 // 服務id
client2:
path:/client2/** // 路由路徑
serviceId: client2 // 服務id
需要注意的是,使用Zuul默認不會將Cookie的信息帶入服務端,所以我們需要在配置文件中進行配置,將敏感頭設置爲空即可:
zuul:
sensitiveHeaders:
二、服務過濾
zuul不僅只是路由,並且還能過濾,做一些安全驗證。我們來新建一個Filter並且繼承ZuulFilter
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
/**
* @Author: lllx
* @Description:
* @Date: Created on 17:54 2018/7/10
* @Modefied by:
*/
public class MyFilter extends ZuulFilter {
/*返回一個字符串代表過濾器的類型
pre:路由之前
routing:路由之時
post: 路由之後
error:發送錯誤調用
我們可以通過導入FilterConstants這個常量類中的屬性來返回
*/
@Override
public String filterType() {
return PRE_TYPE;
}
//過濾的順序,Zuul中也自定義了很多過濾器,調用的順序即通過這個方法返回的大小,越小越靠前。我們可以通過FilterConstants這個常量類中定義好的過濾器-1來返回
@Override
public int filterOrder() {
return PRE_DECORATION_FILTER_ORDER -1;
}
//這裏可以寫邏輯判斷,是否要過濾,本文true,永遠過濾。
@Override
public boolean shouldFilter() {
return true;
}
//過濾器的具體邏輯。可用很複雜,包括查sql,nosql去判斷該請求到底有沒有權限訪問。
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
//從url參數獲取如果沒有token這個參數就不允許請求
String token = request.getParameter("token");
if(StringUtils.isEmpty(token)){
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
return null;
}
}
我們可以通過這樣的方式去自定義一個個的過濾器。
本文作者: catalinaLi
本文鏈接: http://catalinali.top/2018/startZuul/
版權聲明: 原創文章,有問題請評論中留言。非商業轉載請註明作者及出處。