在原先的Horizon平台中,我們采用的是Netflix Zuul作為應用網關,並通過一系列增強的組件和配置來完成限流、降級、熔斷的處理。在Spring Cloud Alibaba中,我們將采用Spring Cloud Gateway和Sentinel作為Zuul的代替品。
在開始搭建工程之前,首先需要跑起來一個Sentinel的控制台,用來對Sentinel的各項參數進行調整,以及實時監控網關的性能數據。從https://github.com/alibaba/Sentinel/releases頁面下載最近的release jar包,而后在本地運行起來:
java -Dserver.port=8847 -Dcsp.sentinel.dashboard.server=localhost:8850 -Dproject.name=sential-dashboard -jar .\sentinel-dashboard-1.7.2.jar
這里指定了兩個端口,server.port指定的是dashboard應用網頁的端口,而csp.sentinel.dashboard.server中的端口則是對外提供sentinel管理服務的端口。上述jar包啟動之后,訪問http://localhost:8847/#/login,可以進入Sentinel Dashboard的登錄界面:
使用默認的用戶名和密碼(均為sentinel)登錄到sentinel主界面:
剛啟動應用的時候,左側應該是沒有任何服務的。
至此,Dashboard搭建完畢。
主體應用仍然是Spring Cloud Gateway,這是Spring Cloud官方出品的網關組件,我們使用它來完成基本的網關路由功能。
在前篇Nacos的工程中,建立一個新的模塊,命名為gateway,引入如下依賴:
<!-- Spring Cloud Alibaba Begin --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <!-- Spring Cloud Alibaba End --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> <version>2.2.4.RELEASE</version> </dependency>
除了必要的Nacos配置服務、Nacos服務發現的依賴之外,還額外引入了sentinel和spring-cloud-starter-gateway。
啟動類加上@EnableDiscoveryClient注解,以開啟服務發現。
配置文件中依舊只保留從配置中心獲取配置的必要配置:
spring: profiles: active: dev cloud: nacos: config: server-addr: 127.0.0.1:8848 username: nacos password: nacos file-extension: yml group: API-Platform application: name: gateway-service
在Nacos中添加如下配置:
server: port: 8888 spring: cloud: sentinel: transport: port: 8850 dashboard: localhost:8847 nacos: discovery: server-addr: 127.0.0.1:8848 username: nacos password: nacos gateway: discovery: locator: enabled: true
上述配置中sentinel部分指定了兩個端口,一個是8850,也就是服務端口,另外一個是8847,也就是sentinel dashboard的網頁地址。
因為只是簡單驗證一下功能可用性,所以這里我們沒有添加任何路由規則,按默認的規則來進行訪問。
啟動應用,如果沒有報錯,就可以開始進行網關的功能驗證了。
接下來,在Nacos搭建過程中的admin-service,我們在搭建時只給它加了個注解啟用了SpringBootAdmin組件,接下來,在里面寫一個很簡單的驗證Controller:
package com.aac.horizon.admin.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class AdminController { @GetMapping(value = "/hello") public String hello(){ return "hello"; } }
啟動后,嘗試直接來訪問這個Controller:
接下來,通過網關來進行訪問:
通過網關同樣訪問到了這個Controller。
這個時候回到Sentinel的控制台,左側應該就會出現剛才啟動的網關服務,而點開網關實例后,左側的菜單可以分別呈現不同的監控內容和控制面板。在這里,可以查看當前網關的請求負載情況,
可以在此處針對每一個API單獨設置限流規則:
此處給我們新增的Controller添加一個簡單的流量控制規則:
而后多次刷新瀏覽器的訪問頁面,將得到如下報錯信息:
相比Zuul的限流策略,此處的控制更加精細,可以細化到API,且無需通過配置文件,但同樣存在一個問題,即,Sentinel的所有規則全部是在內存中進行存儲的,一旦Sentinel Dashboard應用出現宕機或重啟,則需要重新定制全部規則。因此,考慮將Sentinel的所有規則進行固化配置,首選仍然是放在Nacos中:
引入如下依賴:
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency>
在Nacos的Sentinel配置中加入如下配置:
sentinel: datasource: ds: nacos: ### nacos連接地址 server-addr: localhost:8848 ## nacos連接的分組 group-id: DEFAULT_GROUP ###路由存儲規則 rule-type: flow ### 讀取配置文件的 data-id data-id: ratelimit_rule ### 讀取文件類型為json data-type: json
在Nacos中加入如下配置:
[ { "resource": "/admin-service/hello", "limitApp": "default", "grade": 1, "count": 5, "strategy": 0, "controlBehavior": 0, "clusterMode": false } ]
通過上述處理,Sentinel在啟動的時候會讀取Nacos中配置的流控規則,這樣就達到了固化流控規則的目的。