微服务之Spring Cloud Alibaba Nacos基础学习

一,Spring Cloud Alibaba简介

Spring Cloud Alibaba致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 SpringCloud编程模型轻松使用这些组件来开发分布式应用服务。依托Spring Cloud Alibaba,我们只需要添加一些注解和少量配置,就可以将Spring Cloud应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。

Spring Cloud Alibaba的业务支持

目前SpringCloudAlibaba能干的东西很多,大体上包括但不限于以下几点:

  • .Flow control and service degradation: flow control, circuit breaking and system adaptiveprotection with Alibaba Sentinel流量控制和服务退化:流量控制、线路断开和系统自适应保护--用阿里巴巴哨兵

  • Service registration and discovery: instances can be registered with Alibaba Nacos and clients candiscover the instances using Spring-managed beans.Supports Ribbon, the client side load-balancervia Spring Cloud Netflix服务注册和发现:实例可以在阿里巴巴Nacos注册,客户可以使用Spring管理的bean来发现实例。支持Ribbon,客户端通过SpringCloud Netflix实现负载平衡

  • Distributed Configuration: using Alibaba Nacos as a data store分布式配置:使用Alibaba Nacos作为数据存储

  • Event-driven: building highly scalable event-driven microservices connected with Spring Cloudstream RocketMQ Binder.Event驱动:构建与SpringCloudstream RocketMQ绑定器连接的高可伸缩性事件驱动的微服务

  • Message Bus: link nodes of a distributed system with Spring Cloud Bus RocketMQ消息总线:用SpringCloud总线RocketMQ连接分布式系统的节点

  • Distributed Transaction: support for distributed transaction solution with high performance andease of use with Seata分布式事务:支持高性能的分布式事务解决方案,并与Seata一起使用。

  • Dubbo RPC: extend the communication protocols of Spring Cloud service-to-service calls by ApacheDubbo RPC.dubo rpc:通过Apacheduborpc扩展SpringCloud服务到服务调用的通信协议。

更多详细信息可参考Spring Cloud Alibaba参考文档

Spring Cloud Alibaba使用

