Nacos是什么
Nacos提供了统一配置管理、服务发现与注册。 其中服务注册和发现的功能,相当于dubbo里面使用到 的zookeeper、 或者spring cloud里面应用到的consoul以及eureka。
Nacos官网
Nacos的特性
服务发现和服务健康监测
Nacos提供了基于RPC的服务发现,服务提供者可以将自身的服务通过原生API或者openApi来实现服务 的注册,服务消费者可以使用API或者Http来查找和发现服务;
同时,Nacos提供了对服务的实时监控检查,当发现服务不可用时,可以实现对服务的动态下线从而阻 止服务消费者向不健康的服务发送请求。
配置管理
传统的配置管理,是基于项目中的配置文件来实现,当出现配置文件变更时需要重新部署,而动态配置 中心可以将配置进行统一的管理,是的配置变得更加灵活以及高效。
动态配置中心可以实现路由规则的动态配置、限流规则的动态配置、动态数据源、开关、动态UI等场景。
国内比较有名的开源配置中心: Aollo / diamond / disconf
DNS服务
简述服务配置中心和注册中心
服务注册中心
服务配置中心
Ncos的基本应用
Nacos的下载
首先,我们需要先启动Nacos服务,启动服务有两种方式,一种是直接下载已经编译好的包直接运行。 另一种是通过源码来构建。 我们基于源码先来构建
从github上下载源码
git clone https://github.com/alibaba/nacos.git
cd nacos/
mvn -Prelease-nacos clean install -U
ls -al distribution/target/
cd distribution/target/nacos-server-$version/nacos/bin
启动服务
linux系统下: sh startup.sh -m standalone
window系统: cmd startup.cmd
docker下启动
Nacos也可以直接通过docker安装。
docker run -d --name nacos-server-8848 -p 8848:8848 --privileged=true -v
/opt/nacos/init.d/custom.properties:/home/nacos/init.d/custom.properties -v
/opt/nacos/logs:/home/nacos/logs --restart=always -e MODE=standalone -e
PREFER_HOST_MODE=hostname nacos/nacos-server
访问nacos
默认的帐号密码是:nacos/nacos
Nacos注册中心实战
通过一个案例来演示一下spring cloud alibaba下使用nacos实现配置中心以及服务注册的功能。
创建一个项目
- 创建一个spring-cloud-dubbo-example的maven工程
- 分别添加三个模块
- spring-cloud-dubbo-sample-api
- spring-cloud-dubbo-sample-provider
- spring-cloud-dubbo-sample-consumer
其中后面两个模块都是spring boot的应用
修改 spring-cloud-dubbo-sample-provider 这个模块中。
- 将dependencyManagement部分的依赖移动到parent pom.xml
- 版本说明
spring boot采用2.2.x/ spring cloud alibaba采用2.2.1
<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>
</dependencies>
</dependencyManagement>
- 修改spring-cloud-dubbo-sample-provider中的pom.xml,增加parent模块的依赖
<parent>
<groupId>com.gxedu.dubbo</groupId>
<artifactId>spring-cloud-dubbo-example</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
- 添加maven依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<dependency>
<groupId>com.gxedu.dubbo</groupId>
<version>1.0-SNAPSHOT</version>
<artifactId>spring-cloud-dubbo-sample-api</artifactId>
</dependency>
<!-- 服务发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
定义服务接口
在spring-boot-dubbo-sample-api模块中,定义接口
public interface IHelloService {
String sayHello();
}
实现服务
在spring-boot-dubbo-sample-provider中,实现IHelloService接口
public class HelloServiceImpl implements IHelloService{
@Override
public String sayHello() {
return "Hello Gx";
}
}
添加 @EnableDiscoveryClient 注解
@EnableDiscoveryClient
@SpringBootApplication
public class SpringCloudDubboSampleProviderApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudDubboSampleProviderApplication.class,
args);
}
}
配置dubbo服务发布
- 在服务实现类中添加 @Service 注解(dubbo的@Service注解)
import org.apache.dubbo.config.annotation.Service;
@Service(protocol = "dubbo")
public class HelloServiceImpl implements IHelloService{
@Override
public String sayHello() {
return "Hello Gx";
}
}
- 配置dubbo提供方信息
# dubbo 服务扫描基础包路径
dubbo.scan.base-packages=com.gxedu.dubbo.springclouddubbosampleprovider
dubbo.protocol.id=dubbo
# Dubbo 服务暴露的协议配置,其中子属性 name 为协议名称,port 为协议端口( -1 表示自增端口,从 20880 开始)
dubbo.protocol.name=dubbo
dubbo.protocol.port=-1
spring.cloud.nacos.discovery.server-addr=192.168.216.128:8848
- dubbo.scan.base-packages : 指定 Dubbo 服务实现类的扫描基准包
- dubbo.protocol : Dubbo 服务暴露的协议配置,其中子属性 name 为协议名称, port 为 协议端口( -1 表示自增端口,从 20880 开始)
- dubbo.registry : Dubbo 服务注册中心配置,其中子属性 address 的值 “springcloud://localhost”,说明挂载到 Spring Cloud 注册中心
- spring.cloud.nacos.discovery : Nacos 服务发现与注册配置,其中子属性 server-addr 指定 Nacos 服务器主机和端口
构建服务消费者
- 添加jar包依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.gxedu.dubbo</groupId>
<version>1.0-SNAPSHOT</version>
<artifactId>spring-cloud-dubbo-sample-api</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-web</artifactId>
</dependency>
- 添加配置文件
spring.application.name=spring-cloud-dubbo-sample-consumer
dubbo.application.name=spring-cloud-dubbo-sample-consumer
# 服务消费者订阅服务提供者的应用列表
dubbo.cloud.subscribed-services=spring-cloud-dubbo-sample-provider
spring.cloud.nacos.discovery.server-addr=192.168.216.128:8848
除应用名称 spring.application.name 存在差异外, spring-cloud-dubbo-client-sample 新
增了属性 dubbo.cloud.subscribed-services 的设置。并且该值为服务提供方应用 "springcloud-dubbo-sample-provider"。
它的主要作用是服务消费方订阅服务提供方的应用名称的列表,若需订阅多应用,使用 "," 分割。
不推荐使用默认值为 "*",它将订阅所有应用。
- 编写测试代码
@RestController
@EnableDiscoveryClient
@SpringBootApplication
public class SpringCloudDubboSampleConsumerApplication {
public static void main(String[] args) {SpringApplication.run(SpringCloudDubboSampleConsumerApplication.class,
args);
}
@Reference
IHelloService helloService;
@GetMapping("/say")
public String say(){
return helloService.sayHello();
}
}
Nacos配置中心实战
在Nacos中,实现动态配置管理,相对于Spring Cloud中的Config来说,友好太多了
添加jar包依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
bootstrap.properties
需要注意,配置中心的ip,需要放在bootstrap.properties文件中,因为需要保证优先级。
spring.cloud.nacos.config.server-addr=192.168.216.128:8848
NacosConfigController
创建一个controller,用来测试从nacos配置中心获取数据的场景
dataId 可以认为是一个配置集,一个系统可以有多个配置集,一般我们可以使用包名来命名,从而很好的达到数据分类的目的
groupId 配置分组,这个和dataId类似,但是它的纬度更高一些,可能是基于项目层面进行划分
autoRefreshed 自动更新配置
@RefreshScope
@RestController
public class NacosController {
//如果info为null,取默认值hello Nacos
@Value("${info:hello Nacos}")
private String info;
@GetMapping("/get")
public String get(){
return info;
}
}
测试过程
- 启动服务,访问http://localhost:8080/get ,浏览器会显示info的默认值,因为这个时候nacos还 没有配置info的key
- 进入控制台,增加配置,dataid=example,groupid=spring-cloud-dubbo-sample-provider, 并 且增加 info = xx的value属性
- 再次刷新url,就可以读取到值的变化
关于Nacos Config配置解释
在 Nacos Spring Cloud 中, dataId 的完整格式如下:
${prefix}-${spring.profiles.active}.${file-extension}
- prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix 来配置。
- spring.profiles.active 即为当前环境对应的 profile,详情可以参考 。 注意:当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 {file-extension}
- file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 和 yaml 类 型。
Spring Boot集成Nacos
通过上面两个案例,我们了解了Nacos作为服务注册中心以及配置中心的基本使用。
从使用过程中不难发现,它的整体部署和使用比Spring Cloud Netflix的Config以及Eureka要方便很 多。另外,Nacos它是一个独立组件,不一定要集成到Spring Cloud中。有些公司没有采用spring cloud alibaba,而是直接把nacos作为一个独立组件使用也是可以的,再给大家演示一个Spring Boot 集成Nacos实现动态配置和服务注册,虽然本质上是一样,但是在配置上会有一些细微的差异。
Spring Boot集成Nacos实现动态配置
- 创建spring boot应用
- 添加nacos配置中心的依赖
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.7</version>
</dependency>
- 创建一个controller作为测试
@RestController
@NacosPropertySource(dataId = "spring-cloud-dubbo-sampleprovider",autoRefreshed = true)
public class TestController {
@NacosValue(value = "${info:defailt value}",autoRefreshed = true)
private String info;
@GetMapping("/get")
public String get(){
return info;
}
}
- 修改application.properties文件
nacos.config.server-addr=192.168.216.128:8848
Spring Boot集成Nacos实现注册中心
- 添加jar包依赖
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-discovery-spring-boot-starter</artifactId>
<version>0.2.7</version>
</dependency>
- 创建一个测试类,用户返回当前nacos服务器上注册的服务列表
@RestController
public class ServiceController {
@NacosInjected
private NamingService namingService;
@GetMapping("/discovery")
public List<Instance> get(@RequestParam String serviceName) throws
NacosException {
return namingService.getAllInstances(serviceName);
}
@PostMapping("/registry")
public void registry() throws NacosException {
namingService.registerInstance("example","192.168.1.1",8888,"Test");
}
}
- 修改application.properties文件
nacos.discovery.server-addr=192.168.216.128:8848
- 先调用registry这个接口,向nacos注册服务
- 再访问 http://localhost:8080/discovery?serviceName=example 获取指定服务的实例信息
- 也可以通过直接调用nacos server的服务注册接口进行服务注册
http://127.0.0.1:8848/nacos/v1/ns/instance?
serviceName=example&ip=127.0.0.1&port=8080
Nacos的整体架构
逻辑架构及其组件介绍
- 服务管理:实现服务CRUD,域名CRUD,服务健康状态检查,服务权重管理等功能
- 配置管理:实现配置管CRUD,版本管理,灰度管理,监听管理,推送轨迹,聚合数据等功能
- 元数据管理:提供元数据CURD 和打标能力
- 插件机制:实现三个模块可分可合能力,实现扩展点SPI机制
- 事件机制:实现异步化事件通知,sdk数据变化异步通知等逻辑
- 日志模块:管理日志分类,日志级别,日志可移植性(尤其避免冲突),日志格式,异常码+帮助文档
- 回调机制:sdk通知数据,通过统一的模式回调用户处理。接口和数据结构需要具备可扩展性
- 寻址模式:解决ip,域名,nameserver、广播等多种寻址模式,需要可扩展
- 推送通道:解决server与存储、server间、server与sdk间推送性能问题
- 容量管理:管理每个租户,分组下的容量,防止存储被写爆,影响服务可用性
- 流量管理:按照租户,分组等多个维度对请求频率,长链接个数,报文大小,请求流控进行控制
- 缓存机制:容灾目录,本地缓存,server缓存机制。容灾目录使用需要工具
- 启动模式:按照单机模式,配置模式,服务模式,dns模式,或者all模式,启动不同的程序+UI
- 一致性协议:解决不同数据,不同一致性要求情况下,不同一致性机制
- 存储模块:解决数据持久化、非持久化存储,解决数据分片问题
- Nameserver:解决namespace到clusterid的路由问题,解决用户环境与nacos物理环境映射问题
- CMDB:解决元数据存储,与三方cmdb系统对接问题,解决应用,人,资源关系
- Metrics:暴露标准metrics数据,方便与三方监控系统打通
- Trace:暴露标准trace,方便与SLA系统打通,日志白平化,推送轨迹等能力,并且可以和计量计费系统打通
- 接入管理:相当于阿里云开通服务,分配身份、容量、权限过程
- 用户管理:解决用户管理,登录,sso等问题
- 权限管理:解决身份识别,访问控制,角色管理等问题
- 审计系统:扩展接口方便与不同公司审计系统打通
- 通知系统:核心数据变更,或者操作,方便通过SMS系统打通,通知到对应人数据变更
- OpenAPI:暴露标准Rest风格HTTP接口,简单易用,方便多语言集成
- Console:易用控制台,做服务管理、配置管理等操作
- SDK:多语言sdk
- Agent:dns-f类似模式,或者与mesh等方案集成
- CLI:命令行对产品进行轻量化管理,像git一样好用
领域模型
数据模型
Nacos 数据模型 Key 由三元组唯一确定, Namespace默认是空串,公共命名空间(public),分组默认是 DEFAULT_GROUP。
Nacos Server监控
Prometheus
Prometheus,是一个开源的系统监控和告警的工具包,其采用Pull方式采集时间序列的度量数据(也支持push方式),通过Http协议传输。它的工作方式是被监控的服务需要公开一个Prometheus端点,这端点是一个HTTP接口,该接口公开了度量的列表和当前的值,然后Prometheus应用从此接口定时拉取数据,一般可以存放在时序数据库中,然后通过可视化的Dashboard(e.g.Grafana)进行数据展示。它由以下几个核心组件构成:
- 数据爬虫:根据配置的时间定期的通过HTTP抓去metrics数据。
- time-series 数据库:存储所有的metrics数据。
- 简单的用户交互接口:可视化、查询和监控所有的metrics。
Grafana
Grafana使你能够把来自不同数据源比如Elasticsearch, Prometheus, Graphite, influxDB等多样的数据 以绚丽的图标展示出来。
它也能基于你的metrics数据发出告警。当一个告警状态改变时,它能通知你通过email,slack或者其他 途径。
值得注意的是,Prometheus仪表盘也有简单的图标。但是Grafana的图表表现的更好。这也是为什 么,我们需要整合Grafana和Pormetheus来可视化metrics数据。
Nacos server接入到监控
- 修改${NACOS_HOME}/conf/application.properties,开启prometheus监控的endpoint
针对自己的项目也可以自定义endpoint,开启监控,具体详情看springBoot的endpoint
修改prometheus.yml,添加Nacos的采集任务
- 修改prometheus.yml
- job_name: 'nacos'
metrics_path: '/nacos/actuator/prometheus'
static_configs:
- targets:
["192.168.216.128:8848","192.168.216.129:8848","192.168.216.130:8848"]
- job_name:任务名称
- metrics_path: 指标路径
- targets:实例地址/项目地址,可配置多个
- scrape_interval: 多久采集一次
- scrape_timeout: 采集超时时间
- 启动prometheus服务
./prometheus --config.file="prometheus.yml"
[root@localhost prometheus-2.17.1.linux-amd64]# nohup ./prometheus -- config.file=prometheus.yml --web.enable-lifecycle > prometheus.log 2>&1 &
- 访问:http://192.168.101.198:9090/
- 在搜索栏中搜索 nacos_monitor,如果可以看到nacos的数据,说明采集成功
- 在status菜单的service discovery中,可以看到nacos这个job
采用grafana图形化展示metrics数据
下载Grafana:https://grafana.com/grafana/download
wget https://dl.grafana.com/oss/release/grafana-7.0.3-1.x86_64.rpm
sudo yum install grafana-7.0.3-1.x86_64.rpm
- 启动Grafana, service grafana-server start / $GRAFANA_HOME/bin/grafana-server
- 访问Grafana , http://localhost:3000 , 默认的帐号密码 admin/admin
- 菜单选择 Configuration -> Data Source -> Add Data Source -> 名字:prometheus
- 导入nacos的面板数据 .nacos-granfa.json