找回密码
 立即注册
首页 业界区 业界 Nacos简介—1.Nacos使用简介

Nacos简介—1.Nacos使用简介

轨项尺 前天 22:09
大纲
1.Nacos的在服务注册中心 + 配置中心中的应用
2.Nacos 2.x最新版本下载与目录结构
3.Nacos 2.x的数据库存储与日志存储
4.Nacos 2.x服务端的startup.sh启动脚本
5.Dubbo + Nacos微服务RPC调用开发示例
6.Nacos对临时与持久化服务实例的健康检查机制
7.Nacos保护阈值机制防止高并发下出现服务雪崩
8.Nacos保护阈值机制开启后的CAP问题
9.集成Nacos注册中心和配置中心的项目演示
 
1.Nacos的在服务注册中心 + 配置中心中的应用
(1)Nacos作为服务注册中心
(2)Nacos作为配置中心
 
Nacos的两大应用场景分别是:
一.微服务技术体系下的服务注册中心
二.配置中心
 
(1)Nacos作为服务注册中心
1.webp
(2)Nacos作为配置中心
每个系统都会有很多配置信息。比如数据库连接池的配置、RocketMQ的配置、Redis的配置,都会写在Spring Boot项目下的application.yml静态配置文件。如果需要修改配置信息,就需要重新打包、重启系统进行重新部署发布。
 
所以,可以将这些配置信息写到Nacos中进行存储,然后各个系统监听Nacos中的数据变化。这样当需要修改配置信息时,只需要到Nacos中修改对应的数据即可。
 
2.Nacos 2.x最新版本下载与目录结构
下载地址:
  1. https://github.com/alibaba/nacos/releases
复制代码
如下是nacos-server-2.1.2.zip的目录结构:
2.webp
如下是对应的Source code(zip)的目录结构:
3.webp
 
3.Nacos 2.x服务端的数据库存储与日志存储
4.webp
数据库初始化的脚本和日志存储的配置文件位于如下位置:
5.webp
 
4.Nacos 2.x服务端的startup.sh启动脚本
(1)服务端的startup.sh启动脚本与JVM参数
(2)Nacos 2.x服务端的单机模式启动命令
(3)Nacos 2.x服务端的三节点集群化部署
 
(1)服务端的startup.sh启动脚本与JVM参数
通过如下命令启动Nacos服务端。
  1. $ java -jar ${BASE_DIR}/target/${SERVER}.jar
