Spring Cloud Alibaba 教程 | Nacos 篇
写在前面的话: 本笔记在参考网上视频以及博客的基础上,只做个人学习笔记,如有侵权,请联系删除,谢谢!
1、使用nacos做服务的注册和发现
1、父工程项目pom
<!--只做依赖管理,不引入依赖 -->
<dependencyManagement>
<dependencies>
<!--spring-boot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring-cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring-cloud-alibaba -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2、nacos-provider 工程Pom文件
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--nacos注册中心服务治理-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
YAML文件配置
server:
port: 8081
servlet:
context-path: /nacos-provider
spring:
application:
name: nacos-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848
服务提供类
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/sayHello")
public class HelloController {
@RequestMapping("/test/{name}")
public String sayHello(@PathVariable("name") String name){
return "nihao! " + name;
}
}
3、nacos-consumer pom文件配置
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--注册中心服务治理-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
YAML配置
server:
port: 8082
spring:
application:
name: nacos-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
消费类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
public class NacosConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(NacosConsumerApplication.class,args);
}
/**
* 创建RestTemplate并注入Spring容器
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
/**********************调用服务测试**************/
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("hello")
public class ConsumerController {
@Autowired
public RestTemplate restTemplate;
@RequestMapping("sayHi/{name}")
public String sayHello(@PathVariable("name") String name){
return restTemplate.getForObject("http://nacos-provider/nacos-provider/sayHello/test/" +name, String.class);
}
}
网页端测试:
http://localhost:8082/hello/sayHi/zhngsan
2、使用nacos做配置管理
微服务要拉取nacos中管理的配置,并且与本地的application.yml配置合并,才能完成项目启动。
但如果尚未读取application.yml,又如何得知nacos地址呢?
因此spring引入了一种新的配置文件:bootstrap.yaml文件,会在application.yml之前被读取,流程如下:
在nacos中新建配置
- 在需要抽取配置到nacos中的工程中引入nacos-config依赖配置:
<!--nacos配置管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
-
添加bootstrap.yaml
spring: application: name: nacos-provider # 服务名称 profiles: active: dev #开发环境,这里是dev cloud: nacos: discovery: server-addr: 192.168.192.128:8848 config: server-addr: 192.168.192.128:8848 # Nacos地址 file-extension: yaml # 文件后缀名
使用
${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
作为文件id,来读取配置。即nacos-provider-dev.yaml
3、读取nacos配置
@Value("${pattern.dateformat}")
private String dateFormater;
@RequestMapping("getConfig")
public String getConfig(){
return DateTimeFormatter.ofPattern(dateFormater).format(LocalDateTime.now());
}
2、1配置热更新
上面的步骤简单实现了读取nacos上的配置,还未实现配置的热更新。
要实现配置热更新,可以使用两种方式:
1、在@Value注入的变量所在类上添加注解@RefreshScope:
@RefreshScope
public class HelloController {
@Value("${pattern.dateformat}")
private String dateFormater;
}
2、使用@ConfigurationProperties注解的配置类代替@Value注解。
创建配置类:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "pattern")
public class PaternProperties {
private String dateformat;
public String getDateformat() {
return dateformat;
}
public void setDateformat(String dateformat) {
this.dateformat = dateformat;
}
}
使用nacos配置
@Autowired
private PaternProperties paternProperties;
@RequestMapping("getConfig")
public String getConfig(){
return DateTimeFormatter.ofPattern(paternProperties.getDateformat()).format(LocalDateTime.now());
}
Nacos和Eureka的区别
CAP理论
C一致性,A高可用,P分区容错性
-
eureka只支持AP
-
nacos支持CP和AP两种
nacos是根据配置识别CP或AP模式,
如果注册Nacos的client节点注册时是ephemeral=true即为临时节点,那么Naocs集群对这个client节点效果就是AP,反之则是CP,即不是临时节点
#false为永久实例,true表示临时实例开启,注册为临时实例
spring.cloud.nacos.discovery.ephemeral=true
以上配置本人在实际中没有配置生效,仅供参考。
连接方式
nacos使用的是netty和服务直接进行连接,属于长连接
eureka是使用定时发送和服务进行联系,属于短连接
操作实例方式
nacos:提供了nacos console可视化控制话界面,可以对实例列表进行监听,对实例进行上下线,权重的配置,并且config server提供了对服务实例提供配置中心,且可以对配置进行CRUD,版本管理
eureka:仅提供了实例列表,实例的状态,错误信息,相比于nacos过于简单
自我保护机制
相同点:保护阈值都是个比例,0-1 范围,表示健康的 instance 占全部instance 的比例。
不同点:
1)保护方式不同
Eureka保护方式:当在短时间内,统计续约失败的比例,如果达到一定阈值,则会触发自我保护的机制,在该机制下,Eureka Server不会剔除任何的微服务,等到正常后,再退出自我保护机制。自我保护开关(eureka.server.enable-self-preservation: false)
Nacos保护方式:当域名健康实例 (Instance) 占总服务实例(Instance) 的比例小于阈值时,无论实例 (Instance) 是否健康,都会将这个实例 (Instance) 返回给客户端。这样做虽然损失了一部分流量,但是保证了集群的剩余健康实例 (Instance) 能正常工作。
2)范围不同
Nacos 的阈值是针对某个具体 Service 的,而不是针对所有服务的。但 Eureka的自我保护阈值是针对所有服务的。