01.Nacos入门

596 阅读10分钟
Nacos源码下载地址:https://github.com/alibaba/nacos/
nacos-server下载地址:https://github.com/alibaba/nacos/releases
本篇文章中的Nacos版本: Nacos 1.4.1
文档: https://nacos.io/docs/v1/what-is-nacos/
中文文档:https://nacos.io/zh-cn/docs/what-is-nacos.html

Nacos简介

全称:Dynamic Naming and Configuration Service

Nacos 是国产的,是阿里开源的

阿里为 SpringCloud 贡献了一个子项目,叫做 SpringCloud Alibaba,其中包括了微服务开发中的几个基础组件,Nacos 就是此项目中的一项技术,可以实现服务注册中心、分布式配置中心。

在服务的注册与发现上,与Eureka和zk的使用差不多

服务注册中心

何为服务发现?

分布式系统中,包含多个独立的服务,服务之间存在需要调用的需求,应该如何调用?

服务调用时必须知道目标服务实例的 IP、端口、API 接口。

其中 API 信息可以通过服务接口文档中获知,但 IP、端口 都是动态的,每次部署服务实例的时候可能都会变。

知道了目标服务实例的地址,就相当于发现了对方。具体怎么发现目标服务?这就是服务发现机制。

image.png

如上图,在服务实例数量少的时候,每个服务实例可以自己维护相关服务实例的地址信息,也就是自己维护一个通讯录。

例如通过配置文件来记录,相关服务实例地址发生变更的时候就修改一下,有点麻烦,但还可以忍受。

但是,当服务实例数量变大之后,就无法自己维护了,相关服务数量多、地址变化频繁。

此时必须有一种更优的发现机制,就出现了服务注册中心。

image.png

如上图,每个服务实例启动之后,都主动向注册中心登记自己的地址信息,这样注册中心便拥有了所有服务实例的记录,类似于查号台。

当某个服务实例停止运行的时候,主动让注册中心销毁自己的信息。

如果服务实例不是主动停止,而是因为故障等原因死掉的,如何处理?需要注册中心能够主动清理。

注册中心要能够实时知道各个服务实例的状态,通过心跳机制来实现,实例定时向注册中心发送请求,表明自己还活着,如果心跳没了,注册中心就可以对其清理。

image.png

一个服务实例在调用另一个服务时,可以根据服务名称从注册中心获取此服务的实例信息列表,从中选取一个实例进行调用。

以上就是注册中心这种服务发现机制的工作方式。

分布式配置中心

分布式配置概念简介

image.png

每个服务都会有自己的配置信息,例如 SpringBoot 项目中的配置文件,服务运行时会读取配置文件中的配置项。

一个服务通常会启动多个实例,来提供其可靠性,那么每个实例中就都会包含这个配置文件,一个服务的各个实例中配置都是相同的。

如果要改某个配置项的值,怎么办?

修改配置文件,然后重新部署此服务的所有实例。麻烦低效。

image.png 如果把服务的配置信息提出来,不放在自己的配置文件中,而是放到一个第三方的配置中心,服务实例从配置中心读取属于自己的配置,而且,在配置中心里面修改配置项之后,所有相关实例都可以立即拿到最新值,不用重新部署了,这样就方便很多。

所以分布式配置有2大好处:

  • 方便维护,集中维护优于分散式维护每个服务的配置文件
  • 动态更新,配置修改后直接生效,不用重新部署

此外,Nacos 还可以做配置的版本管理,轻松实现历史版本的回滚

分布式系统CAP架构

CAP定理是分布式系统中最基础的原则,所以理解和掌握了CAP对系统架构的设计至关重要。分布式架构下所有系统不可能同时满足以下三点:Consisteny(一致性)、Availability(可用性)、Partition tolerance(分区容错性)

CAP指明了任何分布式系统只能同时满足这三项中的两项。分布式系统肯定都要保证其容错性 ,那么可用性和一致性就只能选一个了

