什麼是網關
API Gateway,是系統的唯一對外的入口,介於客戶端和服務器端之間的中間層,處理非業務功能 提供路由請求、鑑權、監控、緩存、限流等功能
什麼是Zuul
Spring Cloud Zuul是整合Netflix公司的Zuul開源項目實現的微服務網關,它實現了請求路由、負載均衡、校驗過 慮等 功能。
Zuul與Nginx怎麼配合使用
Nginx的作用是反向代理、負載均衡,Zuul的作用是保障微服 務的安全訪問,攔截微服務請求,校驗合法性及負載均衡。
實際運用
客戶端請求網關/api/learning,通過路由轉發到/learning
客戶端請求網關/api/course,通過路由轉發到/course
pom依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
Zuul配置
zuul:
routes:
manage-course:
path: /course/**
serviceId: xc-service-manage-course #微服務名稱,網關會從eureka中獲取該服務名稱下的服務實例的地址
# 例子:將請求轉發到http://localhost:31200/course
#url: http://www.baidu.com #也可指定url,此url也可以是外網地址\
strip-prefix: false #true:代理轉發時去掉前綴,false:代理轉發時不去掉前綴
sensitiveHeaders: #默認zuul會屏蔽cookie,cookie不會傳到下游服務,這裏設置爲空則取消默認的黑名單,如果設置了具體的頭信息則不會傳到下游服務
# ignoredHeaders: 默認爲空表示不過慮任何頭
xc-service-learning: #路由名稱,名稱任意,保持所有路由名稱唯一
path: /learning/**
serviceId: xc-service-learning #指定服務id,從Eureka中找到服務的ip和端口
strip-prefix: false
sensitiveHeaders:
- manage-course:爲路由名稱,名稱任意,保持所有路由名稱唯一
- path:代理的請求
- serviceId:微服務名稱,網關會從eureka中獲取該服務名稱下的服務實例的地址,轉發到該地址
- strip-prefix:是否去掉前綴,true:代理轉發時去掉前綴,false:代理轉發時不去掉前綴,例如,爲true請 求/course/coursebase/get/…,代理轉發到/coursebase/get/,如果爲false則代理轉發到/course/coursebase/get
- sensitiveHeaders:敏感頭設置,默認會過慮掉cookie,這裏設置爲空表示不過慮
- ignoredHeaders:可以設置過慮的頭信息,默認爲空表示不過慮任何頭
啓動類
@SpringBootApplication
@EnableZuulProxy//此工程是一個zuul網關
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
@EnableZuulProxy:表明此工程是一個zuul網關
過慮器
我們要定義一個過濾器繼承ZuulFilter,重寫其方法來實現身份校驗,請求過濾
filterType :返回的字符代表過濾器類型,
- pre:請求在被路由之前調用,我們可以利用這種過濾器實現身份驗證,在集羣中選擇請求的爲服務、記錄調試信息等。
- routing:將請求路由到爲服務。構建發送給微服務的請求
- post:這種過濾器在routing和error過濾器後調用,可以爲響應添加標準的http header、收集信息的指標
- error:處理請求時發生錯誤調用
filterOrder:此方法返回整形數值,通過此數值來定義過濾器的執行順序,數字越小優先級越高
shouldFilter:返回一個Boolean值,判斷該過濾器是否需要執行
run:過濾器的業務邏輯
@Component
public class LoginFilter extends ZuulFilter {
@Autowired
private AuthService authService;
private static final Logger LOG = LoggerFactory.getLogger(LoginFilter.class);
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 3;
}
@Override
public boolean shouldFilter() {
return true;
}
/**
* 身份校驗
*
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
// 獲取請求容器
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
HttpServletResponse response = currentContext.getResponse();
// 獲取token
String token = authService.getTokenFromCookie(request);
if (StringUtils.isEmpty(token)){
access_denied();
}
// 查詢jwt
String jwt = authService.getJwtFromHeader(request);
if (StringUtils.isEmpty(jwt)){
access_denied();
}
// 從redis中校驗身份令牌是否過期
long expire = authService.getExpire(token);
if (expire<0){
access_denied();
}
return null;
}
private void access_denied() {
RequestContext currentContext = RequestContext.getCurrentContext();
// 拒絕請求
currentContext.setSendZuulResponse(false);
// 設置響應狀態碼
currentContext.setResponseStatusCode(200);
ResponseResult result = new ResponseResult(CommonCode.FAIL);
String jsonString = JSON.toJSONString(result);
currentContext.setResponseBody(jsonString);
currentContext.getResponse().setContentType("application/json;charset=UTF-8");
}
}