Spring-Cloud-Netflix-Zuul網關
API網關
- API網關,顧名思義,是統一管理API的一個網絡關口、通道,是整個微服務平台所有請求的唯一入口
- 所有的客戶端和消費端都通過統一的網關接入微服務,在網關層處理所有的非業務功能
有網關和沒有網關:
- 沒有:沒有網關的時候, 用戶可以隨意訪問一台微服務
- 有:有了網關后, 請求必須得要先經過網關, 確定這個請求是否合法,如果合法, zuul會對其做出判斷 , 轉發到指定的微服務,也會自動幫助做負責均衡
Zuul概述
- Zuul是Netflix出品的一個基於JVM路由和服務端的負載均衡器(網關)
- Zuul包含了對請求的路由和過濾兩個最主要的功能:
- 路由功能負責將外部請求轉發到具體的微服務實例上,是實現外部訪問統一入口的基礎
- 過濾器功能則負責對請求的處理過程進行干預,是實現請求校驗、服務聚合等功能的基礎
- Zuul也作為一個客戶端注冊進Eureka
將Zuul自身注冊為Eureka服務治理下的應用
同時從Eureka中獲得其他微服務的消息,也即以后的訪問微服務都是通過Zuul跳轉后獲得。
Zuul使用
1. 在工程當中創建一個網關微服務
2. 導入zuul相關依賴
<dependencies>
<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>
</dependencies>
3.創建啟動類,在啟動類上添加@EnableZuulProxy
@SpringBootApplication
@EnableZuulProxy
public class zullAppServer {
public static void main(String[] args) {
SpringApplication.run(zullAppServer.class,args);
}
}
4 .創建application/yml
server:
port: 8001
eureka:
client:
serviceUrl:
#eureka服務端提供的注冊地址 參考服務端配置的這個路徑
defaultZone: http://eureka:3000/eureka,http://eureka1:3001/eureka,http://eureka2:3000/eureka2
instance:
instance-id: zull-0 #此實例注冊到eureka服務端的唯一的實例ID
prefer-ip-address: true #是否顯示IP地址
#eureka客戶需要多長時間發送心跳給eureka服務器,表明它仍然活着,默認為30 秒 (與下面配置的單位都是秒)
leaseRenewalIntervalInSeconds: 1
#Eureka服務器在接收到實例的最后一次發出的心跳后,需要等待多久才可以將此實例刪除,默認為90秒
leaseExpirationDurationInSeconds: 3
spring:
application:
name: client-zuul #此實例注冊到eureka服務端的name
- 啟動 根據zull的端口號+服務名稱 訪問
zuul配置路由
- 在zuul的配置文件當中添加如下配置
zuul:
routes:
goods: #自己定義的名稱 商品服務
serviceId: client-goods
path: /goods/** #/* 是一級 /** 是多級
order: #訂單服務
serviceId: client-order
path: /order/**
配置完成后,再訪問地址http://localhost:8003/goods/getGoods.do
- 禁用通過微服務的名稱直接調用
- prefix 前綴: 訪問網關時需要加上prefix
訪問時:http://localhost:8001/api/goods/getGoods.do
過濾器
過濾器(filter)是zuul的核心組件 zuul大部分功能都是通過過濾器來實現的
zuul中定義了4種標准過濾器類型:
- PRE
這種過濾器在請求被路由之前調用。 可利用這種過濾器實現身份驗證、在 集群中選擇請求的微服務、記錄調試信息等。- ROUTING
這種過濾器將請求路由到微服務。 這種過濾器用於構建發送給微服 務的請求,並使用 Apache HttpCIient或 Netfilx- POST:
這種過濾器在路由到微服務以后執行。
這種過濾器可用來為響應添加標准 的 HTTP Header、收集統計信息和指標、將響應從微服務發送給客戶端等- ERROR:
在其他階段發生錯誤時執行該過濾器。
自定義過濾器: 寫一個類繼承 ZuulFilter類
@Component
public class zfilter extends ZuulFilter {
/*返回過濾器的類型*/
@Override
public String filterType() {
return FilterConstants.PRE_TYPE; //前置過濾器
}
/*返回指定過濾器的執行順序 越小越靠前*/
@Override
public int filterOrder() {
//+1 在此過濾器之后執行
return FilterConstants.PRE_DECORATION_FILTER_ORDER+1;
}
/*判斷該過濾器是否要執行, true表示執行, false表示不執行。*/
@Override
public boolean shouldFilter() {
return true;
}
/*過濾器的具體邏輯*/
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String remoteAddr = request.getRemoteAddr();
System.out.println("訪問者IP:"+remoteAddr+"訪問地址:"+request.getRequestURI());
//可以通過strip-prefix: true/false確定是否要移除前綴
System.out.println("路由后的地址:"+ctx.get(FilterConstants.REQUEST_URI_KEY));
return null;
}
}
zuul容錯與回退
zuul默認是整合了hystrix和ribbon的, 提供降級回退,當服務訪問不通的時候,會調用自己提供的方法,是服務級別的
實現步驟:
- 編寫一個類,實現FallbackProvider
@Component
public class ZuulFallBackProvider implements FallbackProvider {
//制定為哪個微服務提供回退(這里寫微服務名 寫*代表所有微服務)
@Override
public String getRoute() {
return "*";
}
//此方法需要返回一個ClientHttpResponse對象
// ClientHttpResponse是一個接口,具體的回退邏輯要實現此接口
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
//這里可以判斷根據不同的異常來做不同的處理, 也可以不判斷
//完了之后調用response方法並根據異常類型傳入HttpStatus
if (cause instanceof HystrixTimeoutException) {
return response(HttpStatus.GATEWAY_TIMEOUT);
} else {
return response(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
private ClientHttpResponse response(final HttpStatus status) {
//這里返回一個ClientHttpResponse對象 並實現其中的方法,關於回退邏輯的詳細,便在下面的方法中
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
//返回一個HttpStatus對象 這個對象是個枚舉對象, 里面包含了一個status code 和reasonPhrase信息
return status;
}
@Override
public int getRawStatusCode() throws IOException {
//返回status的code 比如 404,500等
return status.value();
}
@Override
public String getStatusText() throws IOException {
//返回一個HttpStatus對象的reasonPhrase信息
return status.getReasonPhrase();
}
@Override
public void close() {
//close的時候調用的方法, 講白了就是當降級信息全部響應完了之后調用的方法
System.out.println("close調用");
}
@Override
public InputStream getBody() throws IOException {
//把降級信息響應回前端
return new ByteArrayInputStream("系統繁忙,請稍后再試".getBytes());
}
@Override
public HttpHeaders getHeaders() {
//需要對響應報頭設置的話可以在此設置
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}
zuul集群
新創建創建兩個zuul服務
修改8001的zullsever代理的配置
8002的zuul服務端:
8003的zull服務
開啟所有的服務:
訪問goods服務:
http://localhost:8002/api/goods/getGoods.do