几种常见注册中心的区别

  注册中心在分布式应用中是经常用到的,也是必不可少的,那注册中心,又分为以下几种:Eureka、Zookeeper、Nacos等。这些注册中心最大的区别就是其基于AP架构还是CP架构,简单介绍一下:

  Zookeeper:zk集群下一旦leader节点宕机了,在短时间内服务都不可通讯,因为它们在一定时间内follower进行选举来推出新的leader,因为在这段时间内,所有的服务通信将受到影响,而且leader选取时间比较长,需要花费几十秒甚至上百秒的时间,因此:可以理解为 Zookeeper是实现的CP,也就是将失去A(可用性)。

  Eureka:Eureka集群下每个节点之间都会定时发送心跳,定时同步数据,没有master/slave之分,是一个完全去中心化的架构。因此每个注册到Eureka下的实例都会定时同步ip,服务之间的调用也是根据Eureka拿到的缓存服务数据进行调用。若一台Eureka服务宕机,其他Eureka在一定时间内未感知到这台Eureka服务宕机,各个服务之间还是可以正常调用。Eureka的集群中,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。当数据出现不一致时,虽然A, B上的注册信息不完全相同,但每个Eureka节点依然能够正常对外提供服务,这会出现查询服务信息时如果请求A查不到,但请求B就能查到。如此保证了可用性但牺牲了一致性。

  Nacos同时支持CP和AP架构,根据根据服务注册选择临时和永久来决定走AP模式还是CP模式。如果注册Nacos的client节点注册时ephemeral=true,那么Nacos集群对这个client节点的效果就是AP,采用distro协议实现;而注册Nacos的client节点注册时ephemeral=false,那么Nacos集群对这个节点的效果就是CP的,采用raft协议实现。

主流的注册中心支持的功能和区别

image.png

Nacos集成案例

Nacos跟docker、spring、springboot的集成案例可以参考 nacos-groupimage.png

Windows下Nacos源码调试运行

nacos源码导入要求maven 3.2.5以上版本

# nacos源码下载地址,源码包结构如下:

image.png

编译

进入nacos目录,执行编译命令,增加 -Drat.skip=true 参数 ,可以跳过licensing 检查 执行:mvn -Prelease-nacos -Dmaven.test.skip=true -Drat.skip=true clean install -U,编译成功后会在distribution/target目录下生成nacos-server-1.4.1.tar.gz

配置mysql数据库

修改console中的application.properties文件配置,放开mysql,配置为我们自己的mysql数据库。这样服务注册的值就会持久化到数据库,不会服务重启后就消失

application.properties文件位于console\src\main\resources\application.properties

### If use MySQL as datasource:
spring.datasource.platform=mysql

### Count of DB:
db.num=1

### Connect URL of DB:
db.url.0=jdbc:mysql://192.168.30.13:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=username
db.password.0=pwd

执行mysql脚本创建mysql数据库表

mysql脚本位于:distribution/conf/nacos-mysql.sql,执行成功后建表如下:

image.png

配置启动参数

单机模式执行需要指定-Dnacos.standalone=true

如果还是启动失败那么尝试-Dnacos.standalone=true -Dnacos.home=D:\code\java_yuanma\nacos-1.4.1

启动console模块下的com.alibaba.nacos.Nacos

进入console模块,找到启动类 com.alibaba.nacos.Nacos,执行main方法

image.png

启动Nacos.java后控制台输出日志如下,显示启动成功:

"C:\Program Files\Java\jdk1.8.0_271\bin\java.exe" -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:64973,suspend=y,server=n -Dnacos.standalone=true ...省略classpath
Connected to the target VM, address: '127.0.0.1:64973', transport: 'socket'

         ,--.
       ,--.'|
   ,--,:  : |                                           Nacos 
,`--.'`|  ' :                       ,---.               Running in stand alone mode, All function modules
|   :  :  | |                      '   ,'\   .--.--.    Port: 8848
:   |   \ | :  ,--.--.     ,---.  /   /   | /  /    '   Pid: 9624
|   : '  '; | /       \   /     \.   ; ,. :|  :  /`./   Console: http://192.168.5.173:8848/nacos/index.html
'   ' ;.    ;.--.  .-. | /    / ''   | |: :|  :  ;_
|   | | \   | \__\/: . ..    ' / '   | .; : \  \    `.      https://nacos.io
'   : |  ; .' ," .--.; |'   ; :__|   :    |  `----.   \
|   | '`--'  /  /  ,.  |'   | '.'|\   \  /  /  /`--'  /
'   : |     ;  :   .'   \   :    : `----'  '--'.     /
;   |.'     |  ,     .-./\   \  /            `--'---'
'---'        `--`---'     `----'