在微服务项目中,我们只需要引入Spring Cloud Alibaba的依赖即可实现对相关技术依赖的引用。

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>{project-version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

二,Nacos简介

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。

Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。

Nacos可以理解为就是注册中心+配置中心的组合。

总体上Nacos的关键特性包括:

  • 服务发现和服务健康监测

Nacos 支持基于 DNS 和基于 RPC 的服务发现。服务提供者使用 原生SDKOpenAPI、或一个独立的Agent TODO注册 Service 后,服务消费者可以使用DNS TODOHTTP&API查找和发现服务。

Nacos 提供对服务的实时的健康检查,阻止向不健康的主机或服务实例发送请求。Nacos 支持传输层 (PING 或 TCP)和应用层 (如 HTTP、MySQL、用户自定义)的健康检查。 对于复杂的云环境和网络拓扑环境中(如 VPC、边缘网络等)服务的健康检查,Nacos 提供了 agent 上报模式和服务端主动检测2种健康检查模式。Nacos 还提供了统一的健康检查仪表盘,帮助您根据健康状态管理服务的可用性及流量。

  • 动态配置服务

动态配置服务可以让您以中心化、外部化和动态化的方式管理所有环境的应用配置和服务配置。

动态配置消除了配置变更时重新部署应用和服务的需要,让配置管理变得更加高效和敏捷。

配置中心化管理让实现无状态服务变得更简单,让服务按需弹性扩展变得更容易。

Nacos 提供了一个简洁易用的UI (控制台样例 Demo) 帮助您管理所有的服务和应用的配置。Nacos 还提供包括配置版本跟踪、金丝雀发布、一键回滚配置以及客户端配置更新状态跟踪在内的一系列开箱即用的配置管理特性,帮助您更安全地在生产环境中管理配置变更和降低配置变更带来的风险。

  • 动态 DNS 服务

动态 DNS 服务支持权重路由,让您更容易地实现中间层负载均衡、更灵活的路由策略、流量控制以及数据中心内网的简单DNS解析服务。动态DNS服务还能让您更容易地实现以 DNS 协议为基础的服务发现,以帮助您消除耦合到厂商私有服务发现 API 上的风险。

Nacos 提供了一些简单的 DNS APIs TODO 帮助您管理服务的关联域名和可用的 IP:PORT 列表.

  • 服务及其元数据管理

Nacos 能让您从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略、服务的 SLA 以及最首要的 metrics 统计数据。

在微服务中, Nacos 主要用来实现分布式环境下的配置管理和服务注册发现。

  • 通过 Nacos Server 和 spring-cloud-starter-alibaba-nacos-config 实现配置的动态变更。

  • 通过 Nacos Server 和 spring-cloud-starter-alibaba-nacos-discovery 实现服务的注册与发现。

Nacos安装与运行

本地安装与使用

Nacos服务的使用也非常简单,只需我们在官网下载后运行即可。

进入releases界面进行相应的下载,本地直接下载压缩包即可。

但是当你去下载的时候会发现特别的慢,然后我这里给出一种其他的获取压缩包的方法:获取源文件打包后得到zip

方法如下:

1,进入gitee中Nacos的国内镜像仓库去下载Nacos源文件,仓库地址为:Nacos国内镜像仓库

这时候大约不到一分钟就能下载完成。

D:\SpringCloudAlibabaComponent>git clone https://gitee.com/mirrors/Nacos.git
Cloning into 'Nacos'...
remote: Enumerating objects: 104276, done.
remote: Counting objects: 100% (104276/104276), done.
remote: Compressing objects: 100% (34545/34545), done.
remote: Total 104276 (delta 44989), reused 99183 (delta 42084), pack-reused 0
Receiving objects: 100% (104276/104276), 40.03 MiB | 2.76 MiB/s, done.
​
Resolving deltas: 100% (44989/44989), done.
Updating files: 100% (2298/2298), done.

然后进入我们下好的Nacos文件中,通过maven对Nacos源文件进行打包。时间可能相较于前面克隆下载Nacos源文件较长,但是比去官网下载要好得多。

#maven打包命令
mvn -Prelease-nacos-Dmaven.test.skip=true clean install -U

等待maven打包完成后,在Nacos\distribution\target目录下就能得到可用于windows和Linux的压缩包了。

然后将压缩包放到无中文的目录中,注意:包括有中文的括号也会出现启动闪退的情况!必须在没有任何中文符号的纯英文目录下才行。然后进行解压,进入到bin目录中windows上双击启动startup.cmd了。

但是这时候通常或出现启动报错,因为Nacos默认是集群启动的。

"nacos is starting with cluster"
​
         ,--.
       ,--.'|
   ,--,:  : |                                           Nacos 2.1.2
,`--.'`|  ' :                       ,---.               Running in cluster mode, All function modules
|   :  :  | |                      '   ,'\   .--.--.    Port: 8848
:   |   \ | :  ,--.--.     ,---.  /   /   | /  /    '   Pid: 21528
|   : '  '; | /       \   /     \.   ; ,. :|  :  /`./   Console: http://192.168.109.1:8848/nacos/index.html
'   ' ;.    ;.--.  .-. | /    / ''   | |: :|  :  ;_
|   | | \   | \__\/: . ..    ' / '   | .; : \  \    `.      https://nacos.io
'   : |  ; .' ," .--.; |'   ; :__|   :    |  `----.   \
|   | '`--'  /  /  ,.  |'   | '.'|\   \  /  /  /`--'  /
'   : |     ;  :   .'   \   :    : `----'  '--'.     /
;   |.'     |  ,     .-./\   \  /            `--'---'
'---'        `--`---'     `----'
​
2023-01-04 15:14:47,104 INFO The server IP list of Nacos is []
​
2023-01-04 15:14:48,110 INFO Nacos is starting...
​
2023-01-04 15:14:49,114 INFO Nacos is starting...
​
2023-01-04 15:14:50,120 INFO Nacos is starting...

打开startup.cmd文件就能看得到这一点。

因此我们要手动更改启动模式。

# 原来
setMODE="cluster"
​
# 修改后
setMODE="standalone"

然后就可以正常启动了。

"nacos is starting with standalone"
​
         ,--.
       ,--.'|
   ,--,:  : |                                           Nacos 2.2.0
,`--.'`|  ' :                       ,---.               Running in stand alone mode, All function modules
|   :  :  | |                      '   ,'\   .--.--.    Port: 8848
:   |   \ | :  ,--.--.     ,---.  /   /   | /  /    '   Pid: 15168
|   : '  '; | /       \   /     \.   ; ,. :|  :  /`./   Console: http://192.168.109.1:8848/nacos/index.html
'   ' ;.    ;.--.  .-. | /    / ''   | |: :|  :  ;_
|   | | \   | \__\/: . ..    ' / '   | .; : \  \    `.      https://nacos.io
'   : |  ; .' ," .--.; |'   ; :__|   :    |  `----.   \
|   | '`--'  /  /  ,.  |'   | '.'|\   \  /  /  /`--'  /
'   : |     ;  :   .'   \   :    : `----'  '--'.     /
;   |.'     |  ,     .-./\   \  /            `--'---'
'---'        `--`---'     `----'
​
2023-01-0415:22:22,382 INFO Tomcat initialized with port(s): 8848 (http)
​
2023-01-0415:22:22,498 INFO Root WebApplicationContext: initialization completed in3064 ms
​
2023-01-0415:22:27,454 INFO Adding welcome page: class path resource [static/index.html]
​
2023-01-0415:22:27,872 WARN You are asking Spring Security to ignore Ant [pattern='/**']. This is not recommended -- please use permitAll via HttpSecurity#authorizeHttpRequests instead.
​
2023-01-0415:22:27,873 INFO Will not secure Ant [pattern='/**']
​
2023-01-0415:22:27,916 INFO Will secure any request with [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@cf65451, org.springframework.security.web.context.SecurityContextPersistenceFilter@517bd097, org.springframework.security.web.header.HeaderWriterFilter@1601e47, org.springframework.security.web.csrf.CsrfFilter@7de0c6ae, org.springframework.security.web.authentication.logout.LogoutFilter@114a85c2, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@4a9cc6cb, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@56e07a08, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@724f138e, org.springframework.security.web.session.SessionManagementFilter@66971f6b, org.springframework.security.web.access.ExceptionTranslationFilter@5471388b]
​
2023-01-0415:22:27,942 INFO Exposing 1 endpoint(s) beneath base path '/actuator'
​
2023-01-0415:22:27,985 INFO Tomcat started on port(s): 8848 (http) with context path '/nacos'
​
2023-01-0415:22:28,010 INFO Nacos started successfully in stand alone mode. use embedded storage

如果觉得更改启动配置麻烦呢,也可以在bin目录下通过命令脚本以单机模式启动。

## 启动nacos
> startup.bat -m standalone

Nacos Server启动后,转到http://localhost:8848/nacos查看控制台(默认帐户名/密码为nacos/nacos)。

Linux系统下的安装与使用

在Linux系统上,我推荐使用docker进行拉取Nacos服务镜像后进行使用,毕竟能节省部分配置的时间。

首先利用docker搜索nacos的相关镜像。

[root@VM-12-4-centos ~]# docker search nacos
NAME                                 DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
nacos/nacos-server                   This project contains a Docker image meant t…   340                  [OK]
zhusaidong/nacos-server-m1           Nacos Server for Apple MacOS M1                 12                   
nacos/nacos-mysql-master             nacos-mysql-master                              6                    
zill057/nacos-server-apple-silicon   nacos with Apple Silicon M1 Chip support. 支…    6                    
nacos/nacos-mysql                                                                    6                    
paderlol/nacos                       Nacos-quick-start-https://nacos.io/en-us/doc…   5                    
chenfengwei/nacos                    nacos服务镜像,nacos版本1.3.2,同时兼任arm64…               3                    
nacos/nacos-operator                                                                 2                    
king019/nacos                                                                        2                    
nacos/nacos-mysql-slave                                                              1                    
nacos/nacos-peer-finder-plugin       scale plugin for nacos k8s                      1                    
tanyi/nacos-server                   nacos-server官方包制作而成的镜像                          1                    
jude95/nacos-server-mysql8           nacos with mysql8                               0                    
nacosta/node-5.5.0-base                                                              0                    
nacosta/redis                                                                        0                    
centralx/nacos-server                Multi CPU architectures support for nacos/na…   0                    
nacosta/nodejs                                                                       0                    
dockerlishijie/nacos-server                                                          0                    
tonychen0716/nacos-server            Multi-arch image for Alibaba Nacos              0                    
lizexiong/nacos                                                                      0                    
eduosi/nacos-server                                                                  0                    
loads/nacos-server                                                                   0                    
paderlol/nacos-mysql-master                                                          0                    
paderlol/nacos-mysql-slave                                                           0                    
lijiahao1995/nacos               

这里我们选取nacos/nacos-server即可。然后拉取nacos服务的镜像

[root@VM-12-4-centos ~]# docker pull nacos/nacos-server
Using default tag: latest
latest: Pulling from nacos/nacos-server
2d473b07cdd5: Pull complete 
cee47fd629ae: Pull complete 
84a2014f8cf0: Pull complete 
c6b323bb84ba: Pull complete 
054ba3dd31ca: Pull complete 
499f0fb6edda: Pull complete 
44f7142cdeb2: Pull complete 
16c455a3adda: Pull complete 
37ab0ca7ea67: Pull complete 
4f4fb700ef54: Pull complete 
Digest: sha256:be794368c96f90e42a6dd9f288d3fb12d69608cebd782eb091a489ccb48cfd28
Status: Downloaded newer image for nacos/nacos-server:latest
docker.io/nacos/nacos-server:latest
[root@VM-12-4-centos ~]# docker images
REPOSITORY                   TAG          IMAGE ID       CREATED        SIZE
nacos/nacos-server           latest       440657d52bc3   2 weeks ago    1.07GB
openzipkin/zipkin            latest       ad5bf93e3f50   2 weeks ago    165MB
rabbitmq                     management   c8a49f166d2d   2 weeks ago    257MB
mysql                        8.0          7484689f290f   4 weeks ago    538MB
registry                     latest       81c944c2288b   7 weeks ago    24.1MB

有点小大,但是无伤大雅。完工后,通过docker命令启动nacos服务的容器。

#单机模式运行

docker run --envMODE=standalone --name nacos -d-p8848:8848 nacos/nacos-server

然后就能看到nacos服务容器启动成功,暴露端口号为8848。

[root@VM-12-4-centos ~]# docker run --env MODE=standalone --name nacos -d -p 8848:8848 nacos/nacos-server
3bd977fc733cc832cd8f50d9f863627d6014d39475a7a44449f00001a8329aa8
[root@VM-12-4-centos ~]# docker ps -s
CONTAINER ID   IMAGE                 COMMAND                  CREATED         STATUS         PORTS                                                                                                                                                 NAMES     SIZE
3bd977fc733c   nacos/nacos-server    "bin/docker-startup.…"   9 seconds ago   Up 4 seconds   0.0.0.0:8848->8848/tcp, :::8848->8848/tcp                                                                                                             nacos     34.9kB (virtual 1.07GB)
a6f28deb93ee   rabbitmq:management   "docker-entrypoint.s…"   2 weeks ago     Up 7 days      4369/tcp, 5671/tcp, 0.0.0.0:5672->5672/tcp, :::5672->5672/tcp, 15671/tcp, 15691-15692/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp, :::15672->15672/tcp   rabbit1   0B (virtual 257MB)

当然为了让我们能远程访问nacos服务的web界面呢,还需要检查一下服务器防火墙对于8848的端口号是否开放,如果没有则进行开放,阿里云的服务器还要进行安全组配置,这里一笔带过就好。

#检查防火墙端口是否开放

[root@VM-12-4-centos ~]# firewall-cmd --query-port=8848/tcp
You're performing an operation over default zone ('public'),
but your connections/interfaces are in zone 'docker' (see --get-active-zones)
You most likely need to use --zone=docker option.
​
no
#开放8848端口
[root@VM-12-4-centos ~]# firewall-cmd --add-port=8848/tcp --permanent
You're performing an operation over default zone ('public'),
but your connections/interfaces are in zone 'docker' (see --get-active-zones)
You most likely need to use --zone=docker option.
​
success
#重启防火墙
[root@VM-12-4-centos ~]# firewall-cmd --reload
success

但是事与愿违,docker启动nacos服务后很快就停止了。通过docker查看nacos镜像日志后,发现如下异常:

Caused by: java.sql.SQLTimeoutException: Login timeout exceeded.
    at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
    at org.apache.derby.jdbc.InternalDriver.timeLogin(Unknown Source)
    at org.apache.derby.jdbc.InternalDriver.connect(Unknown Source)
    at org.apache.derby.jdbc.InternalDriver.connect(Unknown Source)
    at org.apache.derby.jdbc.EmbeddedDriver.connect(Unknown Source)
    at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138)
    at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:354)
    at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:202)
    at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:473)
    at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:554)
    at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:115)
    at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112)
    at com.alibaba.nacos.config.server.service.datasource.LocalDataSourceServiceImpl.reload(LocalDataSourceServiceImpl.java:95)
    ... 79 common frames omitted
