第一章
SpringCloudAlibaba
优就业.JAVA教研室
学习目标
- 了解 SpringCloudAlibaba介绍、所包含组件
- 理解Nacos介绍
- 理解Nacos下载及安装
- 理解Nacos服务启动
- 掌握基于Nacos搭建服务注册发现演示
- 掌握基于Nacos搭建配置中心
0.SpringCloudAlibaba 简介
Spring Cloud Alibaba 是阿里巴巴提供的微服务开发一站式解决方案,是阿里巴巴开源中间件与 Spring Cloud 体系的融合。
同 Spring Cloud 一样,Spring Cloud Alibaba 也是一套微服务解决方案,包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。
作为 Spring Cloud 体系下的新实现,Spring Cloud Alibaba 跟官方的组件或其它的第三方实现如 Netflix, Consul,Zookeeper 等对比,具备了更多的功能:
这幅图是 Spring Cloud Alibaba 系列组件,其中包含了阿里开源组件,阿里云商业化组件,以及集成Spring Cloud 组件。
阿里开源组件
Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
RocketMQ:开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。
Dubbo:这个就不用多说了,在国内应用非常广泛的一款高性能 Java RPC 框架。
Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。
Arthas:开源的Java动态追踪工具,基于字节码增强技术,功能非常强大。
1. Nacos概述
官方地址:https://nacos.io/zh-cn/
github地址:https://github.com/alibaba/nacos
1.1. 什么是 Nacos
Nacos 是阿里巴巴推出来的一个新开源项目,这是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
1.2. 为什么是Nacos
常见的注册中心:
- Eureka(原生,2.0遇到性能瓶颈,停止维护)
- Zookeeper(支持,专业的独立产品。例如:dubbo)
- Consul(原生,GO语言开发)
- Nacos
相对于 Spring Cloud Eureka 来说,Nacos 更强大。
Nacos = Spring Cloud Eureka + Spring Cloud Config
Nacos 可以与 Spring, Spring Boot, Spring Cloud 集成,并能代替 Spring Cloud Eureka, Spring Cloud Config。
-
通过 Nacos Server 和 spring-cloud-starter-alibaba-nacos-config 实现配置的动态变更。
-
通过 Nacos Server 和 spring-cloud-starter-alibaba-nacos-discovery 实现服务的注册与发现。
1.3. 可以干什么
Nacos是以服务为主要服务对象的中间件,Nacos支持所有主流的服务发现、配置和管理。
Nacos主要提供以下四大功能:
- 服务发现和服务健康监测
- 动态配置服务
- 动态DNS服务
- 服务及其元数据管理
2. Nacos快速开始
结构图:
Nacos 依赖 Java 环境来运行。如果您是从代码开始构建并运行Nacos,还需要为此配置 Maven环境,请确保是在以下版本环境中安装使用:
- 64 bit OS,支持 Linux/Unix/Mac/Windows,推荐选用 Linux/Unix/Mac。
- 64 bit JDK 1.8+
- Maven 3.2.x+
2.1. 下载及安装
你可以通过源码和发行包两种方式来获取 Nacos。
您可以从 最新稳定版本 下载 nacos-server-$version.zip
包。
unzip nacos-server-$version.zip 或者 tar -xvf nacos-server-$version.tar.gz
cd nacos/bin
2.2. 启动nacos服务
Linux/Unix/Mac
启动命令(standalone代表着单机模式运行,非集群模式):
sh startup.sh -m standalone
Windows
启动命令:
startup.cmd -m standalone
或者双击startup.cmd运行文件。(可能报异常 建议执行命令)
访问:http://localhost:8848/nacos
用户名密码:nacos/nacos
出现naocs不能正常使用解决办法:
检测nacos状态:http://localhost:8848/nacos/v1/ns/instance
如果提示:server is DOWN now, please try again later!
解决办法:(1)、停止naocos (2)、删除naocs安装程序,data目录下的protocol文件夹,重启服务即可
2.3. 注册中心
首先创建两个工程:nacos-provider、nacos-consumer
创建生产者:
创建消费者:
然后,一路下一步或者ok。效果如下:
2.3.1. 生产者基本代码
ProviderController代码如下:
@RestController
public class ProviderController {
@Value("${myName}")
private String name;
@GetMapping("hello")
public String hello(){
return "hello " + name;
}
}
application.yml配置如下:
server:
port: 18070
myName: nacos
2.3.2. 生产者注册到nacos
生产者注册到nacos注册中心,步骤:
-
添加依赖:spring-cloud-starter-alibaba-nacos-discovery及springCloud
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.7.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <!-- SpringCloud的依赖 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR2</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.0.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
-
在 application.yml 中配置nacos服务地址和应用名
myName: nacos server: port: 18070 spring: application: name: nacos-provider cloud: nacos: discovery: server-addr: 192.168.188.138:8848
-
通过Spring Cloud原生注解
@EnableDiscoveryClient
开启服务注册发现功能@SpringBootApplication @EnableDiscoveryClient public class NacosProviderApplication { public static void main(String[] args) { SpringApplication.run(NacosProviderApplication.class, args); } }
效果:
2.3.3. 消费端基本代码
ConsumerController代码:
@RestController
public class ConsumerController {
@GetMapping("hi")
public String hi() {
return "hi provider!";
}
}
application.yml:
server:
port: 18080
2.3.4. 消费者注册到nacos
消费者注册到nacos跟生产者差不多,也分3步:
-
添加依赖:同生产者
-
在application.yml中配置nacos的服务名及服务地址:同生产者
-
在引导类(NacosConsumerApplication.java)中添加@EnableDiscoveryClient注解:同生产者
效果:
2.3.5. 使用feign调用服务
以前我们使用feign来远程调用,这里也一样。引入feign的依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
在NacosConsumerApplication类上添加@EnableFeignClients注解:
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class NacosConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(NacosConsumerApplication.class, args);
}
}
编写feignClient:
内容:
@FeignClient("nacos-provider")
public interface ProviderFeign {
@RequestMapping("hello")
public String hello();
}
在Controller中使用feignClient:
@RestController
public class ConsumerController {
@Autowired
private ProviderFeign providerFeign;
@GetMapping("hi")
public String hi() {
System.out.println(System.currentTimeMillis());
return this.providerFeign.hello();
}
}
测试访问:http://localhost:18080/hi
2.4. 配置中心
在系统开发过程中,开发者通常会将一些需要变更的参数、变量等从代码中分离出来独立管理,以独立的配置文件的形式存在。目的是让静态的系统工件或者交付物(如 WAR,JAR 包等)更好地和实际的物理运行环境进行适配。配置管理一般包含在系统部署的过程中,由系统管理员或者运维人员完成。配置变更是调整系统运行时的行为的有效手段。
如果微服务架构中没有使用统一配置中心时,所存在的问题:
- 配置文件分散在各个项目里,不方便维护
- 配置内容安全与权限
- 更新配置后,项目需要重启
nacos配置中心:系统配置的集中管理(编辑、存储、分发)、动态更新不重启、回滚配置(变更管理、历史版本管理、变更审计)等所有与配置相关的活动。
案例:改造生产者中的动态配置项,由配置中心统一管理。
2.4.1. nacos中创建统一配置
-
dataId
的完整格式如下:${prefix}-${spring.profile.active}.${file-extension}
prefix
默认为所属工程配置spring.application.name
的值(即:nacos-provider),也可以通过配置项spring.cloud.nacos.config.prefix
来配置。spring.profile.active
即为当前环境对应的 profile,详情可以参考 Spring Boot文档。 注意:当 spring.profile.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成${prefix}.${file-extension}
file-exetension
为配置内容的数据格式,可以通过配置项spring.cloud.nacos.config.file-extension
来配置。目前只支持properties
和yaml
类型。
总结:配置所属工程的spring.application.name的值 + “.” + properties/yml
-
配置内容:
项目中易变的内容。例如:myName
当前案例中,nacos-provider工程的spring.application.name=nacos-provider,没有配置spring.profiles.active。所以这里的dataId填写的是nacos-provider.properties
2.4.2. 从配置中心读取配置
从配置中心读取配置,分以下3步:
-
引入依赖
在生产者中引入依赖:
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>
-
在
bootstrap.yml
中配置 Nacos server 的地址和应用名
spring:
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
application:
name: nacos-provider
说明:之所以需要配置 spring.application.name
,是因为它是构成 Nacos 配置管理 dataId
字段的一部分。
在springboot工程中,bootstrap.yml的加载优先级更高。
-
通过 Spring Cloud 原生注解
@RefreshScope
实现配置自动更新:@RestController @RefreshScope public class ProviderController { @Value("${myName}") private String name; @RequestMapping("hello") public String hello(){ return "hello " + name; } }
测试:http://localhost:18080/hi
2.4.3. 名称空间切换环境
在实际开发中,通常有多套不同的环境(默认只有public),那么这个时候可以根据指定的环境来创建不同的 namespce,例如,开发、测试和生产三个不同的环境,那么使用一套 nacos 集群可以分别建以下三个不同的 namespace。以此来实现多环境的隔离。
切换到配置列表:
可以发现有四个名称空间:public(默认)以及我们自己添加的3个名称空间(prod、dev、test),可以点击查看每个名称空间下的配置文件,当然现在只有public下有一个配置。
默认情况下,项目会到public下找 服务名.properties
文件。
接下来,在dev名称空间中也添加一个nacos-provider.properties配置。这时有两种方式:
- 切换到dev名称空间,添加一个新的配置文件。缺点:每个环境都要重复配置类似的项目
- 直接通过clone方式添加配置,并修改即可。推荐
点击编辑:修改配置内容,以作区分
在服务提供方nacos-provider中切换命名空间,修改bootstrap.yml添加如下配置
spring:
cloud:
nacos:
config:
server-addr: 192.168.188.138:8848
namespace: dd56a978-fb42-45c7-9e3d-31d9fbb35815
namespace的值为:
重启服务提供方服务,在浏览器中访问测试:
2.4.4. 加载多配置文件
偶尔情况下需要加载多个配置文件。假如现在dev名称空间下有三个配置文件:nacos-provider.properties、redis.properties、jdbc.properties。
jdbc.properties:
jdbc.url=xxxxxx
redis.properties:
redis.url=yyyy
nacos-provider.properties默认加载,怎么加载另外两个配置文件?
在bootstrap.yml文件中添加如下配置:
spring:
cloud:
nacos:
config:
server-addr: 192.168.188.138:8848
namespace: dd56a978-fb42-45c7-9e3d-31d9fbb35815
extension-configs[0]:
data-id: redis.properties
refresh: true
extension-configs[1]:
data-id: jdbc.properties
refresh: true
application:
name: nacos-provider
注意老版本:是用ext-config
修改ProviderController使用redis.properties和jdbc.properties配置文件中的参数:
@RestController
@RefreshScope
public class ProviderController {
@Value("${myName}")
private String name;
@Value("${jdbc.url}")
private String jdbcUrl;
@Value("${redis.url}")
private String redisUrl;
@RequestMapping("hello")
public String hello(){
return "hello " + name + ", redis-url=" + redisUrl + ", jdbc-url=" + jdbcUrl;
}
}
测试效果:
问题:
修改一下配置中心中redis.properties中的配置,不重启服务。能否动态加载配置信息
删掉spring.cloud.nacos.config.ext-config[0].refresh=true
,再修改redis.properties中的配置试试
2.4.6. 配置的分组
在实际开发中,除了不同的环境外。不同的微服务或者业务功能,可能有不同的redis及mysql数据库。
区分不同的环境我们使用名称空间(namespace),区分不同的微服务或功能,使用分组(group)。
当然,你也可以反过来使用,名称空间和分组只是为了更好的区分配置,提供的两个维度而已。
新增一个redis.properties,所属分组为provider:
现在开发环境中有两个redis.propertis配置文件,一个是默认分组(DEFAULT_GROUP),一个是provider组
默认情况下从DEFAULT_GROUP分组中读取redis.properties,如果要切换到provider分组下的redis.properties,需要添加如下配置:
# 指定分组
spring:
cloud:
nacos:
config:
server-addr: 192.168.188.138:8848
namespace: dd56a978-fb42-45c7-9e3d-31d9fbb35815
extension-configs[0]:
group: provider
data-id: redis.properties
refresh: true
缺点:
将来每个分组下会有太多的配置文件,不利于维护。
最佳实践:
命名空间区分业务功能,分组区分环境。