文章目录
Nacos安装与启动
首先安装 Nacos 服务,Windows 安装地址:https://github.com/alibaba/nacos/releases
之后进入 bin
目录,使用命令行输入:
startup.cmd -m standalone
此时出现下图就代表启动成功
默认端口是 8848,如果需要修改端口,就进入 conf
目录里的 application.properties
文件,修改 server.port
值即可
然后,在浏览器输入http://127.0.0.1:8848/nacos即可进行访问
用户名和密码都是 nacos,登录后页面如下:
快速入门
这里首先创建一个父工程 nacos-demo,之后创建两个服务,分别是 service1 和 service2,其中 service1 需要通过 Feign 调用 service2 的方法(Feign 的使用在上个教程有讲过Eureka原理和应用(结合Feign) )
之后的步骤如下:
1.在父工程中加入如下依赖:
<dependencies>
<!-- nacos客户端依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--Feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--HttpClient-->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
<!-- loadbalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!--spring-cloud管理依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- nacos的管理依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.0.1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
这里需要注意,如果不加 Loadbalancer
的依赖,会导致 Feign 调用时报错,报错的理由是 UnknownHostException
,即找不到对应服务的主机
原因在于,比如 A 服务 调用 B 服务,在 Feign 调用时,A 拿到的是 B 服务的名字 b-service,那么在调用的时候是:http://b-service/xx。这时候会判断 FeignClient 是否设置 url 属性,如果设置了,那么直接使用 url 属性的值进行调用;如果没有,就会使用对应的 LoadBalance api 从对应的注册中心获取服务的实例地址。也就是说当使用服务名调用的时候,负载均衡总需要一个,Ribbon 或 Spring Cloud Loadbalancer。不然就无法将服务名替换成对应的真实服务地址进行调用
而在 Nacos 较新的版本中,是不提供 Ribbon 支持的(因为 Ribbon 目前已经停止维护,Spring Cloud 使用了 LoadBalancer 来 替代 Ribbon),因此我们需要单独引入 LoadBalancer 的 jar 包
2.编写 service1 的配置文件
spring:
cloud:
nacos:
server-addr: localhost:8848 # nacos服务地址
application:
name: service1 # 服务名
server:
port: 8080
3.编写 service2 的配置文件
spring:
cloud:
nacos:
server-addr: localhost:8848 # nacos服务地址
application:
name: service2 # 服务名
server:
port: 8081
4.编写 service2 的控制层
@RestController
@RequestMapping("/service2")
@Slf4j
public class WebController {
@GetMapping("/user")
public String getUser() {
log.info("调用service2方法");
return "张三";
}
}
5.编写 service1 的控制层和 Feign 客户端
@FeignClient("service2")
public interface UserClient {
@GetMapping("/service2/user")
String getUser();
}
@RestController
@RequestMapping("/service1")
@Slf4j
public class WebController {
@Autowired
private UserClient userClient;
@GetMapping("/user")
public String getUser() {
log.info("调用service1方法");
return userClient.getUser();
}
}
6.在 service1 的启动类上加上 @EnableFeignClients
注解
@SpringBootApplication
@EnableFeignClients
public class Service1Application {
public static void main(String[] args) {
SpringApplication.run(Service1Application.class, args);
}
}
7.启动两个服务并进行测试
首先进入控制台,可以看到两个服务均已启动
然后使用 Postman 向 service1 发送请求,可以看到发送成功
服务分级存储模型
一个服务对应多个实例,而同在一个地域的多个实例称为一个集群,因此 Nacos 的服务分级存储模型中,第一级是服务,再往下就是集群和实例
Nacos 引入集群概念的目的是为了防止跨集群调用的问题,因为服务调用尽可能选择本地集群的服务,而跨集群调用延迟较高。只有本地集群不可访问时,才去访问其它集群
配置实例集群属性的方法:
修改application.yml,添加如下内容:
spring:
cloud:
nacos:
server-addr: localhost:8848 # nacos服务地址
discovery:
cluster-name: SZ # 集群名称
在控制台中,可以看到服务对应的集群,如下所示
Nacos 默认的负载均衡规则是 RoundRobinLoadBalancer(轮询)
环境隔离
Nacos 中服务存储和数据存储的最外层都是 namespace(命名空间)。namespace 中可以分组,成为 group,而 group 就是具体的服务或数据
新建 namespace 的方式:
1.在控制台创建 namespace,用来隔离不同环境
2.填写一个新的命名空间信息
3.保存后即可在控制台中看到该命名空间,这里需要注意其 id
4.修改 service1 配置文件中的 application.yml,添加 namespace
spring:
cloud:
nacos:
server-addr: localhost:8848 # nacos服务地址
discovery:
cluster-name: SZ # 集群名
namespace: 35154e51-4b73-4f80-bbb3-fc79b7b51de9 # 命名空间的ID
application:
name: service1 # 服务名
server:
port: 8080
5.启动 service1 实例,进行测试
此时会发现 service1 无法访问 service2 的接口,原因在于,不同的 namespace 之间的服务互相不可见
Nacos原理
与 Eureka 不同的是,在健康监测中,Nacos 将服务提供者分成临时实例和非临时实例(默认是临时实例)。对于临时实例来说,和 Eureka 一样,采用心跳监测的方式进行健康监测,若服务超时没发送心跳会被注册中心直接剔除。对于非临时实例来说,Nacos 不要求做心跳监测,而是 Nacos 主动发请求询问服务是否还正常,若非临时实例不正常,Nacos 不会将其剔除,而是仅仅标记其为不健康的状态,并等待其恢复健康
其次,若 Nacos 发现有服务挂了,会立即推送给消费者,告诉消费者服务变更了。这样的好处是可以避免服务在消费者定时拉取服务的间隔期间挂掉了,导致消费者未能及时更新服务列表,而去访问了一个挂了的服务器。因此 Nacos 采用的方式是 pull + push 两者结合,而 Eureka 采用的只有 pull
设置为非临时实例的方式:
服务注册到 Nacos 时,可以选择注册为临时或非临时实例,通过下面的配置来设置:
spring:
cloud:
nacos:
discovery:
ephemeral: false # 设置为非临时实例
此时重新启动可以看到,临时实例这一列的值为 false
总结:
Nacos与Eureka的共同点:
① 都支持服务注册和服务拉取
② 都支持服务提供者心跳方式做健康检测
Nacos与Eureka的区别:
① Nacos 支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式
② 临时实例心跳不正常会被剔除,非临时实例则不会被剔除
③ Nacos 支持服务列表变更的消息推送模式,服务列表更新更及时
④ Nacos 集群默认采用 AP(可用性 + 分区容错性) 方式,当集群中存在非临时实例时,采用 CP(一致性 + 分区容错性) 模式;Eureka采用 AP 方式