Spring Cloud Gateway是基于Spring framework 5、Project Reactor和Spring Boot 2.0構建的API網關實現。它取代了之前使用的spring-cloud-netflix-zuul。請訪問下面的鏈接了解更多詳情。
Spring Cloud Greenwich.RC1現已發布。(https://spring.io/blog/2018/12/12/spring-cloud-greenwich-rc1-available-now#spring-cloud-netflix-projects-entering-maintenance-mode)
還有一些其他的API網關實現,如Kong、Tyk、Apigee等,它們并不基于Spring Cloud。但是本討論完全基于Spring團隊創建的開源Spring Cloud Gateway。
Spring Cloud Gateway是非阻塞式的,即它的設計、編寫方式絕不會阻塞主線程。相反,這些線程始終可以為請求提供服務,并在后臺異步處理請求,一旦處理完成就返回響應。
Spring Cloud Gateway提供以下幾個功能:
Spring Cloud Gateway是一個反向代理。反向代理是位于試圖訪問資源的客戶端和資源本身之間的中間服務器。客戶端甚至不知道自己正在與服務器通信。反向代理負責捕獲客戶端的請求,然后代表客戶端調用遠程資源。簡而言之,反向代理就像其他API網關一樣,充當所有進入系統的請求的單一入口點,而系統則分為一個或多個微服務。
可以對網關進行配置,以基于與DiscoveryClient兼容的服務注冊表中注冊的服務創建路由。要啟用此功能,我們需要在屬性文件中設置以下屬性,并確保DiscoveryClient實現位于類路徑上并已啟用(例如Netflix Eureka、Consul或Zookeeper)。
spring.cloud.gateway.discovery.locator.enabled=true
Spring Cloud Gateway現在將自動使用被調用服務的Eureka服務ID,并將其映射到下游服務實例。
路由可以通過Java配置或通過在屬性/YAML文件中配置來定義。在這里,為了簡單起見,我們將使用第二種方法,因為它可以根據需求進行外部化。
spring.cloud.gateway.routes[0].id=product-servicespring.cloud.gateway.routes[0].uri=lb://product-servicespring.cloud.gateway.routes[0].predicates[0]=Path=/product/**spring.cloud.gateway.routes[1].id=inventory-servicespring.cloud.gateway.routes[1].uri=lb://inventory-servicespring.cloud.gateway.routes[1].predicates[0]=Path=/inventory/**
當存在多個可用實例時,Spring Cloud Gateway將智能地在Discovery客戶端中的可用實例之間平衡傳入請求的負載。
它內部使用spring-cloud-loadbalancer來分發請求流量。它使用其中一種算法來完成相同的操作,但是負載均衡算法的內部實現超出了本討論的范圍,我們將在演示結束后的幾分鐘內更詳細地討論它是如何實現的。
注意:這不能與使用Spring-cloud-loadbalancer的客戶端負載均衡混淆,后者需要在服務通過基于Spring的不同同步/異步Rest客戶端(如RestTemplate、WebClient等)相互通信時使用,與Spring Cloud的Open Feign不同,這些客戶端默認情況下不進行負載均衡。此外,當請求到達單個服務之一時,需要客戶端負載均衡,而在Spring Cloud Gateway中,請求仍在API Gateway層,不需要客戶端負載均衡。
好了,現在讓我們通過一個快速演示來說明這一點吧。
在這個演示中,我們將創建兩個服務,一個是產品服務(product service),一個是庫存服務(inventory service),并將它們的多個實例注冊到Netflix Eureka Discovery Server上。完成后,我們將創建API Gateway服務器,并將其注冊到Eureka Client中。
所有的服務都是使用Spring Boot 3.2.4和Spring Cloud 2023.0.0創建的。
所有服務啟動并正常運行后,我們可以在下面的Eureka儀表板上看到注冊的所有服務,它們運行在8761端口上,每個服務有多個(2個)實例。
圖片
Eureka儀表板顯示所有已注冊服務,運行在8761端口上。
現在讓我們深入了解各個服務。為了展示Spring Cloud Gateway的路由和負載均衡功能,我們將盡量保持業務邏輯的最小化。
我們在每個服務中創建了一個/greet端點,它是一個HTTP GET請求。為了展示負載均衡功能,我們在響應體中發送以下字段:
但是其中最重要的是端口,因為它是用來識別負載均衡功能的。為了獲取該值,我們可以在控制器層添加以下代碼片段,如下所示:
@Value("${spring.application.name}")private String appName;// 只有當發現客戶端是Eureka時才有效private EurekaClient eurekaClient;// 連接Eureka客戶端public ProductController(EurekaClient eurekaClient) { this.eurekaClient = eurekaClient; }@GetMapping("/greet")public ResponseEntity<GreetingResponse> getProduct(HttpServletRequest request) { InstanceInfo service = eurekaClient.getApplication(appName).getInstances().get(0); response.setPort(service.getPort()); return new ResponseEntity<>(response, HttpStatus.OK);}
接下來,我們需要在API Gateway中配置路由。路由配置已在本文的路由部分中提到過。
一切就緒后,讓我們測試一下應用程序。
我們將需要一些REST API測試工具,如Postman或Insomnia。在這里使用了Insomnia。
Spring Cloud Gateway運行在Spring Boot的默認端口8080上。我們將訪問API Gateway,而不是直接調用產品/庫存服務,這也是本演示的目的所在,看看我們是否能夠獲得響應。
圖片
圖片
由于我們能夠獲得正確的響應,說明路由功能正常工作。
現在,讓我們來看看負載均衡方面的內容。我們只選取庫存服務實例進行演示。
在上面的截圖中,我們看到庫存服務的端口是58464,這意味著請求是從58464端口提供的。讓我們再次發出請求,看看我們是否會一直獲得相同的端口。
圖片
在多次訪問端點后,我們發現一些不同的端口號58436和一些不同的實例ID,這意味著請求是從另一個實例提供的,而不是同一個實例。這意味著它成功地分發了請求。
完成上述工作后,讓我們試著深入研究一下。我們從API Gateway服務器的日志開始,通過將日志級別設置為TRACE來查看發生了什么。
日志有很多,但最重要的是下面的內容,它可以幫助我們窺探框架層的幕后運行狀況。
圖片
因此,基本上,負載均衡的實際URL是在Spring Cloud Gateway jar文件的以下類中解析的:
https://github.com/spring-cloud/spring-cloud-gateway/blob/main/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/ReactiveLoadBalancerClientFilter.java
日志分別來自第108行和第143行?,F在,在所有的方法中,choose()方法是最重要的,它創建了負載均衡器的實例ReactLoadBalancer。ReactLoadBalancer是一個接口,來自于spring cloud loadbalancer,它為實際的負載均衡實現算法提供了一個抽象。目前有兩種可用的實現方式,即RandomLoadBalancer和RoundRobinLoadBalancer。關于它的工作原理和算法實現的更多內部細節對于開發者來說并不重要,因為Spring Cloud Gateway框架已經在開箱即用時處理了這些細節。
但需要理解的一點是,如果沒有lb方案,負載均衡將無法工作。在路由部分,我們在屬性文件的API Gateway服務中定義了以下配置。
spring.cloud.gateway.routes[1].uri=lb://inventory-service
如果URL具有lb方案(即lb://myservice),它將使用Spring Cloud ReactorLoadBalancer將名稱解析為實際的主機和端口。因此,如果不添加lb方案,負載均衡將無法工作。
這就是關于Spring Cloud Gateway中路由和負載均衡的討論。完整的代碼可以在以下的GitHub鏈接中找到。
https://github.com/purbarunc/Spring-Cloud-Microservice/tree/gateway-loadbalancing
本文鏈接:http://www.tebozhan.com/showinfo-26-88355-0.html基于Spring Cloud Gateway,實現路由和負載均衡
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
下一篇: 字節面試:說說Java中的鎖機制?