Caused by: org.apache.derby.iapi.error.StandardException: Login timeout exceeded.
    at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
    at org.apache.derby.impl.jdbc.SQLExceptionFactory.wrapArgsForTransportAcrossDRDA(Unknown Source)
    ... 95 common frames omitted
2023-01-0416:53:41,645 WARN [ThreadPoolManager] Start destroying ThreadPool
​
2023-01-0416:53:41,645 WARN [ThreadPoolManager] Destruction of the end
​

猜测可能是新版2.2.0的nacos需要配置数据源信息。因此我们下面说一下外部mysql数据源配置的问题(windos本地不影响使用)。

Nacos配置mysql数据库

在0.7版本之前,在单机模式时nacos使用嵌入式数据库实现数据的存储,不方便观察数据存储的基本情况。0.7版本增加了支持mysql数据源能力,所以只要使用0.7及以上版本的nacos,便可以配置mysql数据库,可视化的查看数据的存储情况了。

windows下配置mysql数据库也很简单,在本地通过Navcat新建一个数据库后,将D:\SpringCloudAlibabaComponent\nacos-server-2.2.0\nacos\conf目录下的sql文件mysql-schema.sql在新建的数据库中导入,即可看到相关数据表都导入成功。

然后在application.properties文件中编辑nacos的配置文件,启用数据库连接配置并修改相关信息。