2024-05-08 19:10:45.981  INFO 9624 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler@7316523a' of type [org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2024-05-08 19:10:45.981  INFO 9624 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'methodSecurityMetadataSource' of type [org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2024-05-08 19:10:46.345  INFO 9624 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8848 (http)
2024-05-08 19:10:46.818  INFO 9624 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 3576 ms
2024-05-08 19:10:49.250  WARN 9624 --- [           main] c.a.nacos.common.notify.NotifyCenter     : There are no [com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent] publishers for this event, please register
2024-05-08 19:10:49.266  WARN 9624 --- [           main] c.a.nacos.common.notify.NotifyCenter     : There are no [com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent] publishers for this event, please register
2024-05-08 19:10:49.266  WARN 9624 --- [           main] c.a.nacos.common.notify.NotifyCenter     : There are no [com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent] publishers for this event, please register
2024-05-08 19:10:49.266  WARN 9624 --- [           main] c.a.nacos.common.notify.NotifyCenter     : There are no [com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent] publishers for this event, please register
2024-05-08 19:10:49.266  WARN 9624 --- [           main] c.a.nacos.common.notify.NotifyCenter     : There are no [com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent] publishers for this event, please register
2024-05-08 19:10:49.266  WARN 9624 --- [           main] c.a.nacos.common.notify.NotifyCenter     : There are no [com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent] publishers for this event, please register
2024-05-08 19:10:49.754  INFO 9624 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2024-05-08 19:10:49.864  INFO 9624 --- [           main] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page: class path resource [static/index.html]
2024-05-08 19:10:50.225  INFO 9624 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: Ant [pattern='/**'], []
2024-05-08 19:10:50.256  INFO 9624 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@2aa811f9, org.springframework.security.web.context.SecurityContextPersistenceFilter@59c862af, org.springframework.security.web.header.HeaderWriterFilter@45539bd8, org.springframework.security.web.csrf.CsrfFilter@2e4b5da1, org.springframework.security.web.authentication.logout.LogoutFilter@60b553f, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@673a9db4, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@558127d2, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@66abb2fa, org.springframework.security.web.session.SessionManagementFilter@408d945b, org.springframework.security.web.access.ExceptionTranslationFilter@6a0e97fc]
2024-05-08 19:10:50.350  INFO 9624 --- [           main] o.s.s.c.ThreadPoolTaskScheduler          : Initializing ExecutorService 'taskScheduler'
2024-05-08 19:10:50.366  INFO 9624 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 2 endpoint(s) beneath base path '/actuator'
2024-05-08 19:10:50.475  INFO 9624 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8848 (http) with context path '/nacos'
2024-05-08 19:10:50.475  INFO 9624 --- [           main] c.a.n.c.l.StartingApplicationListener    : Nacos started successfully in stand alone mode. use external storage
2024-05-08 19:10:52.152  INFO 9624 --- [)-192.168.5.173] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2024-05-08 19:10:52.152  INFO 9624 --- [)-192.168.5.173] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms

访问后台

访问链接:http://localhost:8848/nacos/

用户名和密码都是:nacos image.png

模拟手动服务注册&发现和配置管理

调用以下命令,同时观察nacos控制台中服务列表和配置列表的变化

服务注册
curl -X POST 'http://192.168.5.173:8848/nacos/v1/ns/instance?serviceName=nacos.naming.serviceName&ip=20.18.7.10&port=8080'

服务发现
curl -X GET 'http://192.168.5.173:8848/nacos/v1/ns/instance/list?serviceName=nacos.naming.serviceName'

发布配置
curl -X POST "http://192.168.5.173:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=HelloWorld"

获取配置
curl -X GET "http://192.168.5.173:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"

console模块虽然是负责管理控制台的,但是它本身也依赖了config和naming模块,所以也支持restful风格动态注册config和naming。可以在nacos源码中搜索ConfigControllerInstanceController观察服务注册和配置注册的底层实现

Linux下启动Nacos Server

下载Nacos Server包

Nacos Server下载地址:github.com/alibaba/nac…

Nacos-1.4.1下载位置:github.com/alibaba/nac…

image.png

单机启动

下载zip或者tar.gz包后上传到linux服务器上解压缩,进入其bin目录后发现有四个脚本:shutdown.cmd shutdown.sh startup.cmd startup.sh,支持:

  • linux下单机模式启动:startup.sh -m standalone
  • windows下单机模式启动:startup.cmd -m standalone

当然我们也可以配置conf/application.properties中的mysql,从而达到服务持久化的功能,具体配置可以参考上面的Windows下Nacos源码调试运行

访问后台

Nacos Server的后台访问地址:http://ip:8848/nacos ,默认账号和密码为:nacos

Nacos三种部署模式

nacos部署手册

  • 单机模式:用于测试和单机试用。见上面的Linux下启动Nacos Server
  • 集群模式:用于生产环境,确保高可用。请参考集群模式下运行Nacos
  • 多集群模式:用于多数据中心场景。

Nacos架构

nacos架构图如下: image.png