复制代码
  1. #!/bin/bash
  2. # Copyright 1999-2018 Alibaba Group Holding Ltd.
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #      http://www.apache.org/licenses/LICENSE-2.0
  7. #
  8. # Unless required by applicable law or agreed to in writing, software
  9. # distributed under the License is distributed on an "AS IS" BASIS,
  10. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. # See the License for the specific language governing permissions and
  12. # limitations under the License.
  13. cygwin=false
  14. darwin=false
  15. os400=false
  16. case "`uname`" in
  17. CYGWIN*) cygwin=true;;
  18. Darwin*) darwin=true;;
  19. OS400*) os400=true;;
  20. esac
  21. error_exit ()
  22. {
  23.     echo "ERROR: $1 !!"
  24.     exit 1
  25. }
  26. [ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=$HOME/jdk/java
  27. [ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/java
  28. [ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/opt/taobao/java
  29. [ ! -e "$JAVA_HOME/bin/java" ] && unset JAVA_HOME
  30. if [ -z "$JAVA_HOME" ]; then
  31.   if $darwin; then
  32.     if [ -x '/usr/libexec/java_home' ] ; then
  33.       export JAVA_HOME=`/usr/libexec/java_home`
  34.     elif [ -d "/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home" ]; then
  35.       export JAVA_HOME="/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home"
  36.     fi
  37.   else
  38.     JAVA_PATH=`dirname $(readlink -f $(which javac))`
  39.     if [ "x$JAVA_PATH" != "x" ]; then
  40.       export JAVA_HOME=`dirname $JAVA_PATH 2>/dev/null`
  41.     fi
  42.   fi
  43.   if [ -z "$JAVA_HOME" ]; then
  44.         error_exit "Please set the JAVA_HOME variable in your environment, We need java(x64)! jdk8 or later is better!"
  45.   fi
  46. fi
  47. export SERVER="nacos-server"
  48. export MODE="cluster"
  49. export FUNCTION_MODE="all"
  50. export MEMBER_LIST=""
  51. export EMBEDDED_STORAGE=""
  52. while getopts ":m:f:s:c:p:" opt
  53. do
  54.     case $opt in
  55.         m)
  56.             MODE=$OPTARG;;
  57.         f)
  58.             FUNCTION_MODE=$OPTARG;;
  59.         s)
  60.             SERVER=$OPTARG;;
  61.         c)
  62.             MEMBER_LIST=$OPTARG;;
  63.         p)
  64.             EMBEDDED_STORAGE=$OPTARG;;
  65.         ?)
  66.         echo "Unknown parameter"
  67.         exit 1;;
  68.     esac
  69. done
  70. export JAVA_HOME
  71. export JAVA="$JAVA_HOME/bin/java"
  72. export BASE_DIR=`cd $(dirname $0)/..; pwd`
  73. export CUSTOM_SEARCH_LOCATIONS=file:${BASE_DIR}/conf/
  74. #===========================================================================================
  75. # JVM Configuration
  76. #===========================================================================================
  77. if [[ "${MODE}" == "standalone" ]]; then
  78.     JAVA_OPT="${JAVA_OPT} -Xms512m -Xmx512m -Xmn256m"
  79.     JAVA_OPT="${JAVA_OPT} -Dnacos.standalone=true"
  80. else
  81.     if [[ "${EMBEDDED_STORAGE}" == "embedded" ]]; then
  82.         JAVA_OPT="${JAVA_OPT} -DembeddedStorage=true"
  83.     fi
  84.     JAVA_OPT="${JAVA_OPT} -server -Xms2g -Xmx2g -Xmn1g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
  85.     JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${BASE_DIR}/logs/java_heapdump.hprof"
  86.     JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages"
  87. fi
  88. if [[ "${FUNCTION_MODE}" == "config" ]]; then
  89.     JAVA_OPT="${JAVA_OPT} -Dnacos.functionMode=config"
  90. elif [[ "${FUNCTION_MODE}" == "naming" ]]; then
  91.     JAVA_OPT="${JAVA_OPT} -Dnacos.functionMode=naming"
  92. fi
  93. JAVA_OPT="${JAVA_OPT} -Dnacos.member.list=${MEMBER_LIST}"
  94. JAVA_MAJOR_VERSION=$($JAVA -version 2>&1 | sed -E -n 's/.* version "([0-9]*).*$/\1/p')
  95. if [[ "$JAVA_MAJOR_VERSION" -ge "9" ]] ; then
  96.   JAVA_OPT="${JAVA_OPT} -Xlog:gc*:file=${BASE_DIR}/logs/nacos_gc.log:time,tags:filecount=10,filesize=102400"
  97. else
  98.   JAVA_OPT_EXT_FIX="-Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/ext"
  99.   JAVA_OPT="${JAVA_OPT} -Xloggc:${BASE_DIR}/logs/nacos_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M"
  100. fi
  101. JAVA_OPT="${JAVA_OPT} -Dloader.path=${BASE_DIR}/plugins,${BASE_DIR}/plugins/health,${BASE_DIR}/plugins/cmdb,${BASE_DIR}/plugins/selector"
  102. JAVA_OPT="${JAVA_OPT} -Dnacos.home=${BASE_DIR}"
  103. JAVA_OPT="${JAVA_OPT} -jar ${BASE_DIR}/target/${SERVER}.jar"
  104. JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}"
  105. JAVA_OPT="${JAVA_OPT} --spring.config.additional-location=${CUSTOM_SEARCH_LOCATIONS}"
  106. JAVA_OPT="${JAVA_OPT} --logging.config=${BASE_DIR}/conf/nacos-logback.xml"
  107. JAVA_OPT="${JAVA_OPT} --server.max-http-header-size=524288"
  108. if [ ! -d "${BASE_DIR}/logs" ]; then
  109.   mkdir ${BASE_DIR}/logs
  110. fi
  111. echo "$JAVA $JAVA_OPT_EXT_FIX ${JAVA_OPT}"
  112. if [[ "${MODE}" == "standalone" ]]; then
  113.     echo "nacos is starting with standalone"
  114. else
  115.     echo "nacos is starting with cluster"
  116. fi
  117. # check the start.out log output file
  118. if [ ! -f "${BASE_DIR}/logs/start.out" ]; then
  119.   touch "${BASE_DIR}/logs/start.out"
  120. fi
  121. # start
  122. echo "$JAVA $JAVA_OPT_EXT_FIX ${JAVA_OPT}" > ${BASE_DIR}/logs/start.out 2>&1 &
  123. if [[ "$JAVA_OPT_EXT_FIX" == "" ]]; then
  124.   nohup "$JAVA" ${JAVA_OPT} nacos.nacos >> ${BASE_DIR}/logs/start.out 2>&1 &
  125. else
  126.   nohup "$JAVA" "$JAVA_OPT_EXT_FIX" ${JAVA_OPT} nacos.nacos >> ${BASE_DIR}/logs/start.out 2>&1 &
  127. fi
  128. echo "nacos is starting,you can check the ${BASE_DIR}/logs/start.out"
