为什么需要服务注册与发现
会出现以下几个问题:
- mafeng-order订单微服务发出Http远程调用时,该如何得知mafeng-user实例的IP和端口呢?
- 在多个mafeng-user实例的情况下,mafeng-order该选择哪个实例进行调用呢?
- mafeng-order如何得知mafeng-user实例状态是否健康?
- Eureka
- Zookeeper
- Consul
- Nacos
Nacos简介
- Nacos作为 服务注册发现 组件,可以替换Spring Cloud应用中传统的服务注册于发现组件,如:
- Eureka、Zookeeper、Consul等,支持服务的健康检查。
- Nacos作为服务配置中心,可以替换Apollo、Spring Cloud Config和Bus。
搭建Nacos单机
WIndow方式启动
- nacos-server-2.1.1.zip
- startup.cmd -m standalone
http://localhost:8848/nacos
账户密码默认为nacos。
Docker方式启动
拉取nacos最新镜像
docker pull nacos/nacos-server:2.0.3
创建容器
docker run --env MODE=standalone --restart=always --name nacos -d -p 8848:8848 - p 9848:9848 -p 9849:9849 nacos/nacos-server:2.0.3
注意: Nacos2.0版本相比1.X新增了gRPC的通信方式,因此需要增加2个端口:9848、9849 Nacos官网 | Nacos 官方社区 | Nacos 下载 | Nacos
端口 | 与主端口的偏移量 | 描述 |
9848 | 1000 | 客户端gRPC请求服务端端口,用于客户端向服务端发起连接和请求 |
9849 | 1001 | 服务端gRPC请求服务端端口,用于服务间同步等 |
访问:http://192.168.66.133:8848/nacos,同window。
服务注册到Nacos单机
mafeng-user和mafeng-order都需要注册到Nacos,步骤相同
导入nacos依赖
因为Nacos 属于 SpringCloudAlibaba 体系的组件,所以要单独锁定 spring - cloud - alibaba-dependencies
在父工程锁定依赖版本:
<properties>
<springcloud.alibaba.version>2.2.9.RELEASE</springcloud.alibaba.version>
</properties>
<!-- nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${springcloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
以上配置加到dependencyManagement 里面
PS:关于SpringCloudAlibaba的与SpringCloud的版本关系说明:
https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E 6%98%8E
在子工程再导入nacos依赖:
<!-- nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
配置yml连接nacos
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.66.133:8848
注意:这里虽然8848端口,但会自动偏移+1000,真正连接的是gRPC端口:9848。
重启服务,查看Nacos客户端
临时实例和持久实例
在服务注册时有一个属性ephemeral 用于描述当前实例在注册时是否以临时实例出现;
- 为true则为临时实例(默认值);
- 为false则为持久实例;
临时实例
- 默认情况,服务实例仅会注册在Nacos内存,不会持久化到Nacos磁盘,其健康检测机制为Client 模式,即Client主动向Server上报其健康状态(类似于推模式);
- 默认心跳间隔为5秒,在15秒内Server未收到Client心跳,则会将其标记为“不健康”状态;在30秒内若收到了Client心跳,则重新恢复“健康”状态,否则该实例将从Server端内存清除。即对于不健康的实例,Server会自动清除;
- Nacos的临时实例 选择采用AP模式 ,采用distro协议实现
持久实例
- 服务实例不仅会注册到Nacos内存,同时也会被持久化到Nacos磁盘,其健康检测机制为Server 模式,即Server会主动去检测Client的健康状态(类似于拉模式);
- 默认每20秒检测一次,健康检测失败后服务实例会被标记为“不健康”状态,但不会被清除,因为其是持久化在磁盘的,其对不健康持久实例的清除,需要专门进行;
- Nacos的持久实例 选择采用CP模式 ,采用raft协议实现
应用场景
- 临时实例:适合于存在突发流量暴增可能的互联网项目,可以实现弹性扩容,正常生产中的环境就 是这样;
- 持久实例:用于保护阈值,比如说服务A有100个实例,那么当有98个不可用时:
- 如果是临时实例,则只会返回两个服务,那么大并发量请求这两个服务肯定会造成雪崩的, 造成整个服务不可用;
- 如果是持久实例,实例会全部返回,虽然有98个不可用,消费者可能会请求失败,但不至于剩下的两个健康实例崩溃;
Nacos环境隔离
Nacos既是注册中心,又是数据中心。为了便于管理,Nacos提供了namespace来实现环境隔离功能。用于进行租户级别的隔离,我们最常用的就是不同环境比如测试环境,线上环境进行隔离。
- nacos中可以有多个namespace
- namespace下可以有group等。业务相关性比较强的可以放在一组,比如:支付和订单不同namespace之间相互隔离,即不同namespace的服务互相不可见
创建新的namespace
服务配置namespace
修改mafeng-user的namespace,加入dev的namespace
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.66.133:8848
ephemeral: true
namespace: fb99a686-aa07-4ed4-a574-684e1f889189
Nacos数据持久化
默认存储
默认采用内嵌式数据库 Derby 数据库,数据存放在 /nacos/data/derby-data 目录下:
Nacos的namespace、group、持久实例信息等都会持久化写入Derby数据库。
切换为MySQL
做小型工程,用Derby数据库还行,但中大型应用更建议使用MySQL。我们尝试切换为MySQL。
1、登录nacos容器:
docker exec -it nacos /bin/bash
2、修改conf/application.properties文件,在最后追加以下内容
SPRING_DATASOURCE_PLATFORM=mysql
MYSQL_DATABASE_NUM=1
MYSQL_SERVICE_HOST=192.168.66.133
MYSQL_SERVICE_PORT=3306
MYSQL_SERVICE_DB_NAME=nacos
MYSQL_SERVICE_USER=root
MYSQL_SERVICE_PASSWORD=root
3、在mysql导入nacos-mysql.sql
4、重启nacos
docker restart nacos
搭建Nacos集群
Nacos集群架构
搭建集群
我们采用docker-compose搭建,过程轻松简单。
1、上传nacos-docker-master到/root目录下
2、查看example/docker-compose.yml文件内容
version: "3.3"
services:
nacos1:
hostname: nacos1
container_name: nacos1
image: nacos/nacos-server:2.0.3
volumes:
- ./cluster-logs/nacos1:/home/nacos/logs
ports:
- "8861:8848"
- "9861:9848"
- "10555:9555"
env_file:
- ../env/nacos-hostname.env
restart: always
depends_on:
- mysql
nacos2:
hostname: nacos2
image: nacos/nacos-server:2.0.3
container_name: nacos2
volumes:
- ./cluster-logs/nacos2:/home/nacos/logs
ports:
- "8862:8848"
- "9862:9848"
env_file:
- ../env/nacos-hostname.env
restart: always
depends_on:
- mysql
nacos3:
hostname: nacos3
image: nacos/nacos-server:2.0.3
container_name: nacos3
volumes:
- ./cluster-logs/nacos3:/home/nacos/logs
ports:
- "8863:8848"
- "9863:9848"
env_file:
- ../env/nacos-hostname.env
restart: always
depends_on:
- mysql
mysql:
container_name: mysql8
image: nacos/nacos-mysql:8.0.16
env_file:
- ../env/mysql.env
volumes:
- ./mysql:/var/lib/mysql
ports:
- "3307:3306"
nginx:
image: nginx:latest
restart: always
ports:
- "8801:80"
volumes:
- ../nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- ../nginx/conf/conf.d:/etc/nginx/conf.d
- ../nginx/log:/var/log/nginx
- ../nginx/html:/usr/share/nginx/html
container_name: "nginx"
depends_on:
- nacos1
- nacos2
- nacos3
3、查看nginx/conf/nginx.conf文件内容:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
stream
{
upstream nacos {
server 192.168.66.133:9861;
server 192.168.66.133:9862;
server 192.168.66.133:9863;
}
server {
listen 80;
proxy_pass nacos;
}
}
4、在example根目录下执行
docker-compose up -d
等待所有容器启动
5、访问集群
http://192.168.66.133:8861/nacos
服务注册到Nacos集群
mafeng-user和mafeng-order的Nacos连接地址改为:
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.66.133:7801 # 7801(程序端口)+1000(偏移量)=8801(Nginx端口)
各大注册中心产品的相同点
作为服务注册中心,核心的服务注册功能和发现功能都是一样的。
项目中我们可以统一使用Spring Cloud框架的DiscoveryClient 对象实现服务发现和远程调用, 具体使用哪个注册中心产品是透明的。
各大注册中心产品的核心区别
核心对比 | Nacos(推荐使用) | Eureka | Consul | Zookeeper |
一致性协议 | CP或AP | AP | CP | CP |
版本迭代 | 迭代升级中 | 不再升级 | 迭代升级中 | 迭代升级中 |
SpringCloud集成 | 支持 | 支持 | 支持 | 支持 |
Dubbo集成 | 支持 | 不支持 | 不支持 | 支持 |
K8S集成 | 支持 | 不支持 | 支持 | 不支持 |
Eureka优先支持AP
Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和 查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节
点,只要有一台Eureka还在,就能保证注册服务可用(保证强可用性AP),只不过查到的信息可能不是最 新的(不保证强一致性CP)。
Zookeeper优先支持CP
Zookeeper在选举leader时,会停止服务,直到选举成功之后才会再次对外提供服务,这个时候就说明 了服务不可用,但是在选举成功之后,因为一主多从的结构,zookeeper在这时还是一个高可用注册中 心,只是在优先保证一致性的前提下,zookeeper才会顾及到可用性
Consul优先支持CP
1、服务注册相比Eureka会稍慢一些。因为Consul的raft协议要求必须过半数的节点都写入成功才认 为注册成功
2、Leader挂掉时,重新选举期间整个consul不可用。保证了强一致性但牺牲了可用性。
Nacos同时支持AP和CP(推荐使用)
Nacos的临时实例 选择采用AP模式 ,采用distro协议实现
Nacos的持久实例 选择采用CP模式 ,采用raft协议实现