SpringCloud筆記五:微服務網關zuul
文章目錄
什麼是網關
- API Gateway,是系統的唯一對外入口,介於客戶端和服務端之間的中間層,處理非業務功能,提供路由請求,鑑權,監控,緩存,限流等功能。
統一接入
智能路由,
AB測試,灰度測試
負載均衡,容災處理
日誌埋點。
流量監控
限流處理
服務降級
安全防護
鑑權處理
監控
機器網絡隔離
- 網關的架構位置
- 主流網關
1、zuul:是Netflix開源的微服務項目,和Eureka,Ribbon,Hystrix等組件配合使用,zuul2.0比1.0的性能提高了很多。
2、Kong:由Mashape公司開源,基於Nginx的ApI gateway
3、Nginx+Lua:是一個高性能的Http和反向代理服務器,lua是腳本語言,讓Nginx執行Lua腳本,並且高併發,非阻塞的處理各種請求。
SpringCloud的網關組件zuul基本使用
- 加入依賴,可以在創建應用的時候選擇zuul和hystrix,引入依賴,比較慢,可以指定鏡像
<repositories>
<repository>
<id>nexus-aliyun</id>
<name>Nexus aliyun</name>
<layout>default</layout>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
- 進行eureka服務註冊
server:
port: 9000
#服務名稱
spring:
application:
name: api-gateway
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
- zuul網關路由映射配置
#自定義路由映射
zuul:
routes:
order-service: /apigatewaytwo/**
product-service: /apigateway/**
ignored-patterns: /*-service/**
#忽略整個服務,對外提供接口
#ignored-services: product-service
- zuul配置作用圖
Zuul常見問題分析和網關過濾器原理分析
- 路由名稱定義問題
路由映射重複覆蓋問題。後面的會覆蓋前面的。
#自定義路由映射
zuul:
routes:
#下面兩個必須唯一
order-service: /apigateway/order/**
product-service: /apigateway/product/**
ignored-patterns: /*-service/**
#忽略整個服務,對外提供接口
#ignored-services: product-service
- http請求頭過濾問題
zuul網關有個問題,默認會屏蔽調請求的cookie內容,這樣後端就會接收不到cookie信息,需要在配置中處理一下。sensitive-headers:
#自定義路由映射
zuul:
routes:
#下面兩個必須唯一
order-service: /apigateway/order/**
product-service: /apigateway/product/**
ignored-patterns: /*-service/**
#處理http請求頭爲空
sensitive-headers:
#忽略整個服務,對外提供接口
#ignored-services: product-service
- 過濾器執行順序問題,過濾器的order值越小,越先執行。
在ZuulFilter類裏面
- 共享requestContext,上下文對象。
自定義Zuul過濾器實現登錄鑑權功能
- 在網關項目中新建一個包filter,然後新建一個類並集成ZuulFilter
- 重寫ZuulFilter裏面的方法。
- 添加@Component,讓spring掃描
- 過濾器代碼
/**
* @program: api-gateway
* @description: 登錄過濾器
* @author: kaifan·Zhang
* @create: 2020-03-19 16:
*/
@Component
public class LoginFilter extends ZuulFilter {
/**
* 過濾器類型,前置過濾器
* @return
*/
@Override
public String filterType() {
return PRE_TYPE;
}
/**
* 過濾器順序,越小越先執行
* @return
*/
@Override
public int filterOrder() {
return 4;
}
/**
* 過濾器是否生效
* @return
*/
@Override
public boolean shouldFilter() {
//在此處做一些,哪些接口需要權限控制。
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
System.out.println(request.getRequestURI());
System.out.println(request.getRequestURL());
/*
* /apigateway/order/api/v1/order/save
http://localhost:9000/apigateway/order/api/v1/order/save
**/
//ACL,將訪問接口列表存儲在redis裏面,定期進行拉取
if("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())){
return true;
}
return false;
}
/**
* 業務邏輯,這段代碼就是如果攔截,就會執行,如果不攔截,就不會執行。
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
//jwt操作
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
String token = request.getHeader("token");
if(StringUtils.isBlank(token)){
token=request.getParameter("token");
}
if(StringUtils.isEmpty(token)){
currentContext.setSendZuulResponse(false);
currentContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());//401未授權
}
return null;
}
}
高併發情況下接口限流的特技
- 採用谷歌guava框架,網關限流
原理:當用戶請求時,服務端設置一個令牌,只有拿到令牌的請求,才允許訪問,否則就拋棄掉。也就是這個網關設置最多訪問量爲1000,當超過1000的併發量時,就限制訪問。
使用RateLimiter設置令牌。這個令牌是每秒產生的。限制每秒最多1000的訪問量。
- 限流種類
1、nginx限流
2、網關限流
- 網關限流代碼
@Component
public class OrderRateLimiterFilter extends ZuulFilter {
//每秒產生1000個令牌
private static final RateLimiter RATE_LIMITER=RateLimiter.create(1000);
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return -4;
}
@Override
public boolean shouldFilter() {
//在此處做一些,哪些接口需要權限控制。
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
if("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())){
return true;
}
return false;
}
@Override
public Object run() throws ZuulException {
//獲取令牌
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
if(!RATE_LIMITER.tryAcquire()){
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());//429請求過多
}
return null;
}
}
Zuul微服務網關集羣搭建
-
網關架構模型
-
nginx+lvs+keepalive
- 開啓多個網關服務
換個服務端口,
或者在Idea的啓動vm中
-Dserver.port=xxxx(端口)