复制代码
(2)Nacos 2.x服务端的单机模式启动命令
  1. $ cd nacos/bin
  2. $ nohup sh startup.sh -m standalone &
复制代码
(3)Nacos 2.x服务端的三节点集群化部署
集群间的数据交互机制是通过MySQL来实现的。
 
一.修改各节点的系统配置文件application.properties
第一个节点监听的端口是8848。
第二个节点监听的端口是8858。
第三个节点监听的端口是8868。
 
二.配置各节点的集群配置文件cluster.conf
配置好三个节点的地址和端口。
 
5.Dubbo + Nacos微服务RPC调用开发示例
其实只需要在配置文件里进行配置即可,与Nacos相关的配置项其实就是:dubbo.registry.address和spring.cloud.nacos.discovery.server-addr。
 
一.进行服务注册的微服务配置
  1. spring.application.name=demo-dubbo-nacos-ServiceA
  2. dubbo.scan.base-packages=com.demo.dubbo.nacos
  3. dubbo.protocol.name=dubbo
  4. dubbo.protocol.port=20880
  5. dubbo.registry.address=spring-cloud://localhost
  6. spring.cloud.nacos.discovery.server-addr=192.168.31.152:8848,192.168.31.152:8858,192.168.31.152:8868
  7. spring.datasource.type: com.alibaba.druid.pool.DruidDataSource
  8. spring.datasource.url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8
  9. spring.datasource.username: root
  10. spring.datasource.password: root
  11. spring.datasource.driverClassName: com.mysql.jdbc.Driver
  12. spring.datasource.initialSize: 1
  13. spring.datasource.minIdle: 1
  14. spring.datasource.maxActive: 50
  15. spring.datasource.maxWait: 60000
  16. spring.datasource.timeBetweenEvictionRunsMillis: 60000  
  17. spring.datasource.minEvictableIdleTimeMillis: 300000
  18. spring.datasource.validationQuery: SELECT 1 FROM DUAL
  19. spring.datasource.testWhileIdle: true
  20. spring.datasource.testOnBorrow: false  
  21. spring.datasource.testOnReturn: false  
  22. spring.datasource.poolPreparedStatements: true
  23. spring.datasource.maxPoolPreparedStatementPerConnectionSize: 20
  24. spring.datasource.filters: stat,wall,log4j
  25. spring.datasource.connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
复制代码
二.进行服务调用的微服务配置
  1. spring.application.name=demo-dubbo-nacos-ServiceB
  2. dubbo.cloud.subscribed-services=demo-dubbo-nacos-ServiceA
  3. dubbo.scan.base-packages=com.demo.dubbo.nacos
  4. spring.cloud.nacos.discovery.server-addr=192.168.31.152:8848,192.168.31.152:8858,192.168.31.152:8868
复制代码
 
6.Nacos对临时与持久化服务实例的健康检查机制
(1)Nacos有两种健康检查机制
(2)Nacos对临时的服务实例进行健康检查的机制
(3)Nacos对持久化的服务实例进行健康检查的机制
 
