Nacos
Nacos是什么?
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
Nacos功能特性
-
服务发现与健康检查
动态服务发现对以服务为中心的(例如微服务和云原生)应用架构方式非常关键。Nacos支持DNS-Based和RPC-Based(Dubbo、gRPC)模式的服务发现。Nacos也提供实时健康检查,以防止将请求发往不健康的主机或服务实例。借助Nacos,您可以更容易地为您的服务实现断路器。
-
动态配置管理
动态配置服务让您能够以中心化、外部化和动态化的方式管理所有环境的配置。动态配置消除了配置变更时重新部署应用和服务的需要。配置中心化管理让实现无状态服务更简单,也让按需弹性扩展服务更容易。
-
动态DNS服务
通过支持权重路由,动态DNS服务能让您轻松实现中间层负载均衡、更灵活的路由策略、流量控制以及简单数据中心内网的简单DNS解析服务。动态DNS服务还能让您更容易地实现以DNS协议为基础的服务发现,以消除耦合到厂商私有服务发现API上的风险。
-
服务和元数据管理
nacos给我们提供了管理界面,从管理平台的角度,可以看到注册的服务及其实例信息,动态的服务权重调整,优雅的服务上线、下线
Nacos的安装部署
在这里我们简单介绍下nacos的单实例服务部署
nacos下载
可以从git上下载最新的压缩包,下载地址 https://github.com/alibaba/nacos/releases ,Windows版本选择zip安装包就行,当然你也可以下载源码自己编译
这里我们用的最新版本2.1.0版本
安装
下载后会得到一个压缩包,解压到自己想安装的路径即可,这里我们介绍下nacos的配置文件:
进入到安装目录的conf文件夹:
数据库配置
nacos 0.7版本之前使用的是嵌入式数据库(Derby),Derby在使用的时候局限性的,比如不支持多用户操作,数据量大时会导致连接积压。nacos提供了对MySQL的支持。
在安装目录的conf文件夹下,有MySQL的SQL文件1.4.0-ipv6_support-update.sql和nacos-mysql.sql,我们只要在Navicat创建一个nacos数据库,先运行nacos-mysql.sql,再运行1.4.0-ipv6_support-update.sql即可。 1.4.0-ipv6_support-update.sql是1.4之后新增对IPv6的支持,只是修改了字段长度。
启动找到解压文件的bin目录,地址栏输入cmd,回车
然后命令行输入以下命令,standalone代表着单机模式运行,非集群模式。默认是集群模式,目前就启动一个nacos服务端,所以以单机的形式启动。
startup.cmd -m standalone
出现以下界面表示成功:成功之后在浏览器地址栏输入:下图圈住部分
输入上图地址,进入nacos登录页面,nacos管理平台用户名和密码默认都是 nacos
输入用户名和密码进入nacos管理页面,如下:
Nacos服务注册中心
Nacos相关概念
namespace
命名空间,即namespace,namespace是nacos针对于企业级开发设计用来针对于不同环境的区分,比如正在企业开发时有测试环境,生产环境,等其他环境,为了保证不同环境配置实现隔离,提出了namespace的概念。nacos中存在一个默认的命名空间public,所有配置以及服务注册,在没有指定命名空间时都会默认从public这个命名空间拉取配置以及注册到该命名空间下的注册表中!!
举个例子:
一个超市,内部有很多区域对吧!比如零售休闲区、瓜果蔬菜区、生鲜区等等,顺着超市路标指引,我们如果买鱼,直接去生鲜区即可,我们买零食,直接去零食休闲区即可,买个东西无需在超市乱窜…这种区域划分呢,便是物以类聚,环境隔离的思想!!!
使用命名空间主要是为了环境隔离
nacos分组
在nacos中,可以根据业务需求,对不同的服务以及配置进行分组,通过不同的字符串名(分组名)来表示不同的分组,nacos中 如果未显示的指明分组名,那么就会默认的划分在DEFAULT_GROUP
分组之中!
举个列子:
前边已经划分了各个区域namespace了,为什么那还来个分组?简单!零食区中,薯片是放一个柜的吧!!糖是放一个柜的吧!!鲫鱼与鲫鱼是在一起的吧!!猪排与猪排是在一起的吧! 这便是分组,实际上也是一个更细微的环境隔离机制罢了!!!
dataId
Nacos 中的某个配置集的 ID。配置集 ID 是组织划分配置的维度之一。Data ID 通常用于组织划分系统的配置集。一个系统或者应用可以包含多个配置集,每个配置集都可以被一个有意义的名称标识。Data ID 通常采用类 Java 包(如 com.taobao.tc.refund.log.level)的命名规则保证全局唯一性。此命名规则非强制。这个概念来自于官方文档,说人话就是配置文件的名字,相当于主键的作用
下面我们归纳一下:
概念 | 描述 |
---|---|
Namespace | 代表不同的环境,比如开发、测试、预发布、生产 |
Group | 代表某项目,比如云平台、教学服务 |
DataId | 某个项目中具体的配置文件 |
服务提供者搭建
- 在父工程中引入依赖
<dependencyManagement>
<dependencies>
<!-- springCloud alibaba SCA-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${alibaba.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 在项目中引入nacos相关依赖,在这里我们暂时用的feign来进行远程调用
<dependencies>
<!-- web 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- nacos 服务注册中心依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- feign依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
- 配置中心文件
server:
port: 8082
spring:
application:
name: user-service
#nacos相关配置
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 #nacos服务地址
namespace: public #指定namespace 默认为public,一般我们使用分组是为了区分不同的环境如dev、test、beta。。。
register-enabled: true #是否往注册中心注册自己,默认为true (当我们本地开发的时候可以设置成false不往注册中心注册自己避免造成开发测试环境的混乱)
- application启动类代码
/**
* @Description:
* @author: dy
* @Date: 2022/5/25
*/
@SpringBootApplication
//开启注册中心客户端(通用型注解、可以注册到nacos、eureka)
@EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
- 定义一个client
/**
* @Description:
* @author: dy
* @Date: 2021/11/26
*/
//@FeignClient表明当前类是一个feign客户端,value指定该客户端要请求的服务名称(登记到注册中心的服务提供者名称) fallback指定回退类
@FeignClient(value = "user-service",path = UserClient.MAPPING ,fallback = UserFallback.class)
public interface UserClient {
String MAPPING = "/user-service";
@RequestMapping(value = "/get_user_id", method = RequestMethod.GET)
public String getUserId();
}
/**
* @Description:
* @author: dy
*/
@Slf4j
@RestController
@RequestMapping(UserClient.MAPPING)
public class UserResource implements UserClient {
@Override
public String getUserId() {
return "我是user-service";
}
}
服务消费者搭建
- 在父工程中引入依赖
<dependencyManagement>
<dependencies>
<!-- springCloud alibaba SCA-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${alibaba.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 在服务提供者中引入nacos依赖
<dependencies>
<dependency>
<groupId>com.dy.springcloud</groupId>
<artifactId>user-service</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- web 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- nacos 服务注册中心依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
- 配置文件相关配置
server:
port: 8081
spring:
application:
name: user-api
#nacos相关配置
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 #nacos服务地址
namespace: public #指定namespace 默认为public,一般我们使用分组是为了区分不同的环境如dev、test、beta。。。
register-enabled: true #是否往注册中心注册自己,默认为true (当我们本地开发的时候可以设置成false不往注册中心注册自己避免造成开发测试环境的混乱)
- application启动类代码
/**
* @Description:
* @author: dy
* @Date: 2022/5/24
*/
//开启feign客户端功能 basePackages指定要扫描的feignClient类所在包路径
@EnableFeignClients(basePackages = {"com.dy.client.user"})
@SpringBootApplication(scanBasePackages = {
//client指定了fallback,这里要把所有hystrix的fallback注入容器中
"com.dy.client.user.fallback",
//指定了scanBasePackages要把我们本身的bean注入到容器中
"com.dy.api.user"
})
//开启注册中心客户端(通用型注解、可以注册到nacos、eureka)
@EnableDiscoveryClient
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class,args);
}
}
- 定义一个controller
/**
* @Description:
* @author: dy
* @Date: 2022/5/25
*/
@RequestMapping(UserApi.MAPPING)
public interface UserApi {
String MAPPING = "/api/user";
@RequestMapping(value = "/get_user_info", method = RequestMethod.GET)
String getUserInfo();
}
/**
* @Description:
* @author: dy
* @Date: 2022/5/25
*/
@Slf4j
@RestController
public class UserController implements UserApi {
@Autowired
private UserClient userClient;
@Override
public String getUserInfo() {
return userClient.getUserId();
}
}
启动user-service和user-api服务,我就去nacos的管理界面的服务管理就可以看到我们的服务了:
浏览器访问接口http://localhost:8081/api/user/get_user_info:
大功告成!!!
当然我们也可以自己在nacos管理中心自己创建一个空服务:
在这里我们介绍下保护阈值:
可以设置为0-1之间的浮点数,它其实是个比例值(当前服务健康实例数/当前服务总实例 数)一般流程下, nacos是服务注册中心,服务消费者要从nacos获取某个服务的可用实例信息,对于服 务实例有健康/不健康状态之分, nacos在返回给消费者实例信息的时候,会返回健康实例。这个时候在 一些搞并发、大流量场景下会存在一定的问题:
如果服务A有100个实例, 98个实例都不健康了,只有2个实例是健康的,如果nacos只返回这两个健康 实例的信息的话,那么后续消费者的请求将全部被分配到这两个实例,流量洪峰到来, 2个健康的实例 也扛不住了,整个服务A 就扛不住,上游的微服务也会导致崩溃,产生雪崩效应
保护阈值的意义在于: 当服务A健康实例数/总实例数 < 保护阈值 的时候,说明健康实例真的不多了,这个时候保护阈值会被触 发(状态true),nacos将会把该服务所有的实例信息(健康的+不健康的)全部提供给消费者,消费者可能访问到不健康的实例,请求失败,但这样也比造成雪崩要好,牺牲了一些请求,保证了整个系统的一个可用性。
至此,我们就把我们的服务注册到了nacos注册中心上了!!!
源码地址:https://gitee.com/dai-yong-1/dy-springcloud-alibaba