一、Spring Cloud Alibaba
1、简介
Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。
主要功能
服务限流降级 :默认支持 WebServlet、WebFlux, OpenFeign、RestTemplate、Spring Cloud Gateway, Zuul, Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。
服务注册与发现 :适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。
分布式配置管理 :支持分布式系统中的外部化配置,配置更改时自动刷新。
消息驱动能力 :基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。
分布式事务 :使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。
阿里云对象存储 :阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。
分布式任务调度 :提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker(schedulerx-client)上执行。
阿里云短信服务 :覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。
组件
[Sentinel] :阿里巴巴源产品,把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
[Nacos] :一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
[RocketMQ] :一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。
[Dubbo] :Apache Dubbo™ 是一款高性能 Java RPC 框架。
[Seata] :阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。
[Alibaba Cloud OSS] : 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
[Alibaba Cloud SchedulerX]: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。
[Alibaba Cloud SMS] : 覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。
二、Nacos介绍
Nacos(Naming Configuration Service) 是一个易于使用的动态服务发现、配置和服务管理平台,用于构建云原生应用程序。
服务发现是微服务架构中的关键组件之一
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
1、什么是Nacos?
1. Nacos = 注册中心+配置中心组合
2. Nacos支持几乎所有主流类型的“服务”的发现、配置和管理,常见的服务如下:
Kubernetes Service
gRPC & Dubbo RPC Service
Spring Cloud RESTful Service
3、为何使用Nacos?
为何使用注册中心呢?我们以入住酒店的前台为例子,稍微加以解释。先设想一个没有服务前台的酒店,客人入住需要自己寻找合适居住的房间,客人不知道每个房间的情况,无法确定那个房间是打扫干净可以入住,客人只能逐个房间寻找,如果遇到已经居住房客的房间一定很尴尬,显然这是不正常的情况。正常的情况是酒店会安排服务台,酒店打扫干净可以入住的房间会登记注册到服务台,这样客人来住店,只需要在前台就可以查找到可以入住的房间,这样就无需等待快速的入住。显然,服务器提供发注册和发现机制可以让房客快速找到合适的房间,快速解决入住问题。
采用微服务以后,软件微服务组件各自独立,但最终还要组合为一个整体作为一个软件系统服务于最终客户,这时软件组件之间也需要彼此通讯,彼此调用方法。微服务架构内部发起通讯调用方法的一方成为“服务消费者”,提供远程方法调用的服务器称为“服务提供者”,往往为了提高系统性能,会提供多个服务器作为服务提供者,此时服务消费者找到服务提供者的过程,就类似于用户在找房间的过程。为了帮助服务消费者快速的发现服务提供者,在微服务框架中都会引入**注册中心。注册中心类似于酒店的前台,提供在软件服务的注册和发现功能,服务提供者会先在注册中心进行注册,声明可以对外提供服务,而服务消费者只需要在注册中心就可以快速发现找到可以使用的服务,快速使用服务。注册中心实现了服务提供和服务消费的快速撮合功能。
2、Nacos下载和安装
4.1、启动
可以查看官网手册安装启动等。
1、解压后找到bin目录
2、执行指令:
Linux/Unix/Mac
启动命令(standalone代表着单机模式运行,非集群模式):
sh startup.sh -m standalone
如果您使用的是ubuntu系统,或者运行脚本报错提示[[符号找不到,可尝试如下运行:
bash startup.sh -m standalone
Windows
启动命令(standalone代表着单机模式运行,非集群模式):
startup.cmd -m standalone
默认账号密码是:nacos/nacos
http://127.0.0.1:8848/nacos/#/login
5、Nacos代替Eureka
Nacos可以直接提供注册中心(Eureka)+配置中心(Config),所以它的好处显而易见,我们在上节课成功安装和启动了Nacos以后就可以发现Nacos本身就是一个小平台,它要比之前的Eureka更加方便,不需要我们在自己做配置。
三、Nacos之服务注册中心
1、Nacos服务注册中心
服务发现是微服务架构中的关键组件之一。在这样的架构中,手动为每个客户端配置服务列表可能是一项艰巨的任务,并且使得动态扩展极其困难。Nacos Discovery 帮助您自动将您的服务注册到 Nacos 服务器,Nacos 服务器会跟踪服务并动态刷新服务列表。此外,Nacos Discovery 将服务实例的一些元数据,如主机、端口、健康检查 URL、主页等注册到 Nacos。
spring-cloud-alibaba官网
点击 Reference Doc.
如何引入Nacos Discovery进行服务注册/发现
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
1、application.properties
server.port=8070
spring.application.name=service-provider
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
通过 Spring Cloud 原生注解 @EnableDiscoveryClient 开启服务注册发现功能:
@SpringBootApplication
@EnableDiscoveryClient
public class NacosProviderApplication {
public static void main(String[] args) {
SpringApplication.run(NacosProviderApplication.class, args);
}
@RestController
class EchoController {
@RequestMapping(value = "/echo/{string}", method = RequestMethod.GET)
public String echo(@PathVariable String string) {
return "Hello Nacos Discovery " + string;
}
}
}
2、配置服务消费者,从而服务消费者可以通过 Nacos 的服务注册发现功能从 Nacos server 上获取到它要调用的服务。
application.properties
server.port=8080
spring.application.name=service-consumer
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
通过 Spring Cloud 原生注解 @EnableDiscoveryClient 开启服务注册发现功能。给 RestTemplate 实例添加 @LoadBalanced 注解,开启 @LoadBalanced 与 Ribbon 的集成:
@SpringBootApplication
@EnableDiscoveryClient
public class NacosConsumerApplication {
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(NacosConsumerApplication.class, args);
}
@RestController
public class TestController {
private final RestTemplate restTemplate;
@Autowired
public TestController(RestTemplate restTemplate) {this.restTemplate = restTemplate;}
@RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
public String echo(@PathVariable String str) {
return restTemplate.getForObject("http://service-provider/echo/" + str, String.class);
}
}
}
启动 ProviderApplication 和 ConsumerApplication ,调用 http://localhost:8080/echo/2018,返回内容为 Hello Nacos Discovery 2018。
注意:要先启动Nacos,然后再来启动服务
2、远程调用与Ribbon
1、什么是Ribbon
它是一个基于HTTP和TCP客户端负载均衡器。它虽然只是一个工具类库,它却是每一个微服务的基础设施。因为实际上,对于服务间调用、API网关请求转发都需要经过Ribbon负载均衡来实现。总体来说,Ribbon的主要作用是:从注册服务器端拿到对应服务列表后以负载均衡的方式访问对应服务。
要注意的是Nacos已经整合了Ribbon,所以我们想要使用只需要导入Spring Cloud Alibaba Nacos的依赖就可以直接使用了。
2、具体使用
现在如果我们需要远程访问那么可以使用RestTemplate,其中getForObject是最常用方法,同时还要在服务消费者中配置RestTemplate:
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
restTemplate.getForObject(arg1,arg2,arg3...);
第一个参数url表示被调用的目标Rest接口位置
1. url的第一部分是在Nacos中注册的服务提供者名称,如果多个服务提供者注册相同名称,
Ribbon会自动寻找其中一个服务提供者,并且调用接口方法。这个就是负载均衡功能。
2. url后半部是控制器的请求路径。
第二个参数是返回值类型
1. JavaBean类型或者JavaBean数组类型,如果控制器返回的是List集合,需要使用数组类型接收。
第三个参数是可变参数
1. 是传递给url的动态参数,使用参数时候需要在url上需要使用{1}、{2}、{3}进行参数占位,
这样传递的参数就会自动替换占位符。
验证Nacos自带负载均衡:
重复上面 <<1、Nacos服务注册中心>>创建2个服务提供者9001,9002,服务消费者8001,请求,查看是否自动负载均衡。
总结:因为Nacos中本身就集成了Ribbon所以它本身就自带负载均衡
3、各种服务注册中心对比
服务注册与发现框架 | CAP模型 | 控制台管理 | 社区活跃度 |
Eureka | AP | 支持 | 低(2.x版本闭源) |
Zookeeper | CP | 不支持 | 中 |
Consul | CP | 支持 | 高 |
Nacos | AP/CP | 支持 | 高 |
CAP模型
计算机专家 埃里克·布鲁尔(Eric Brewer)于 2000 年在 ACM 分布式计算机原理专题讨论会(简称:PODC)中提出的分布式系统设计要考虑的三个核心要素:
- 一致性(Consistency):同一时刻的同一请求的实例返回的结果相同,所有的数据要求具有强一致性(Strong Consistency)
- 可用性(Availability):所有实例的读写请求在一定时间内可以得到正确的响应
- 分区容错性(Partition tolerance):在网络异常(光缆断裂、设备故障、宕机)的情况下,系统仍能提供正常的服务
以上三个特点就是CAP原则(又称CAP定理),但是三个特性不可能同时满足,所以分布式系统设计要考虑的是在满足P(分区容错性)的前提下选择C(一致性)还是A(可用性),即:CP或AP。
CP原则:一致性 + 分区容错性原则
CP 原则属于强一致性原则,要求所有节点可以查询的数据随时都要保持一直(同步中的数据不可查询),即:若干个节点形成一个逻辑的共享区域,某一个节点更新的数据都会立即同步到其他数据节点之中,当数据同步完成后才能返回成功的结果,但是在实际的运行过程中网络故障在所难免,如果此时若干个服务节点之间无法通讯时就会出现错误,从而牺牲了以可用性原则(A),例如关系型数据库中的事务。
AP原则:可用性原则 + 分区容错性原则
AP原则属于弱一致性原则,在集群中只要有存活的节点那么所发送来的所有请求都可以得到正确的响应,在进行数据同步处理操作中即便某些节点没有成功的实现数据同步也返回成功,这样就牺牲一致性原则(C 原则)。
使用场景:对于数据的同步一定会发出指令,但是最终的节点是否真的实现了同步,并不保证,可是却可以及时的得到数据更新成功的响应,可以应用在网络环境不是很好的场景中。
Nacos支持CP和AP
Nacos无缝支持一些主流的开源生态,同时再阿里进行Nacos设计的时候重复的考虑到了市场化的运作(市面上大多都是以单一的实现形式为主,例如:Zookeeper使用的是 CP、而 Eureka采用的是AP),在Nacos中提供了两种模式的动态切换。
Nacos 何时选择切换模式
- 1. 一般来说,如果不需要储存服务界别的信息且服务实例通过nacos-client注册,并能够保持心跳上报,那么就可以选择AP模式。如Spring Cloud 和 Dubbo,都适用于AP模式,AP模式为了服务的可用性减弱了一致性,因此AP模式下只支持注册临时实例。
- 2. 如果需要在服务级别编辑或者储存配置信息,那么CP是必须的,K8S服务和DNS服务则是用于CP模式。CP模式下则支持注册持久化实例,此时则是以Raft协议为集群运行模式,该模式下注册实例之前必须先注册服务,如果服务不存在,则会返回错误。
切换命令(默认是AP):
curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'
注意:临时和持久化的区别主要在健康检查失败后的表现,持久化实例健康检查失败后会被标记成不健康,而临时实例会直接从列表中被删除。
四、Nacos之服务配置中心
Nacos不仅仅可以作为注册中心来使用,同时它支持作为配置中心
1、添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2、YML配置
要注意的是这里我们要配置两个,因为Nacos同SpringCloud-config一样,在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置之后,才能保证项目的正常启动。
springboot中配置文件的加载是存在优先级顺序的,bootstrap优先级高于application
分别要配置的是,这里bootstrap.yml配置好了以后,作用是两个,第一个让服务注册到Nacos中,第二个作用就是去Nacos中去读取指定后缀为yaml的配置文件:
bootstrap.yml
# nacos配置
server:
port: 8085
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
config:
server-addr: localhost:8848 #Nacos作为配置中心地址
file-extension: yaml #指定yaml格式的配置
application.yml
spring:
profiles:
active: dev # 表示开发环境
业务类
这里的@RefreshScope实现配置自动更新,意思为如果想要使配置文件中的配置修改后不用重启项目即生效,可以使用@RefreshScope配置来实现
@RestController
@RequestMapping("/config")
@RefreshScope //实现Nacos配置自动更新
public class ConfigController {
@Value("${useLocalCache:false}")
private boolean useLocalCache;
@RequestMapping("/get")
public boolean get() {
return useLocalCache;
}
}
3、Nacos配置规则
在 Nacos Spring Cloud 中,dataId 的完整格式如下:Nacos官网说明
${prefix}-${spring.profiles.active}.${file-extension}
- prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置。
- spring.profiles.active 即为当前环境对应的 profile。 注意:当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}
- file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 和 yaml 类型。
# ${spring.application.name}-${spring.profiles.active}.${file-extension}
# nacos-config-client-dev.yaml
# 微服务名称-当前环境-文件格式
五、Nacos命名空间分组和DataID三者关系
1、命名空间(Namespace)
用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
2、配置分组(Group)
Nacos 中的一组配置集,是组织配置的维度之一。通过一个有意义的字符串(如 Buy 或 Trade )对配置集进行分组,从而区分 Data ID 相同的配置集。当您在 Nacos 上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用 DEFAULT_GROUP 。配置分组的常见场景:不同的应用或组件使用了相同的配置类型,如 database_url 配置和 MQ_topic 配置。
3、配置集 ID(Data ID)
Nacos 中的某个配置集的 ID。配置集 ID 是组织划分配置的维度之一。Data ID 通常用于组织划分系统的配置集。一个系统或者应用可以包含多个配置集,每个配置集都可以被一个有意义的名称标识。Data ID 通常采用类 Java 包(如 com.taobao.tc.refund.log.level)的命名规则保证全局唯一性。此命名规则非强制。
配置集:一组相关或者不相关的配置项的集合称为配置集。在系统中,一个配置文件通常就是一个配置集,包含了系统各个方面的配置。例如,一个配置集可能包含了数据源、线程池、日志级别等配置项。
三者关系
这三者的关系类似于Java里面的package名和类名,最外层的Namespace是可以用于区分部署环境的,Group和DataID逻辑上区分两个目标对象。
默认情况
Namespace=public,Group=DEFAULT_GROUP,默认Cluster是DEFAULT
具体情况
Nacos默认的命名空间是public,我们就可以利用Namespace来实现隔离,比如我们现在有三个环境:开发、测试、生产环境,我们就可以创建三个Namespace,不同的Namespace之间是隔离的。
Group本身就是分组的意思,它可以把不同的微服务划分到同一个分组里面去。
剩下的就是具体微服务,一个Service可以包含多个Cluster,Nacos默认Cluster是DEFAULT,Cluster是对指定微服务的一个虚拟划分。比如说,将一个Service部署在北京和和杭州的机房中,北京机房的Service就可以起名为(BJ),杭州机房中的Service就可以起名为(HZ),这样就可以尽量让同一个机房的微服务互相调用,提升性能。
4、切换不同环境
1、DataID方案
1. 指定spring.profile.active和配置文件的DataID来使不同环境下读取不同的配置,配置规则:默认空间+新建dev和test两个DataId:
2.通过spring.profile.active属性就能进行多环境下配置文件的读取
spring:
profiles:
# active: dev #表示开发环境
active: test #表示测试环境
2、Group方案
根据之前的讲解我们都知道Group为分组默认是:DEFAULT_GROUP,所以现在我们就需要分出两组,一组是“Dev开发组”,一组是“test测试组”
1. 新建Group
DEV_GROUP
TEST_GROUP
2. 完成以上配置以后,接下来就需要通过bootstrap+application来配合完成,具体方式:在config下增加一条Group的配置即可,可以配置为DEV_GROUP或TEST_GROUP
# nacos配置
server:
port: 8001
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
config:
server-addr: localhost:8848 #Nacos作为配置中心地址
file-extension: yaml #指定yaml格式的配置
group: TEST_GROUP #增加分组
3、Namespace空间方案
Namespace(命名空间)方案,默认此方案为public,此方案不能删除,我们现在来新建两个命名空间方案
1. 新建dev/test的Namespace
# nacos配置
server:
port: 8001
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
config:
server-addr: localhost:8848 #Nacos作为配置中心地址
file-extension: yaml #指定yaml格式的配置
group: TEST_GROUP #增加分组
namespace: 4ba4bf0e-210c-41ce-954c-23538de1dcbc #指定命名空间
六、Nacos部署模式
Nacos部署环境
单机模式支持mysql
在0.7版本之前,在单机模式时nacos使用嵌入式数据库实现数据的存储,不方便观察数据存储的基本情况。0.7版本增加了支持mysql数据源能力,具体的操作步骤:
- 1.安装数据库,版本要求:5.6.5+
- 2.初始化mysql数据库,数据库初始化文件:mysql-schema.sql
- 3.修改conf/application.properties文件,增加支持mysql数据源配置(目前只支持mysql),添加mysql数据源的url、用户名和密码。
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://11.162.196.16:3306/nacos_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&serverTimezone=UTC
db.user=root
db.password=123456
注意:这里需要注意几个点,一个是url地址需要改,另外数据库的用户和密码也需要更改,同时还有一个是官网上在db.url.0=jdbc:mysql这个属性上少了一个属性为serverTimezone=UTC需要我们手动添加
在Linux系统中解压此文件,并且把其中nacos目录拷贝到nacos目录中
tar -zxvf nacos-server-x.x.x.tar.gz
cd nacos/bin
配置集群配置文件
在nacos的解压目录nacos/的conf目录下,有配置文件cluster.conf,请每行配置成ip:port。(请配置3个或3个以上节点)
# ip:port
200.8.9.16:8848
200.8.9.17:8848
200.8.9.18:8848
启动服务器
Linux/Unix/Mac
Stand-alone mode
sh startup.sh -m standalone
集群模式
使用内置数据源
sh startup.sh -p embedded
使用外置数据源
sh startup.sh
// 关闭防火墙服务-但是开启还会自动启动
systemctl stop firewalld
// 彻底关闭-开机不会启动防火墙
systemctl disable firewalld
Nginx配置
修改nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
stream {
upstream nacos {
server 200.8.9.16:8848;
server 200.8.9.17:8848;
server 200.8.9.18:8848;
}
server {
listen 81;
proxy_pass nacos;
}
}
server:
port: 9002
spring:
application:
name: nacos-provider
cloud:
nacos:
discovery:
# server-addr: localhost:8848
# 换成nginx的81端口,做集群
server-addr: http://200.8.9.16:81