#*************** Config Module Related Configurations ***************#
### If use MySQL as datasource:
 spring.datasource.platform=mysql
​
### Count of DB:
 db.num=1
​
### Connect URL of DB:
 db.url.0=jdbc:mysql://127.0.0.1:3306/nacos-config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai
 db.user.0=root
 db.password.0=123456
​
### Connection pool configuration: hikariCP
db.pool.config.connectionTimeout=30000
db.pool.config.validationTimeout=10000
db.pool.config.maximumPoolSize=20
db.pool.config.minimumIdle=2

windows上的mysql数据源配置完成。

Linux系统上过程大致相似,需要我们将mysql-schema.sql数据库文件导入Linux上的mysql数据库中。不同于windows的是,我们只需在docker启动nacos的时候指明相关配置信息即可。

[root@VM-12-4-centos containers]# docker run \
>    --env MODE=standalone \
>    --env SPRING_DATASOURCE_PLATFORM=mysql \
>    --env MYSQL_SERVICE_HOST=服务器ip地址  \
>    --env MYSQL_SERVICE_DB_NAME=nacos-config   \
>    --env MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8\&connectTimeout=1000\&socketTimeout=3000\&autoReconnect=true\&useUnicode=true\&useSSL=false\&serverTimezone=Asia/Shanghai  \
>    --env MYSQL_SERVICE_USER=root   \
>    --env MYSQL_SERVICE_PASSWORD=123456   \
>    --name nacos -d -p 8848:8848 nacos/nacos-server 
d56e6021bb76cd533af51b995699a21d428124b722986504486b3be1196d67c8
[root@VM-12-4-centos containers]# docker logs nacos
+ export CUSTOM_SEARCH_NAMES=application
+ CUSTOM_SEARCH_NAMES=application
+ export CUSTOM_SEARCH_LOCATIONS=file:/home/nacos/conf/
+ CUSTOM_SEARCH_LOCATIONS=file:/home/nacos/conf/
+ export MEMBER_LIST=
+ MEMBER_LIST=
+ PLUGINS_DIR=/home/nacos/plugins/peer-finder
+ [[ standalone == \s\t\a\n\d\a\l\o\n\e ]]
+ JAVA_OPT=' -Xms1g -Xmx1g -Xmn512m'
+ JAVA_OPT=' -Xms1g -Xmx1g -Xmn512m -Dnacos.standalone=true'
+ [[ all == \c\o\n\f\i\g ]]
+ [[ all == \n\a\m\i\n\g ]]
+ [[ ! -z '' ]]
+ [[ ! -z '' ]]
+ [[ ! -z '' ]]
+ [[ ! -z '' ]]
+ [[ ! -z '' ]]
+ [[ ip == \h\o\s\t\n\a\m\e ]]
+ JAVA_OPT=' -Xms1g -Xmx1g -Xmn512m -Dnacos.standalone=true -Dnacos.member.list='
++ /usr/lib/jvm/java-1.8.0-openjdk/bin/java -version
++ sed -E -n 's/.* version "([0-9]*).*$/\1/p'
+ JAVA_MAJOR_VERSION=1
+ [[ 1 -ge 9 ]]
+ JAVA_OPT=' -Xms1g -Xmx1g -Xmn512m -Dnacos.standalone=true -Dnacos.member.list= -Djava.ext.dirs=/usr/lib/jvm/java-1.8.0-openjdk/jre/lib/ext:/usr/lib/jvm/java-1.8.0-openjdk/lib/ext:/home/nacos/plugins/health:/home/nacos/plugins/cmdb:/home/nacos/plugins/mysql'
+ JAVA_OPT=' -Xms1g -Xmx1g -Xmn512m -Dnacos.standalone=true -Dnacos.member.list= -Djava.ext.dirs=/usr/lib/jvm/java-1.8.0-openjdk/jre/lib/ext:/usr/lib/jvm/java-1.8.0-openjdk/lib/ext:/home/nacos/plugins/health:/home/nacos/plugins/cmdb:/home/nacos/plugins/mysql -Xloggc:/home/nacos/logs/nacos_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M'
+ JAVA_OPT=' -Xms1g -Xmx1g -Xmn512m -Dnacos.standalone=true -Dnacos.member.list= -Djava.ext.dirs=/usr/lib/jvm/java-1.8.0-openjdk/jre/lib/ext:/usr/lib/jvm/java-1.8.0-openjdk/lib/ext:/home/nacos/plugins/health:/home/nacos/plugins/cmdb:/home/nacos/plugins/mysql -Xloggc:/home/nacos/logs/nacos_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dnacos.home=/home/nacos'
+ JAVA_OPT=' -Xms1g -Xmx1g -Xmn512m -Dnacos.standalone=true -Dnacos.member.list= -Djava.ext.dirs=/usr/lib/jvm/java-1.8.0-openjdk/jre/lib/ext:/usr/lib/jvm/java-1.8.0-openjdk/lib/ext:/home/nacos/plugins/health:/home/nacos/plugins/cmdb:/home/nacos/plugins/mysql -Xloggc:/home/nacos/logs/nacos_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dnacos.home=/home/nacos -jar /home/nacos/target/nacos-server.jar'
+ JAVA_OPT=' -Xms1g -Xmx1g -Xmn512m -Dnacos.standalone=true -Dnacos.member.list= -Djava.ext.dirs=/usr/lib/jvm/java-1.8.0-openjdk/jre/lib/ext:/usr/lib/jvm/java-1.8.0-openjdk/lib/ext:/home/nacos/plugins/health:/home/nacos/plugins/cmdb:/home/nacos/plugins/mysql -Xloggc:/home/nacos/logs/nacos_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dnacos.home=/home/nacos -jar /home/nacos/target/nacos-server.jar '
+ JAVA_OPT=' -Xms1g -Xmx1g -Xmn512m -Dnacos.standalone=true -Dnacos.member.list= -Djava.ext.dirs=/usr/lib/jvm/java-1.8.0-openjdk/jre/lib/ext:/usr/lib/jvm/java-1.8.0-openjdk/lib/ext:/home/nacos/plugins/health:/home/nacos/plugins/cmdb:/home/nacos/plugins/mysql -Xloggc:/home/nacos/logs/nacos_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dnacos.home=/home/nacos -jar /home/nacos/target/nacos-server.jar  --spring.config.additional-location=file:/home/nacos/conf/'
+ JAVA_OPT=' -Xms1g -Xmx1g -Xmn512m -Dnacos.standalone=true -Dnacos.member.list= -Djava.ext.dirs=/usr/lib/jvm/java-1.8.0-openjdk/jre/lib/ext:/usr/lib/jvm/java-1.8.0-openjdk/lib/ext:/home/nacos/plugins/health:/home/nacos/plugins/cmdb:/home/nacos/plugins/mysql -Xloggc:/home/nacos/logs/nacos_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dnacos.home=/home/nacos -jar /home/nacos/target/nacos-server.jar  --spring.config.additional-location=file:/home/nacos/conf/ --spring.config.name=application'
+ JAVA_OPT=' -Xms1g -Xmx1g -Xmn512m -Dnacos.standalone=true -Dnacos.member.list= -Djava.ext.dirs=/usr/lib/jvm/java-1.8.0-openjdk/jre/lib/ext:/usr/lib/jvm/java-1.8.0-openjdk/lib/ext:/home/nacos/plugins/health:/home/nacos/plugins/cmdb:/home/nacos/plugins/mysql -Xloggc:/home/nacos/logs/nacos_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dnacos.home=/home/nacos -jar /home/nacos/target/nacos-server.jar  --spring.config.additional-location=file:/home/nacos/conf/ --spring.config.name=application --logging.config=/home/nacos/conf/nacos-logback.xml'
+ JAVA_OPT=' -Xms1g -Xmx1g -Xmn512m -Dnacos.standalone=true -Dnacos.member.list= -Djava.ext.dirs=/usr/lib/jvm/java-1.8.0-openjdk/jre/lib/ext:/usr/lib/jvm/java-1.8.0-openjdk/lib/ext:/home/nacos/plugins/health:/home/nacos/plugins/cmdb:/home/nacos/plugins/mysql -Xloggc:/home/nacos/logs/nacos_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dnacos.home=/home/nacos -jar /home/nacos/target/nacos-server.jar  --spring.config.additional-location=file:/home/nacos/conf/ --spring.config.name=application --logging.config=/home/nacos/conf/nacos-logback.xml --server.max-http-header-size=524288'
+ echo 'Nacos is starting, you can docker logs your container'
Nacos is starting, you can docker logs your container
+ exec /usr/lib/jvm/java-1.8.0-openjdk/bin/java -Xms1g -Xmx1g -Xmn512m -Dnacos.standalone=true -Dnacos.member.list= -Djava.ext.dirs=/usr/lib/jvm/java-1.8.0-openjdk/jre/lib/ext:/usr/lib/jvm/java-1.8.0-openjdk/lib/ext:/home/nacos/plugins/health:/home/nacos/plugins/cmdb:/home/nacos/plugins/mysql -Xloggc:/home/nacos/logs/nacos_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dnacos.home=/home/nacos -jar /home/nacos/target/nacos-server.jar --spring.config.additional-location=file:/home/nacos/conf/ --spring.config.name=application --logging.config=/home/nacos/conf/nacos-logback.xml --server.max-http-header-size=524288

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

