在原先的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中配置的流控规则,这样就达到了固化流控规则的目的。