文章目录
Nacos
一、概述
Nacos是阿里巴巴2018年7月推出来的一个开源项目,是一个更易于构建云原生应用的动态服务注册与发现、配置管理和服务管理平台;(Nacos:纳科斯)
Nacos致力于快速实现动态服务注册与发现、服务配置、服务元数据及流量管理;
Nacos 属于Spring cloud alibaba下的一个组件;
Nacos 约等于 spring cloud eureka(注册中心)+ spring cloud config(配置中心)
Nacos官网:https://nacos.io/
二、Nacos 运行环境部署
下载地址:https://github.com/alibaba/nacos/releases
在 Linux 环境下解压 nacos 的二进制压缩包
tar -zxvf nacos-server-1.3.1.tar.gz -C /usr/local
cd nacos/bin
启动 nacos sever
# 注:单机环境必须带-m standalone参数启动,否则无法启动,不带参数启动的是集群环境
./startup.sh -m standalone
查看启动日志
tail -f /usr/local/nacos/logs/start.out
访问:http://ip地址:8848/nacos
默认用户名密码:nacos/nacos
三、Spring Cloud Alibaba Nacos Discovery服务注册发现
和Dubbo类似,微服务开发是controller调用controller,调用者是服务消费者,被调用者是服务提供者,服务消费者和服务提供者是相对概念,服务消费者也可以被另一个服务调用,那么此时的服务消费者也是一个服务提供者;
在实际开发中,我们会把所有服务都注册到nacos注册中心上,由nacos去维护和管理我们的所有服务;
通过添加一个starter依赖:spring-cloud-starter-alibaba-nacos-discovery它通过自动配置、注解以及Spring Boot 编程模型与Nacos无缝集成,实现服务注册与发现
3.1实现服务提供者
搭建 nacos-discovery-provider 模块
3.1.1 引入依赖
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.0.RELEASE</spring-boot.version>
<spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
</properties>
<dependencies>
<!--spring boot web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--spring-cloud-alibaba nacos服务注册/发现的依赖-->
<!--格式: spring-cloud-starter-[开源组织机构名字]-[项目模块名字]-->
<!--spring-cloud-starter-alibaba-sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--spring-cloud-alibaba nacos 配置中心的依赖-->
<!--
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</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>
<!--spring-boot-starter-actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- mybatis-spring-boot-starter,该依赖是mybatis官方提供的 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<!-- MySQL的jdbc驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- SkyWalking 对 Logback 的集成 -->
<!-- apm-toolkit-logback-1.x -->
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>8.1.0</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring-cloud-dependencies -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
3.1.2 application.properties 配置文件
server.port=8082
spring.application.name=nacos-discovery-provider
# 连接nacos的注册中心地址
spring.cloud.nacos.discovery.server-addr=192.168.106.128:8848
# 如果不想使用Nacos作为您的服务注册与发现,可以将 spring.cloud.nacos.discovery.enabled 设置为 false;
spring.cloud.nacos.discovery.enabled=true
spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos
# spring boot actuator 功能
management.endpoints.jmx.exposure.include=*
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
3.1.3 启动类
//开启服务注册与发现功能: classpath: META-INF/spring.factories文件
@EnableDiscoveryClient
@SpringBootApplication
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
3.1.4 控制层
@Slf4j
@RestController
public class EchoController {
@GetMapping("/")
public ResponseEntity index() {
log.info("provider /");
return new ResponseEntity("index", HttpStatus.OK);
}
@GetMapping("/test")
public ResponseEntity test() {
log.info("provider /test");
return new ResponseEntity("test", HttpStatus.OK);
}
@GetMapping("/sleep")
public String sleep() {
log.info("provider /sleep");
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "ok";
}
@GetMapping("/echo/{string}")
public String echo(@PathVariable String string) {
log.info("provider /echo/{string}");
return "hello Nacos Discovery " + string;
}
@GetMapping("/divide")
public String divide(@RequestParam Integer a, @RequestParam Integer b) {
log.info("provider /divide");
return String.valueOf(a / b);
}
@GetMapping("/notFound")
public String notFound() {
System.out.println("provider 1 .........");
return "notFound";
}
}
3.2 实现服务消费者
搭建 nacos-discovery-consumer模块
3.2.1 引入依赖
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.0.RELEASE</spring-boot.version>
<spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
</properties>
<dependencies>
<!--spring boot web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- springboot官方依赖: spring-boot-starter-xxx-->
<!-- springboot非官方依赖:xxx-spring-boot-starter-->
<!--springcloud依赖:spring-cloud-starter-xxx -->
<!--spring-cloud-alibaba 服务注册发现-->
<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>
<!--spring-boot-starter-actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--spring-cloud-starter-netflix-ribbon-->
<!--
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
-->
<!--spring-cloud-starter-openfeign-->
<!--<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--依赖统一的commons项目-->
<dependency>
<groupId>com.qes</groupId>
<artifactId>nacos-discovery-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--引入Spring Boot内嵌的Tomcat对JSP的解析包-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<!-- SkyWalking 对 Logback 的集成 -->
<!-- apm-toolkit-logback-1.x -->
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>8.1.0</version>
</dependency>
<!-- SkyWalking 工具类 -->
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-trace</artifactId>
<version>8.1.0</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring-cloud-dependencies -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
3.2.2 application.properties 配置文件
server.port=8083
spring.application.name=nacos-discovery-consumer
# 连接nacos的注册中心地址
spring.cloud.nacos.discovery.server-addr=192.168.106.128:8848
spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos
# spring boot actuator 功能
management.endpoints.jmx.exposure.include=*
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
spring.main.allow-bean-definition-overriding=true
3.2.3 启动类
@EnableFeignClients //开启 feign
@EnableDiscoveryClient //开启服务注册与发现功能
@SpringBootApplication
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
@LoadBalanced //负载均衡
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
3.2.4 控制层
@RestController
public class TestController {
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/echo/{app}")
public String echoAppName(@PathVariable("app") String app){
//使用 LoadBalanceClient 和 RestTemplate 结合的方式来访问
ServiceInstance serviceInstance = loadBalancerClient.choose("nacos-discovery-provider");
// http://192.168.106.128:8082/echo/{app}
String url = String.format("http://%s:%s/echo/%s", serviceInstance.getHost(), serviceInstance.getPort(), app);
System.out.println("request url:"+url);
return restTemplate.getForObject(url, String.class);
}
/*
* 需把启动类的 @LoadBalanced 注释掉才可
*/
@GetMapping("/echo-rest/{str}")
public String rest(@PathVariable String str) {
//restTemplate + @LoadBalanced 实现远程调用
return restTemplate.getForObject("http://nacos-discovery-provider/echo/" + str, String.class);
}
@GetMapping("/services/{service}")
public Object client(@PathVariable String service) {
return discoveryClient.getInstances(service);
}
@GetMapping("/services")
public Object services() {
System.out.println(discoveryClient.description());
System.out.println(discoveryClient.getOrder());
return discoveryClient.getServices();
}
}
3.3 服务EndPoint端点
每一个采用 spring-cloud-starter-alibaba-nacos-discovery
实现的服务都提供了一个EndPoint,EndPoint的访问地址为 http://ip:port/actuator/nacos-discovery
EndPoint主要提供了两类信息:
1、subscribe
: 显示了当前有哪些服务订阅者;
2、NacosDiscoveryProperties
: 显示当前服务实例关于 Nacos 的基础配置;
{
"subscribe": [],
"NacosDiscoveryProperties": {
"serverAddr": "192.168.106.128:8848",
"username": "nacos",
"password": "nacos",
"endpoint": "",
"namespace": "",
"watchDelay": 30000,
"logName": "",
"service": "nacos-discovery-provider",
"weight": 1,
"clusterName": "DEFAULT",
"group": "DEFAULT_GROUP",
"namingLoadCacheAtStart": "false",
"metadata": {
"preserved.register.source": "SPRING_CLOUD"
},
"registerEnabled": true,
"ip": "192.168.0.103",
"networkInterface": "",
"port": 8082,
"secure": false,
"accessKey": "",
"secretKey": "",
"heartBeatInterval": null,
"heartBeatTimeout": null,
"ipDeleteTimeout": null
}
}
四、Spring Cloud Alibaba Nacos Config配置中心
Nacos提供用于存储配置和其他元数据功能,为分布式系统中的外部化配置提供服务器端和客户端支持,使用Spring Cloud Alibaba Nacos Config就可以在Nacos Server集中管理Spring Cloud应用的外部属性配置;
Spring Cloud Alibaba Nacos config是在启动的bootstrap阶段,将配置加载到Spring环境中;
Spring Cloud Alibaba Nacos Config使用DataId和GROUP确定一个配置;
4.1 实现服务配置
搭建 nacos-discovery-spring-cloud-config 模块
4.1.1 引入依赖
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.0.RELEASE</spring-boot.version>
<spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<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>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring-cloud-dependencies -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
4.1.2 bootstrap.properties 配置文件
server.port=8090
spring.application.name=nacos-discovery-config
spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos
spring.cloud.nacos.discovery.server-addr=192.168.106.128:8848
spring.cloud.nacos.config.server-addr=192.168.106.128:8848
spring.cloud.nacos.config.file-extension=properties
spring.cloud.nacos.config.group=DEFAULT_GROUP
4.1.3 启动类
@SpringBootApplication
@EnableDiscoveryClient
public class ConfigApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(ConfigApplication.class,args);
while (true) {
//当动态配置刷新时,会更新到 Enviroment 中,因此此处每隔一秒从 Enviorment 中获取配置
String userName = applicationContext.getEnvironment().getProperty("user.name");
String userAge = applicationContext.getEnvironment().getProperty("user.age");
System.out.println("user name : " + userName + "; age: " + userAge);
//获取当前部署的环境
String currentEnv = applicationContext.getEnvironment().getProperty("current.env");
System.err.println("in [ "+currentEnv+" ] enviroment; "+"user name :" + userName + "; age: " + userAge);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
4.1.4 Nacos添加配置
DataId
是以.properties
为扩展名(默认的文件扩展名方式就是.properties
); 在运行时必须使用
bootstrap.properties
配置文件配置 nacos server地址,同时,spring.application.name
值必须与 Nacos 中配置的 Data Id匹配(除了.properties或者.yaml后缀); DataId默认使用
spring.application.name
配置跟文件扩展名结合(配置格式默认使用.properties),GROUP不配置默认使用DEFAULT_GROUP
;
五、Nacos Config 配置中心动态刷新
Nacos Config Starter 默认为所有获取数据成功的 Nacos 的配置项添加了监听功能,在监听到服务端配置发生变化时会实时触发 org.springframework.cloud.context.refresh.ContextRefresher
的refresh 方法;
可以通过配置 spring.cloud.nacos.config.refresh.enabled=false
来关闭动态刷新;
六、基于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} 参数配置即可
spring.profiles.active=product
${spring.profiles.active}
当通过配置文件来指定时必须放在 bootstrap.properties
文件中;
Nacos 上新增一个 dataid 为:nacos-discovery-config.yaml
的基础配置,如下所示:
Data ID: nacos-discovery-config-dev.yaml
Group : DEFAULT_GROUP
配置格式: YAML
配置内容: current.env: dev-env
taid 为 ${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} 参数配置即可
spring.profiles.active=product
${spring.profiles.active}
当通过配置文件来指定时必须放在 bootstrap.properties
文件中;
Nacos 上新增一个 dataid 为:nacos-discovery-config.yaml
的基础配置,如下所示:
Data ID: nacos-discovery-config-dev.yaml
Group : DEFAULT_GROUP
配置格式: YAML
配置内容: current.env: dev-env