2023-01-04 17:40:42,039 INFO Tomcat initialized with port(s): 8848 (http)

2023-01-04 17:40:42,158 INFO Root WebApplicationContext: initialization completed in 4628 ms

2023-01-04 17:40:47,886 INFO Adding welcome page: class path resource [static/index.html]

2023-01-04 17:40:49,107 WARN You are asking Spring Security to ignore Ant [pattern='/**']. This is not recommended -- please use permitAll via HttpSecurity#authorizeHttpRequests instead.

2023-01-04 17:40:49,108 INFO Will not secure Ant [pattern='/**']

2023-01-04 17:40:49,152 INFO Will secure any request with [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@76a82f33, org.springframework.security.web.context.SecurityContextPersistenceFilter@5cc69cfe, org.springframework.security.web.header.HeaderWriterFilter@b672aa8, org.springframework.security.web.csrf.CsrfFilter@209775a9, org.springframework.security.web.authentication.logout.LogoutFilter@4a8ab068, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@21c64522, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@11dee337, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@6bab2585, org.springframework.security.web.session.SessionManagementFilter@ec0c838, org.springframework.security.web.access.ExceptionTranslationFilter@c65a5ef]

2023-01-04 17:40:49,193 INFO Exposing 1 endpoint(s) beneath base path '/actuator'

2023-01-04 17:40:49,291 INFO Tomcat started on port(s): 8848 (http) with context path '/nacos'

2023-01-04 17:40:49,384 INFO Nacos started successfully in stand alone mode. use external storage
[root@VM-12-4-centos containers]# docker ps -s
CONTAINER ID   IMAGE                 COMMAND                  CREATED          STATUS          PORTS                                                                                                                                                 NAMES     SIZE
d56e6021bb76   nacos/nacos-server    "bin/docker-startup.…"   56 seconds ago   Up 51 seconds   0.0.0.0:8848->8848/tcp, :::8848->8848/tcp                                                                                                             nacos     8.35MB (virtual 1.08GB)