(1)Nacos有两种健康检查机制
作为服务注册中心,一般都会有健康检查机制。Nacos的健康检查机制会根据两种不同的服务实例进行分别处理。一种是临时的服务实例,一种是持久化的服务实例。对于不同的服务实例,Nacos的健康探测机制会不一样。
 
Dubbo服务实例向Nacos进行服务注册时需要带上一个参数[ephemeral]。这个[ephemeral]参数可取两个值:临时和持久化。分别表示注册的服务实例是临时的和持久化的。一般不用主动设置该参数,默认情况下的服务实例都是临时的。
 
(2)Nacos对临时的服务实例进行健康检查的机制
临时的服务实例默认会每隔5s上报一次心跳给Nacos,Nacos如果15s没收到心跳就标记该服务实例为不健康,Nacos如果超过30s没收到心跳就摘除这个服务实例。
 
(3)Nacos对持久化的服务实例进行健康检查的机制
Nacos会每隔20s主动对服务实例检查一次。如果检查失败,发现服务实例为不健康状态,也不会摘除这个服务实例。默认情况下,不健康的服务实例Nacos是不会返回的。
 
7.Nacos保护阈值机制防止高并发下出现服务雪崩
如果健康的服务实例比例太低,会导致健康的服务实例请求压力过大。可能导致服务实例被打死,从而引发服务雪崩,所以引入了保护阈值。
 
保护阈值,可以设置为0~1之间的比例。如果健康的服务实例比例太低,则把不健康的服务实例也返回服务调用方。此时会有很多请求交给不健康的服务实例来处理,会导致请求失败,但可以避免健康的服务实例出现因为请求流量过大而被压垮的问题。Nacos的保护阈值牺牲了一致性,得到了可用性。
 
假设有10个服务实例,每个服务实例的极限QPS是700,当前QPS是500。同时假设保护阈值=0.8。
 
情况一:如果仅仅有2个服务实例宕机,此时Nacos是不会去触发保护阈值的。此时每秒的5000请求会分配给8个服务实例,每个服务实例QPS是600+。每个服务实例都不会被压垮,因为每个服务实例的极限QPS是700。
 
情况二:如果有4个服务实例宕机了,只剩下6个健康的服务实例。那么每秒的5000个请求分配给6个服务实例,每个服务实例QPS是800+。此时就会导致服务实例被压垮,所以需要Nacos触发保护阈值0.8。不能让请求分配给6个服务实例,而是继续让6健康 + 4不健康一起处理。
 
8.Nacos保护阈值机制开启后的CAP问题
CAP:Consistency(一致性)、Available(可用性)、Partition(网络分区)。网络分区、一致性和可用性是不能同时兼得的。Nacos的保护阈值牺牲了一致性,得到了可用性。
 
9.集成Nacos注册中心和配置中心的项目演示
(1)集成Nacos注册中心
(2)集成Nacos配置中心
 
(1)集成Nacos注册中心
首先需要把订单服务、库存服务两个服务都注册到Nacos中去。库存服务要告诉Nacos注册中心,它的IP地址具体是多少。订单服务需要从Nacos注册中心获取库存服务登记的IP地址。这样订单服务才能找到库存服务,进行服务调用。
 
库存服务如何实现将服务注册到Nacos中:
步骤一:在pom.xml文件中引入Nacos注册中心的依赖
  1. <dependency>
  2.     <groupId>com.alibaba.cloud</groupId>
  3.     spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  4. </dependency>
复制代码
步骤二:application.properties中配置Nacos服务地址
更多详细的配置可以参考地址:
  1. https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-discovery
复制代码
  1. spring:
  2.     application:
  3.         name: stock-service
  4.     cloud:
  5.         nacos:
  6.             # 注册中心
  7.             discovery:
  8.                 server-addr: http://127.0.0.1:8848
复制代码
步骤三:启动库存服务
此时查看Nacos控制台,就多了一个stock-service的服务了。
6.webp
点击stock-service服务的详情进行查看,可以发现其IP和Port都登记好了。
7.webp
订单服务也是一样的步骤,将服务注册到Nacos中。
 
