Nacos是什么

Nacos提供了统一配置管理、服务发现与注册。 其中服务注册和发现的功能,相当于dubbo里面使用到 的zookeeper、 或者spring cloud里面应用到的consoul以及eureka。

Nacos官网

Nacos的特性

服务发现和服务健康监测

Nacos提供了基于RPC的服务发现,服务提供者可以将自身的服务通过原生API或者openApi来实现服务 的注册,服务消费者可以使用API或者Http来查找和发现服务;

同时,Nacos提供了对服务的实时监控检查,当发现服务不可用时,可以实现对服务的动态下线从而阻 止服务消费者向不健康的服务发送请求。

配置管理

传统的配置管理,是基于项目中的配置文件来实现,当出现配置文件变更时需要重新部署,而动态配置 中心可以将配置进行统一的管理,是的配置变得更加灵活以及高效。

动态配置中心可以实现路由规则的动态配置、限流规则的动态配置、动态数据源、开关、动态UI等场景。

国内比较有名的开源配置中心: Aollo / diamond / disconf

DNS服务

简述服务配置中心和注册中心

服务注册中心

查看nacos容器连接的数据库地址_Cloud

服务配置中心

查看nacos容器连接的数据库地址_ide_02

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

http://localhost:8848/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
  • 版本说明

    查看nacos容器连接的数据库地址_Cloud_03

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 的拼接格式变成 查看nacos容器连接的数据库地址_查看nacos容器连接的数据库地址_04{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的整体架构

查看nacos容器连接的数据库地址_查看nacos容器连接的数据库地址_05

查看nacos容器连接的数据库地址_Cloud_06

逻辑架构及其组件介绍

查看nacos容器连接的数据库地址_ide_07

  • 服务管理:实现服务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容器连接的数据库地址_ide_08

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

  • 查看nacos容器连接的数据库地址_查看nacos容器连接的数据库地址_09

  • 访问这个地址: http://192.168.101.198:8848/nacos/actuator/prometheus 可以看到服务监控信息

查看nacos容器连接的数据库地址_查看nacos容器连接的数据库地址_10

修改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容器连接的数据库地址_ide_11

  • 导入nacos的面板数据 .nacos-granfa.json