这样我们的nacos服务(单机模式)就启动成功了。

访问nacos服务web端也能正常启动成功。

如果服务器是云服务器的话,切记在在安全组或服务器防火墙(不是linux系统防火墙)配置8848端口开放,否则即使系统防火墙开放了8848端口,在本地远程访问nacos服务的可视化界面也会显示连接超时或者网络失败等情况!

另外笔者在这推荐MYSQL_SERVICE_HOST使用服务器指定的ip地址,因为如果有的小伙伴的mysql使用的是docker镜像,而此时指定的nacos上的mysql服务ip为127.0.0.1的话,可能会出现数据源未设置的情况No DataSource set,因为docker中mysql的镜像IP地址是会随docker启动镜像随机分配net的IP的,所属环境不同,ip也就会有差异,从而导致nacos启动异常的出现。

三,Spring Cloud Alibaba Nacos Discovery使用

服务发现是微服务体系结构中的关键组件之一。在这样的体系结构中,为每个客户机手动配置服务列表可能是一项艰巨的任务,并使动态扩展变得极其困难。Nacos Discovery帮助我们将服务自动注册到Nacos服务器,Nacos服务器跟踪服务并动态刷新服务列表。此外,Nacos Discovery向Nacos注册服务实例的一些元数据,例如主机、端口、健康检查URL、主页。

更多了解信息可参考Nacos中文网

Nacos实现服务注册与发现

正常准备一个微服务模块,并在pom中导入相关依赖信息。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>SpringCloudAlibaba</artifactId>
        <groupId>com.yy</groupId>
        <version>1.0.1</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <description>服务提供者8020实现在nacos中的服务注册</description>
    <artifactId>cloud-Nacos-8020</artifactId>
    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>
    <dependency>
        <groupId>com.yy</groupId>
        <artifactId>cloud-common</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies>
</project>

配置服务名称以及nacos的服务地址信息等。

server:
  port: 8020
spring:
  application:
    name: nacos-producer-8020
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
      
management:
  endpoints:
    web:
      exposure:
        include: "*"

默认情况,这时候nacos是作为我们的服务注册与发现的,如果并不像使用,可以设置spring.cloud.nacos.discovery.enabled=false

为了节约时间笔者并没有在项目中使用数据库,而是用模拟数据进行业务的基本效果实现。

package com.yy.service;

import com.yy.clientEntities.TestData;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * Author young
 * Date 2023/1/3 22:57
 * Description: 模拟对数据库的基本操作
 */
@Service
public class TestDataService {
    private static Map<Integer, TestData> col=null;
    private Integer initId=7;
    static {
        col=new HashMap<>();
        col.put(1,new TestData(1,"水浒传",100));
        col.put(2,new TestData(2,"西游记",180));
        col.put(3,new TestData(3,"三国演义",60));
        col.put(4,new TestData(4,"红楼梦",75));
        col.put(5,new TestData(5,"造梦西游",66));
        col.put(6,new TestData(6,"大话西游",97));
    }
    
    //增
    public String add(TestData testData){
        if (testData.getId()==null){
            testData.setId(initId++);
        }
        col.put(testData.getId(),testData);
        return "数据添加成功";
    }
    //删
    public String delete(Integer id){
        col.remove(id);
        return "数据删除成功";
    }
    //改
    public TestData update(TestData testData){
        Assert.notNull(testData,"数据为空");
        return col.replace(testData.getId(), testData);
    }
    //根据id查
    public TestData findOne(Integer id){
        return col.get(id);
    }
    //查全部
    public Collection<TestData> findAll(){
       return col.values();
    }
}

构建controller层的业务接口。

package com.yy.controller;

import com.yy.clientEntities.TestData;
import com.yy.service.TestDataService;
import com.yy.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.util.Collection;

/**
 * Author young
 * Date 2023/1/3 23:11
 * Description: SpringCloudAlibaba
 */
@RestController
@RequestMapping("nacos1")
public class TestController {
    @Autowired
    private TestDataService testDataService;
    @Value("${server.port}")
    private String port;
    @PutMapping("add")
    public Result<String> add(@RequestBody TestData testData){
       return Result.ok(testDataService.add(testData)).message("->端口号为"+port);
    }
    @DeleteMapping("delete/{id}")
    public Result<String> delete(@PathVariable("id")Integer id){
        return Result.ok(testDataService.delete(id)).message("->端口号为"+port);
    }
    @PostMapping("update")
    public Result<TestData> update(@RequestBody TestData testData){
        return Result.ok(testDataService.update(testData)).message("->端口号为"+port);
    }
    @GetMapping("find/{id}")
    public Result<TestData> findOne(@PathVariable("id")Integer id){
        return Result.ok(testDataService.findOne(id)).message("->端口号为"+port);
    }
    @GetMapping("all")
    public Result<Collection<TestData>> all(){
        return Result.ok(testDataService.findAll()).message("->端口号为"+port);
    }
}

然后就可以构建启动类进行测试了。

package com.yy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

/**
 * Author young
 * Date 2023/1/3 21:38
 * Description: nacos服务注册效果实现
 */
@SpringBootApplication
@EnableDiscoveryClient
public class NacosClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(NacosClientApplication.class,args);
    }
}

和Eureka不同的是这里我们只需要一个@EnableDiscoveryClient注解就可以实现服务注册与发现了。而Eureka还需要使用两个注解。

/*标识eureka客户端*/
@EnableEurekaClient
/*服务发现*/
@EnableDiscoveryClient

谁更方便,高下立判。

最后我们在本地运行nacos服务,然后启动项目即可在nacos的web端看到服务注册结果了。需要注意的是,这里顺序不能有错,否则,项目会因为未检测到nacos式服务而启动失败。

Nacos集成负载均衡实现

