原先做了个Spring Cloud的小项目(未完成),使用Spring的全家桶,其中注册中心用的是eureka,但目前2.X版本已经停止维护了。
最近刷到了Nacos相关的信息,去了解了下,是属于Spring Cloud Alibaba的组件,能当注册中心和配置中心使用。正好想体验下Spring Cloud Alibaba,于是就上手试试了。
摘一段Spring Cloud Alibaba与Spring Cloud的关系概述:
Spring Cloud Alibaba是依赖SpringCloud相关的标准实现的一套微服务的架构。
结合阿里巴巴的相关实践与阿里云的相关服务实现的一些组件得以更快的实现相关产品业务。
这篇文章是来记录几个体验过程中遇到的小坑,虽然大多数属于没有好好看文档导致的。
版本
使用Spring Cloud Alibaba需要配置对应的Spring Cloud和Spring Boot版本,不然可能会出现乱七八糟的错误。
官方的版本对应关系链接:Spring Cloud Alibaba版本说明
我这里用的版本:
- Spring Cloud Alibaba:2.2.3.RELEASE
- Spring Cloud:Hoxton.SR8
- Spring Boot:2.3.2.RELEASE
另外提一句目前最新版的SpringBoot为2.4.1,但和Nacos的最新版本不兼容,等修复吧。(GitHub issues链接)
配置中心
模块要使用配置中心,一开始在模块下建立了application.yml
,并添加如下配置,进行读取远程配置,但启动后报错无法读取,查了下才知道需要把文件名改为bootstrap.yml
,两者具体差别自行Google。
server:
port: 6001
spring:
profiles:
active: dev
application:
name: demo-client
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848 #配置中心地址
file-extension: yaml
查看Nacos Spring Cloud文档有提到dataId
的格式,也就是Nacos控制台对应的文件,默认格式为:
${prefix}-${spring.profiles.active}.${file-extension}
- ${prefix}:默认是
application.name
,在我这个配置文件里就是demo-client。 - ${spring.profiles.active}:这个值取的是
spring.profiles.active
,在我这是dev。 - ${file-extension}:这个就是文件的后缀,默认是
properties
,我这里配置了yaml。
结合上面,我这份配置文件会到Nacos的配置中心里,找到demo-client-dev.yaml
这个配置进行读取,所以我们需要建立对应的文件存放配置。
网关限流
使用了Spring Cloud Gateway,配合sentinel进行限流。
maven:
<!-- 限流熔断 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
配置文件:
server:
port: 8888
spring:
application:
name: server-gateway
cloud:
nacos:
server-addr: localhost:8848
gateway:
routes:
- id: server-source
uri: lb://server-source
predicates:
- Path=/server-source/**
filters:
- StripPrefix=1
限流配置类
@Configuration
public class GatewayConfiguration {
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
// 初始化一个限流的过滤器
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
// 配置初始化的限流参数
@PostConstruct
public void initGatewayRules() {
Set<GatewayFlowRule> rules = new HashSet<>();
rules.add(new GatewayFlowRule("server-source") //资源名称,对应路由id
.setCount(1) // 限流阈值
.setIntervalSec(1) // 统计时间窗口,单位是秒,默认是 1 秒
);
GatewayRuleManager.loadRules(rules);
}
// 配置限流的异常处理器
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
// 自定义限流异常页面
@PostConstruct
public void initBlockHandlers() {
BlockRequestHandler blockRequestHandler = (serverWebExchange, throwable) -> {
Map map = new HashMap<>();
map.put("code", 0);
map.put("message", "接口被限流了");
return ServerResponse.status(HttpStatus.OK).
contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(map));
};
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
}
默认路由覆盖导致限流失效
当spring.cloud.gateway.discovery.locator.enabled=true
时,网关会根据注册中心的服务自动生成默认路由规则,手动配置的路由断言与默认路由规则一致时,会优先使用默认生成的路由规则。例如路由到server-source服务配置为:
server:
port: 8888
spring:
application:
name: server-gateway
cloud:
nacos:
server-addr: localhost:8848
gateway:
discovery:
locator:
enabled: true
routes:
- id: server-source
uri: lb://server-source
predicates:
- Path=/server-source/**
filters:
- StripPrefix=1
此时,http://localhost:8888/server-source/index
的路由会被默认路由接管,配置文件内的这个路由是无效的。由于走了默认路由规则,限流中resourceId也就不是server-source
了,因此限流也就失效了。
Linux上各类组件开机自启
上了一些组件,其中有Zipkin
、Sentinel
、Nacos
,全部装在了虚拟机上,希望每次启动虚拟机的时候能够自启这些组件。
直接加入到/etc/rc.local
文件内启动吧,在文件内添加如下内容:
# nacos开机自启
/usr/local/nacos/bin/startup.sh -m standalone
# zipkin开机自启
nohup /usr/local/java/jdk1.8.0_281/bin/java -jar /usr/local/zipkin/zipkin-server-2.23.2-exec.jar >> /usr/local/zipkin/nohup.out &
# sentinel开机自启
nohup /usr/local/java/jdk1.8.0_281/bin/java -jar /usr/local/sentinel/sentinel-dashboard.jar >> /usr/local/sentinel/nohup.out &
赋予/etc/rc.local
权限:
chmod +x /etc/rc.local
注:/etc/rc.local
文件执行命令的时候似乎不会加载环境,所以上面的java都替换成了绝对路径,在Nacos的startup.sh脚本中也需要替换一下脚本内的JAVA_HOME路径,把顶部一堆JAVA_HOME相关内容替换成这个绝对路径:
[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/local/java/jdk1.8.0_281
[ ! -e "$JAVA_HOME/bin/java" ] && unset JAVA_HOME
重启测试即可
本文由 visionki 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Mar 17, 2021 at 06:33 am