步骤四:通过服务中心进行服务调用演示
在order-service订单服务中,通过使用Feign来调用库存服务。
  1. package com.demo.order.service;
  2. import com.demo.order.feign.StockService;
  3. import lombok.AllArgsConstructor;
  4. import org.springframework.stereotype.Service;
  5. @Service
  6. @AllArgsConstructor
  7. public class OrderService {
  8.     private final StockService stockService;
  9.     public Integer getProductStock(Integer productId) {
  10.         return stockService.selectStockByProductId(productId);
  11.     }
  12. }
  13. —————————————————————————————————————————————————————————————
  14. package com.demo.order.feign;
  15. import org.springframework.cloud.openfeign.FeignClient;
  16. import org.springframework.web.bind.annotation.GetMapping;
  17. import org.springframework.web.bind.annotation.RequestParam;
  18. @FeignClient(name = "stock-service")
  19. public interface StockService {
  20.     //查询库存
  21.     @GetMapping(value = "/stock/getStockByProductId")
  22.     Integer selectStockByProductId(@RequestParam("productId") Integer productId);
  23. }
复制代码
(2)集成Nacos配置中心
问题:为什么要选用Nacos?
Nacos比其他注册中心多了一个配置中心,可以统一管理项目的配置文件。并且能够做到无需重启项目,也能感知配置文件的修改。
 
步骤一:在Nacos控制台创建对应的配置文件
打开Nacos后台,配置管理 -> 配置列表 -> 点击+号,创建一个配置文件。
8.webp
9.webp
这里的Data ID可以理解为配置文件名字,具有唯一性。Groups相当于分组,可以分不同的环境、不同的业务。配置格式这里选择的是YAML,最后按照所选格式,把配置内容放进去。
 
步骤二:引入Nacos配置服务依赖
在Spring Boot项目的pom.xml文件中,引入Nacos配置中心的Maven依赖;
  1. <dependency>
  2.     <groupId>com.alibaba.cloud</groupId>
  3.     spring-cloud-starter-alibaba-nacos-config</artifactId>
  4. </dependency>
复制代码
步骤三:修改配置文件名
把配置文件的文件名改成bootstrap.yml,默认是application.yml。
 
步骤四:配置Nacos配置中心信息
在bootstrap.yml文件中,新增Nacos配置中心相关配置:
  1. spring:
  2.     application:
  3.         name: stock-service
  4.         cloud:
  5.             nacos:
  6.                 # 配置中心
  7.                 config:server-addr: http://124.223.102.236:8848
  8.                     ## 配置文件前缀
  9.                     prefix: stock-service
  10.                     # 配置文件类型
  11.                     file-extension: yml
  12.                 # 注册中心
  13.                 discovery:
  14.                     server-addr: http://124.223.102.236:8848
复制代码
步骤五:配置中心演示
下面在stock-service库存服务中编写一个User实体类代码,进行测试。@Value注解的意思就是从配置文件中去读取这个属性。@RefreshScope这个注解是表示动态刷新,动态感知配置文件变化。如果不加这个注解,修改Nacos上的配置文件,则不会有动态刷新效果。
  1. @Data
  2. @Component
  3. @RefreshScope
  4. public class User {
  5.     @Value("${user.userName}")
  6.     private String userName;
  7. }
复制代码
编写一个Controller来测试,原本数据是李四。在Nacos控制台,把配置文件中的usereName属性,修改成王五后,项目不需要重新启动也能动态改变原来的值。
  1. @RestController
  2. @AllArgsConstructor
  3. @RequestMapping("/user")
  4. public class UserController {
  5.     private final User user;
  6.    
  7.     @GetMapping("/getUserName")
  8.     public String getUserName() {
  9.         return user.getUserName();
  10.     }
  11. }
复制代码
(3)客户端的版本选择
Nacos服务端使用什么版本,其他组件也有对应使用版本要求。所以一开始在组件选型时,得先了解一下版本的选择,如下:
10.webp
Demo项目里的Nacos使用版本是1.4.1,那么对应Spring Cloud Alibaba的版本至少是2.2.4 Release。如下:
  1. <properties>
  2.     <java.version>1.8</java.version>
  3.     <spring-cloud-alibaba.version>2.2.5.RELEASE</spring-cloud-alibaba.version>
  4. </properties>
复制代码
 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册