为了查看配合负载均衡的效果,我们需要准备一个业务模块来作为消费端。然后通过显示的使用 LoadBalanceClient 和 RestTemolate 结合的方式来访问,或者使用FeignClient来实现。因为Feign也集成了Ribbon技术,所以也支持负载均衡(轮询)。在这里笔者用Feign来实现。

创建新的项目模块后导入所需依赖。这里主要用到open Feign以及Nacos Discovery。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>SpringCloudAlibaba</artifactId>
        <groupId>com.yy</groupId>
        <version>1.0.1</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <description>消费端测试nacos注册的服务被调用的负载均衡效果实现</description>
    <artifactId>cloud-Nacos-consumer-8021</artifactId>
    
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.yy</groupId>
        <artifactId>cloud-configuration</artifactId>
        <version>1.0.1</version>
    </dependency>
<!--    openFeign依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
<!--    loadbalancer依赖,由于引入的nacos依赖没继承ribbon 因此手动引入-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-loadbalancer</artifactId>
    </dependency>
    <dependency>
        <groupId>com.yy</groupId>
        <artifactId>cloud-common</artifactId>
        <version>${myproject.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
<!--    nacos服务注册与发现依赖-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies>
</project>

配置yml文件,在其中暴露服务的EndPoint信息,配置feign的日志信息,方便打印运行情况。

server:
  port: 8021
spring:
  application:
    name: nacos-consumer-8021
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
management:
  endpoints:
    web:
      exposure:
        include: "*"
        
#配置feign日志
logging:
  level:
    com.yy.service.FeignService: debug

新建一个接口类,并上加上注解@FeignClient,并指定需要做负载均衡的服务名称。

package com.yy.service;

import com.yy.clientEntities.TestData;
import com.yy.utils.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

import java.util.Collection;

/**
 * Author young
 * Date 2023/1/4 22:08
 * Description: feign管理服务提供端接口
 */
@FeignClient(value = "nacos-producer-8020")
public interface FeignService {
    @GetMapping("nacos1/find/{id}")
    Result<TestData> findOne(@PathVariable("id") Integer id);

    @GetMapping("nacos1/all")
    Result<Collection<TestData>> all();

    @PutMapping("nacos1/add")
    Result<String> add(@RequestBody TestData testData);

    @PostMapping("naacos1/update")
    Result<TestData> update(@RequestBody TestData testData);

    @DeleteMapping("nacos1/delete/{id}")
    Result<String> delete(@PathVariable("id") Integer id);
}

编写消费端的服务调用接口,实现对8020服务的调用。

package com.yy.controller;

import com.yy.clientEntities.TestData;
import com.yy.service.FeignService;
import com.yy.utils.Result;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Collection;

/**
 * Author young
 * Date 2023/1/4 22:07
 * Description: SpringCloudAlibaba
 */
@RestController
@RequestMapping("feign")
public class ConsumerController {
    @Resource
    private FeignService feignService;


    @GetMapping("find/{id}")
   public Result<TestData> findOne(@PathVariable("id") Integer id){
      return feignService.findOne(id);
    }

    @GetMapping("all")
    Result<Collection<TestData>> all() {
        return feignService.all();
    }

    @PutMapping("add")
    Result<String> add(@RequestBody TestData testData){
        return feignService.add(testData);
    }

    @PostMapping("update")
    Result<TestData> update(@RequestBody TestData testData){
        return feignService.update(testData);
    }

    @DeleteMapping("delete/{id}")
    Result<String> delete(@PathVariable("id") Integer id){
        return feignService.delete(id);
    }
}

为了节省代码量,这里并不做更多的服务提供端了。而是通过复制配置,模拟两个服务提供方即可,另一个服务端口为8023。

分别运行三个服务成功后,nacos上的web界面即可看到三个服务全部注册成功。

然后分别对接口进行测试。

再次刷新接口后即可发现调用服务端口变为了8023,即实现了轮询的负载均衡。

Nacos与其他注册中心特性对比

NACOS

EUREKA

CONSUL

COREDNS

ZOOKEEPER

一致性协议

CP+AP

AP

CP

/

CP

健康检查

TCP/HTTP/MySQL/Client Beat

Client Beat

TCP/HTTP/gRPC/Cmd

/

Client Beat

负载均衡

权重/DSL/metadada/CMDB

Ribbon

Fabio

RR

/

雪崩保护

支持

支持

不支持

不支持

不支持

自动注销实例

支持

支持

不支持

不支持

支持

访问协议

HTTP/DNS/UDP

HTTP

HTTP/DNS

DNS

TCP

监听支持

支持

支持

支持

不支持

支持

多数据中心

支持

支持

支持

不支持

不支持

跨注册中心

支持

不支持

支持

不支持

不支持

SpringCloud集成

支持

支持

支持

不支持

不支持

Dubbo集成

支持

不支持

不支持

不支持

支持

K8s集成

支持

不支持

支持

支持

不支持

四,Spring Cloud Alibaba Nacos Config使用

Nacos配置中心说明

Nacos 提供用于存储配置和其他元数据的 key/value 存储,为分布式系统中的外部化配置提供服务器端和客户端支持。使用 Spring Cloud Alibaba Nacos Config,我们可以在 Nacos Server 集中管理 Spring Cloud 应用的外部属性配置。

Spring Cloud Alibaba Nacos Config 是 Config Server 和 Client 的替代方案,客户端和服务器上的概念与 Spring Environment 和 PropertySource 有着一致的抽象,在特殊的 bootstrap 阶段,配置被加载到 Spring 环境中。当应用程序从开发到测试再到生产时,我们可以管理这些环境之间的配置,并确保应用程序具有迁移时需要运行的所有内容。

Nacos Config同SpringCloud-Config一样,在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置之后,才能保证项目的正常启动。springboot中配置文件的加载是存在优先级顺序的,bootstrap优先级高于application。

因此首先需要nacos中配置一些需要使用的相关配置,直接在可视化界面上配置即可。

这里我们需要注意的是Data ID的命名格式,在 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 的拼接格式变成 ${prefix}.${file-extension}

  • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 和 yaml 类型。

因为在微服务项目中,配置文件为yml或properties格式,但是并没有yaml,所以在这里nacos配置中的yaml就对应的yml文件配置格式。这里可以看出nacos是支持profile的配置的,spring-cloud-starter-alibaba-nacos-config 在加载配置的时候,不仅仅加载了以 dataId 为 ${spring.application.name}.${file-extension:properties} 为前缀的基础配置,还加载了dataId为 ${spring.application.name}-${profile}.${file-extension:properties} 的基础配置。在日常开发中如果遇到多套环境下的不同配置,可以通过Spring 提供的 ${spring.profiles.active} 这个配置项来配置。但是需要注意的是:${spring.profiles.active} 当通过配置文件来指定时必须放在 bootstrap的文件中。

这样我们构建三个配置文件以便测试。

这里能注意到nacos可以使用Data ID和Group来区分不同配置。

Data ID指的是Nacos 中的某个配置集的 ID。一个配置集可能包含了数据源、线程池、日志级别等配置项,因此nacos使用配置集 ID 来标识这些配置项的集合。配置集 ID 是组织划分配置的维度之一。Data ID 通常用于组织划分系统的配置集。一个系统或者应用可以包含多个配置集,每个配置集都可以被一个有意义的名称标识。Data ID 通常采用类 Java 包(如 com.yy.log.level)的命名规则保证全局唯一性。此命名规则非强制。

Group是指Nacos 中的一组配置集,是组织配置的维度之一。通过一个有意义的字符串(如 Buy 或 Trade )对配置集进行分组,从而区分 Data ID 相同的配置集。当我们在 Nacos 上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用 DEFAULT_GROUP 。在微服务中可以用来将不同的服务配置进行分组。

除此以外,nacos还提供了命名空间(namespace)来使用,命名空间用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。

创建新的命令空间后,我们就能实现更细粒度的配置管理。

Data ID、Group和namespace之间的联系类似于java项目中的包名与类名的关系,大致关系图如下:

  • NameSpace:命名空间 默认为public,其作用可以用来实现环境隔离作用,比如我们的开发环境、测试环境、生产环境。

  • Group:默认分组为DEFAULT_GROUP,Group 可以将不同的微服务进行分组划分。

  • Service/DataId: 也就是微服务工程,一个微服务工程可以有多个集群中心,比如一个消费者工程可以使用两个服务中心作为集群,每个中心读取不同的配置文件,每个中心内可以有多个实例实现集群。

配置读取测试

在项目中使用Nacos来实现应用外部化配置时,首先需要导入相关依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>SpringCloudAlibaba</artifactId>
        <groupId>com.yy</groupId>
        <version>1.0.1</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <description>nacos配置中心-8022</description>
    <artifactId>cloud-NacosConfig-8022</artifactId>
    
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
<dependencies>
<!--    nacos配置中心-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
<!--    读取bootstrap配置依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-bootstrap</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
<!--    nacos服务注册与发现依赖-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
<!--    服务监控-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>
</project>

在编写yml配置文件时,也需要像SpringCloud-Config一样,必须使用 bootstrap.yml配置文件,来配置Nacos Server 地址(properties格式的配置文件也行)

server:
  port: 8022
spring:
  application:
    name: nacos-config
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #nacos服务注册中心地址
      config:
        server-addr: localhost:8848 #Nacos Server 地址
        file-extension: yaml #显示的声明 dataId 文件扩展名
        #group: DEV_GROUP 默认为DEFAULT_GROUP
        #namespace: a63d7050-3dd9-41f5-a420-6f6e97e0051a  指明不同的命名空间

这里在读取不同分组中的配置信息的时候,我们可以通过配置

spring.cloud.nacos.config.group=GROUP_NAME

来制定对应的组名,在没有明确指定 ${spring.cloud.nacos.config.group} 配置的情况下, 默认使用的是 DEFAULT_GROUP 。需要注意的是:该配置必须放在 bootstrap.yml 文件中,并且必须和nacos平台中配置的组名一致。

对于不同的命名空间,在没有明确指定 ${spring.cloud.nacos.config.namespace} 配置的情况下, 默认使用的是 Nacos 上 Public 这个namespace。如果需要使用自定义的命名空间,可以通过以下配置来实现:

spring.cloud.nacos.config.namespace=b3404bc0-d7dc-4855-b519-570ed34b62d7

和Group配置一样,该配置也必须放在 bootstrap.yml文件中。此外 spring.cloud.nacos.config.namespace 的值是 namespace 对应的 id,id 值可以在 Nacos 的控制台获取。并且在添加配置时注意不要选择其他的 namespace,否则将会导致读取不到正确的配置。

然后我们通过application.yml文件来控制读取不同环境的信息

spring:
  profiles:
    active: test

最后编写一个controller类来测试读取信息结果,并添加 Spring Cloud 原生注解 @RefreshScope 实现配置自动更新。这样当我们修改配置中心的配置时,可以实现配置实时刷新。

package com.yy.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Author young
 * Date 2023/1/5 22:18
 * Description: 读取配置中心的配置信息
 */
@RestController
@RequestMapping("read")
//自动刷新配置
@RefreshScope 
public class ReadMsgController {
    @Value("${spring.datasource.username}")
    private String username;
    @Value("${spring.datasource.password}")
    private String password;
    
    @GetMapping("msg")
    public String msg() {
        return "读取的信息为:"+username+"\n"+password;
    }
}

测试后端接口后成功得到读取得到的配置信息。

并且在更改nacos配置中心的相关配置信息后,仍然能实时得到修改后的配置信息结果。

非常实时,相较于Spring Cloud Config结合Spring Cloud Bus设置消息总线,然后等配种中心服务刷新客户端配置这些操作等等才能实现刷新配置来说,简直不要太香。

后续微服务的学习过程会陆续总结出来……

需要nacos-server2.2.0的压缩包的小伙伴可以自行到我博客上的资源进行下载哦

猜你喜欢

转载自blog.csdn.net/qq_42263280/article/details/128571624