官网文档:https://spring-cloud-alibaba-group.github.io/github-pages/2021/en-us/index.html
Spring Cloud Alibaba是Spring Cloud下的一个子项目,Spring Cloud Alibaba为分布式应用程序开发提供了一站式解决方案,它包含开发分布式应用程序所需的所有组件,使您可以轻松地使用Spring Cloud开发应用程序,使用Spring Cloud Alibaba,您只需要添加一些注解和少量配置即可将Spring Cloud应用程序连接到Alibaba的分布式解决方案,并使用Alibaba中间件构建分布式应用程序系统
Spring Cloud Alibaba 是阿里巴巴开源中间件跟 Spring Cloud 体系的融合:
1、流量控制和服务降级: 使用阿里巴巴Sentinel进行流量控制,断路和系统自适应保护;
2、服务注册和发现: 实例可以在Alibaba Nacos上注册,客户可以使用Spring管理的bean发现实例,通过Spring Cloud Netflix支持Ribbon客户端负载均衡器;
3、分布式配置: 使用阿里巴巴Nacos作为数据存储;
4、事件驱动: 构建与Spring Cloud Stream RocketMQ Binder连接的高度可扩展的事件驱动微服务;
5、消息总线: 使用Spring Cloud Bus RocketMQ链接分布式系统的节点;
6、分布式事务: 支持高性能且易于使用的Seata分布式事务解决方案;
7、Dubbo RPC: 通过Apache Dubbo RPC扩展Spring Cloud服务到服务调用的通信协议;
Nacos是阿里巴巴2018年7月推出来的一个开源项目,是一个更易于构建云原生应用的动态服务注册与发现、配置管理和服务管理平台;(Nacos:纳科斯)
Nacos致力于快速实现动态服务注册与发现、服务配置、服务元数据及流量管理;
Nacos 属于Spring cloud alibaba下的一个组件;
Nacos 约等于 spring cloud eureka(注册中心)+ spring cloud config(配置中心)
Nacos官网:https://nacos.io/zh-cn/docs/quick-start.html
因为Naco的官方文档非常详细切丰富,本文就不做太多介绍
1、下载nacos最新的二进制压缩包;
下载地址:https://github.com/alibaba/nacos/releases
2、解压下载下来的nacos最新的二进制压缩包;
tar -zxvf nacos-server-1.4.1.tar.gz
cd nacos/bin
3、启动nacos server
./startup.sh -m standalone
注:单机环境必须带-m standalone参数启动,否则无法启动,不带参数启动的是集群环境;
4、启动日志:/usr/local/nacos/logs/start.out
5、访问:Nacos Server启动后,到http://ip:8848查看控制台(默认账号名/密码为nacos/nacos):
和Dubbo类似,微服务开发是controller调用controller,调用者是服务消费者,被调用者是服务提供者,服务消费者和服务提供者是相对概念,服务消费者也可以被另一个服务调用,那么此时的服务消费者也是一个服务提供者;
在实际开发中,我们会把所有服务都注册到nacos注册中心上,由nacos去维护和管理我们的所有服务;
通过添加一个starter依赖:spring-cloud-starter-alibaba-nacos-discovery它通过自动配置、注解以及Spring Boot 编程模型与Nacos无缝集成,实现服务注册与发现,nacos经过双十一考验,可以在生产环境中作为大规模分布式系统的服务注册中心;
1、pom.xml 文件,引入Nacos Discovery Starter;
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2、在应用的/src/main/resources/application.properties(也可以是application.yaml) 配置文件中配置 Nacos Server 地址;
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848`
如果不想使用Nacos作为您的服务注册与发现,可以将 spring.cloud.nacos.discovery.enabled 设置为 false;
3、使用 @EnableDiscoveryClient 注解开启服务注册与发现功能;
@SpringBootApplication
@EnableDiscoveryClient
public class NacosProviderDemoApplication {
public static void main(String[] args) {
SpringApplication.run(NacosProviderDemoApplication.class, args);
}
@RestController
public class EchoController {
@GetMapping(value = "/echo/{string}")
public String echo(@PathVariable String string) {
return "Hello Nacos Discovery " + string;
}
}
}
消费者应用比提供者应用要稍微复杂一点,因为在消费端需要去调用提供者提供的REST 服务,此时需要用到RestTemplate、Feign及负载均衡Ribbon,
@SpringBootApplication
@EnableDiscoveryClient
public class NacosConsumerApp {
@RestController
public class NacosController{
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;
@Value("${spring.application.name}")
private String appName;
@GetMapping("/echo/app-name")
public String echoAppName(){
//Access through the combination of LoadBalanceClient and RestTemplate
ServiceInstance serviceInstance = loadBalancerClient.choose("nacos-provider");
String path = String.format("http://%s:%s/echo/%s",serviceInstance.getHost(),serviceInstance.getPort(),appName);
System.out.println("request path:" +path);
return restTemplate.getForObject(path,String.class);
}
}
//Instantiate RestTemplate Instance
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(NacosConsumerApp.class,args);
}
}
在这个例子中,我们注入了一个 LoadBalancerClient 实例,并手动实例化了一个 RestTemplate。同时,我们将 的配置值注入spring.application.name到应用程序中,以便在调用提供者的服务时可以显示当前的应用程序名称。
地址:http://127.0.0.1:8082/echo/app-name
访问结果: Hello Nacos Discovery nacos-consumer
每一个采用spring-cloud-starter-alibaba-nacos-discovery实现的服务都提供了一个EndPoint,EndPoint的访问地址为
http://ip:port/actuator/nacos-discovery
EndPoint主要提供了两类信息:
Nacos提供用于存储配置和其他元数据功能,为分布式系统中的外部化配置提供服务器端和客户端支持,使用Spring Cloud Alibaba Nacos Config就可以在Nacos Server集中管理Spring Cloud应用的外部属性配置;
Spring Cloud Alibaba Nacos config是在启动的bootstrap阶段,将配置加载到Spring环境中;
Spring Cloud Alibaba Nacos Config使用DataId和GROUP确定一个配置;
启动好Nacos之后,在Nacos添加如下的配置:
Data ID: nacos-config.properties
Group : DEFAULT_GROUP
如果要在项目中使用Nacos来实现应用的外部化配置,需要添加如下依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
Nacos Config Starter 默认为所有获取数据成功的 Nacos 的配置项添加了监听功能,在监听到服务端配置发生变化时会实时触发 org.springframework.cloud.context.refresh.ContextRefresher的refresh 方法;
可以通过配置 spring.cloud.nacos.config.refresh.enabled=false 来关闭动态刷新;
yaml格式
Nacos Config 除了支持.properties格式以外,也支持yaml格式,这个时候只需要完成以下两步:
1、在应用的bootstrap.properties配置文件中显式地声明DataId文件扩展名;bootstrap.properties文件配置如下:
spring.application.name=nacos-config
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.file-extension=yaml
2、在Nacos的web管控台新增一个DataId为yaml扩展名的配置,如下所示:
Data ID: nacos-config.yaml
Group : DEFAULT_GROUP
配置格式: YAML
配置内容: user.name: zhangcuishan
user.age: 35
3、动态刷新配置
@SpringBootApplication
public class NacosConfigApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(NacosConfigApplication.class, args);
while(true) {
//When configurations are refreshed dynamically, they will be updated in the Enviroment, therefore here we retrieve configurations from Environment every other second.
String userName = applicationContext.getEnvironment().getProperty("user.name");
String userAge = applicationContext.getEnvironment().getProperty("user.age");
System.err.println("user name :" + userName + "; age: " + userAge);
TimeUnit.SECONDS.sleep(1);
}
}
}
当 user.age 改变时,可以从应用程序中检索到最新的值
基于profile粒度的多环境配置
spring-cloud-starter-alibaba-nacos-config 在加载配置的时候,不仅仅加载了以 dataid 为 ${spring.application.name}.${file-extension:properties}
为的基础配置,还加载了dataid为
${spring.application.name}-${profile}.${file-extension:properties}
的基础配置;
在日常开发中如果遇到多套环境下的不同配置,可以通过Spring提供的 ${spring.profiles.active}
配置项来激活使用某个配置文件;
spring.profiles.active=dev
${spring.profiles.active}当通过配置文件来指定时必须放在 bootstrap.properties文件中;
比如在Nacos上新增一个dataid为:nacos-config-dev.yaml
的基础配置,如下所示:
Data ID: nacos-config-deve.yaml
Group : DEFAULT_GROUP
配置格式: YAML
配置内容: current.env: dev环境
启动 Spring Boot 应用测试;
如果需要切换到生产环境,只需要更改 ${spring.profiles.active} 参数配置即可,如下所示:
spring.profiles.active=proc
这里面涉及到三个概念
(1)命名空间 (java package: com.bjpowernode.service / controller)
用于配置隔离,不同命名空间下,可以存在相同的Group或Data ID配置,Namespace的常用场景之一是不同环境的配置进行区分隔离,例如开发环境、测试环境和生产环境的资源(如配置、服务)隔离等;
(2)Group
Nacos中的一组配置集合,是组织配置的维度之一,通过一个有意义的字符串(如 Buy 或 Trade)对一组配置集合进行分组,从而区分Data ID相同的配置集合,当在 Nacos 上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用 DEFAULT_GROUP,配置分组的常见场景:不同的应用或组件使用了相同的配置类型,如 database_url配置和MQ_topic配置;
(3)Data Id
Nacos中的某个配置集合的ID,配置集合ID是组织划分配置的维度之一,Data ID通常用于组织划分系统的配置集合,一个系统或者应用可以包含多个配置集合,每个配置集都可以被一个有意义的名称标识;
默认命名空间(public) + 默认Group分组(DEFAULT_GROUP) + 自定义Data Id(没有默认值);
默认命名空间:public
默认Group:DEFAULT_GROUP
自定义Data Id:
${spring.application.name}-${profile}.${file-extension:properties}
比如:nacos-config-dev.yaml
默认命名空间 + 自定义Group分组 + 自定义的Data Id(没有默认值);
默认命名空间:public
默认Group:MY_GROUP
自定义Data Id:
${spring.application.name}-${profile}.${file-extension:properties}
比如:nacos-config-dev.yaml
自定义命名空间 + 自定义Group分组 + 自定义的Data Id(没有默认值);
默认命名空间:public
默认Group:MY_GROUP
自定义Data Id:
${spring.application.name}-${profile}.${file-extension:properties}
比如:nacos-config-dev.yaml
Nacos默认情况下是采用apache derby内嵌数据库进行数据存储,在单机模式时可以使用nacos嵌入式数据库实现数据存储,但是derby数据库不方便观察数据存储的基本情况,从nacos 0.7版本开始增加了支持mysql数据源能力;
具体操作步骤:
第一步:安装数据库,版本要求:5.6.5+;
第二步:初始化MySQL数据库,数据库初始化文件: nacos-mysql.sql,该文件可以在Nacos程序包下的 conf目录下获得;
第三步:修改 conf/application.properties文件,增加支持MySQL数据源配置,添加(目前只支持mysql)数据源的url、用户名和密码;
然后启动nacos(还是单机启动),此时发现nacos所有写嵌入式数据库的数据都写到了mysql;
#*************** Config Module Related Configurations ***************#
### If use MySQL as datasource:
spring.datasource.platform=mysql
### Count of DB:
db.num=1
### Connect URL of DB:
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user=root
db.password=123456
具体配置步骤:
1、准备三个nacos,3个或3个以上Nacos节点才能构成集群;
2、在Nacos的conf目录下有一个cluster.conf.example,可以直接把example扩展名去掉来使用,也可以单独创建一个cluster.conf文件,然后在该文件中每行配置一个ip:port;
127.0.0.1:8801
127.0.0.1.:8802
127.0.0.1.:8803
3、按照上面nacos持久化的方式配置好数据持久化到MySQL,生产使用建议至少主备模式,或者采用高可用数据库;
4、启动测试;
集群下客户端怎么连?
第一种:可以在单机的基础上加多个IP和端口中间用逗号隔开;
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8801,127.0.0.1:8802,1127.0.0.1:8803
第二种:配合Nginx代理我们的Nacos集群,配置里就直接写Nginx的IP和端口即可;
Nacos集群节点有三种角色状态:leader、follower、candidate;
当leader宕机,会从剩下的follower中投票选举出一个新的leader,选举算法是基于Raft算法实现;
经测试,发现有一点与三个角色不符,部署3个nacos节点,其中宕机2台,只剩下一个节点,此节点将变为candidate角色,但是此时该nacos集群仍然可以注册服务,订阅服务,(按照正确的理论应该是:如果nacos集群中没有leader角色的节点就不能注册服务,因为leader角色处理事务性请求),这比较匪夷所思,有待研究;
Consistency(一致性)、
Availability(可用性)、
Partition tolerance(分区容错性),三者不可得兼。
可以看一下我的另外一篇博客,关于CAP的
Nacos支持AP与CP模式的切换。
首先nacos保证了P,官方推荐使用A,即AP,保证其高可用
C:是所有节点在同一时间看到的数据是一致的
A:所有的请求都会得到响应
CP与AP的适用场景
CP: 如果需要在服务级别编辑或者存储配置信息的时候,CP就是必须的
CP模式下则支持注册持久化实例,是以Raft协议为集群运行模式,该模式注册实例之前必须先注册服务,如果服务不存在,则会返回错误
AP: 如果不需要存储服务级别信息且服务实例通过nacos-client注册,并能够保持心跳上报,AP模式只支持注册临时实例