阿里的一个开源产品,是针对微服务架构中的服务发现、配置管理、服务治理的综合型解决方案。 (用来实现配置中心和服务注册中心) 1.四大功能服务发现和服务健康监测(使服务更容易注册,并通过DNS或HTTP接口发现其他服务,还提供服务的实时健康检查,以防 止向不健康的主机或服务实例发送请求。 ) 支持基于DNS和基于RPC的服务发现。服务提供者使用原生SDK、OpenAPI、或一个独立的Agent TODO注册 Service 后,服务消费者可以使用DNS TODO 或HTTP&API查找和发现服务。 Nacos提供对服务的实时的健康检查,阻止向不健康的主机或服务实例发送请求。Nacos 支持传输层 (PING 或 TCP)和应用层 (如 HTTP、MySQL、用户自定义)的健康检查。 对于复杂的云环境和网络拓扑环境中(如 VPC、边缘网络等)服务的健康检查,Nacos 提供了 agent 上报模式和服务端主动检测2种健康检查模式。Nacos 还提供了统一的健康检查仪表盘,帮助您根据健康状态管理服务的可用性及流量。 动态配置服务 以中心化、外部化和动态化的方式管理所有环境的应用配置和服务配置。 消除了配置变更时重新部署应用和服务的需要,让配置管理变得更加高效和敏捷。 配置中心化管理让实现无状态服务变得更简单,让服务按需弹性扩展变得更容易。 提供了一个简洁易用的UI (控制台样例 Demo) 帮助管理所有的服务和应用的配置。 Nacos 还提供包括配置版本跟踪、金丝雀发布、一键回滚配置以及客户端配置更新状态跟踪在内的一系列开箱即用的配置管理特性,能更安全地在生产环境中管理配置变更和降低配置变更带来的风险。 动态 DNS 服务 动态 DNS 服务支持权重路由,更容易地实现中间层负载均衡、更灵活的路由策略、流量控制以及数据中心内网的简单DNS解析服务。动态DNS服务还能更容易地实现以 DNS 协议为基础的服务发现,消除耦合到厂商私有服务发现 API 上的风险。 Nacos 提供了一些简单的 DNS APIs TODO ,管理服务的关联域名和可用的 IP:PORT 列表 服务及其元数据管理 从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略、服务的 SLA 以及最首要的 metrics 统计数据。 2.服务发现在微服务架构中一个业务流程需要多个微服务通过网络接口调用完成业务处理,服务消费方从服务注册中心获取服 务提供方的地址,从而进行远程调用,这个过程叫做服务发现。 2.1.服务发现过程
存在的问题: 在微服务架构中,整个系统会按职责能力划分为多个服务,通过服务之间协作来实现业务目标。服务的消费方要调用服务的生产方,为了完成一次请求,消费方需要知道服务生产方的网络位置(IP地址和端口号)。 微服务可能是部署在云环境的,服务实例的网络位置或许是动态分配的。 每个服务一般会有多个实例来做负载均衡,由于宕机或升级,服务实例网络地址会经常动态改变。 每个服务也可能应对临时访问压力增加新的服务节点。 服务发现概念 服务发现就是服务消费方通过服务发现中心智能发现服务提供方,从而进行远程调用的过程。 服务发现流程: 服务实例本身并不记录服务生产方的网络地址,所有服务实例内部都会包含服务发现客户端。
在每个服务启动时会向服务发现中心上报自己的网络位置。在服务发现中心内部会形成一个服务注册表,服务注册表是服务发现的核心部分,是包含所有服务实例的网络地址的数据库。
服务发现客户端会定期从服务发现中心同步服务注册表 ,并缓存在客户端。
当需要对某服务进行请求时,服务实例通过该注册表,定位目标服务网络地址。若目标服务存在多个网络地址,则使用负载均衡算法从多个服务实例中选择出一个,然后发出请求。 总结,在微服务环境中,由于服务运行实例的网络地址是不断动态变化的,服务实例数量的动态变化 ,因此无法使用固定的配置文件来记录服务提供方的网络地址,必须使用动态的服务发现机制用于实现微服务间的相互感知。 各服务实例会上报自己的网络地址,这样服务中心就形成了一个完整的服务注册表,各服务实例会通过服务发现中心来获取访问目标服务的网络地址,从而实现服务发现的机制。 2.2.服务发现产品对比目前市面上用的比较多的服务发现中心有:Nacos、Eureka、Consul和Zookeeper。
Nacos 需要依赖一定的环境: 64 bit OS,支持 Linux/Unix/Mac/Windows 64 bit JDK 1.8+ Maven 3.2.x+
下载源码或者安装包
从Github上下载源码方式 #从GitHub中下载Nacos git clone https://github.com/alibaba/nacos.git #进入Nacos中 cd nacos/ #安装 mvn ‐Prelease‐nacos clean install ‐U ls ‐al distribution/target/ // change the $version to your actual path cd distribution/target/nacos‐server‐$version/nacos/bin
下载编译后压缩包方式 下载地址:https://github.com/alibaba/nacos/releases 可以从最新稳定版本下载 nacos-server-$version.zip 包,本教程使用nacos-server-1.1.3版本。
启动服务器
Linux/Unix/Mac启动方式: #启动命令(standalone代表着单机模式运行,非集群模式) sh startup.sh -m standalone #如果是ubuntu系统,或者运行脚本报错提示[[符号找不到,可尝试如下运行: bash startup.sh -m standalone
Windows启动方式: #启动命令: cmd startup.cmd #双击startup.cmd运行文件。
检验是否启动成功:浏览器访问 :8848/nacos (启动后会显示访问的地址,如本次访问的是::8848/nacos/index.html),会打开nacos控制台登录页面;
使用默认用户名:nacos,默认密码:nacos ;登录即可打开主页面。
外部mysql数据库支持 单机模式时nacos默认使用嵌入式数据库实现数据的存储,若想使用外部mysql存储nacos数据,需要进行以下步 骤:
安装数据库,版本要求:5.6.5+ ,mysql 8 以下
初始化mysql数据库,新建数据库nacos_config,数据库初始化文件:${nacoshome}/conf/nacosmysql.sql
修改${nacoshome}/conf/application.properties文件,增加支持mysql数据源配置(目前只支持 mysql),添加mysql数据源的url、用户名和密码。 spring.datasource.platform=mysql db.num=1 db.url.0=jdbc:mysql://11.162.196.16:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true db.user=root db.password=123456 4.SpringBoot整合Nacos
在nacos-discovery父工程中添加依赖管理 <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring‐boot‐dependencies</artifactId> <version>2.1.3.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring‐cloud‐dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring‐cloud‐alibaba‐dependencies</artifactId> <version>2.1.0.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
分别在服务提供及服务消费工程中添加依赖,此依赖的作用是服务发现 <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring‐cloud‐starter‐alibaba‐nacos‐discovery</artifactId> </dependency>
服务注册:在服务提供工程中配置nacos服务发现相关的配置: 启动nacos(启动服务提供),观察nacos服务列表,nacos-restful-provider注册成功。 服务名:每个服务在服务注册中心的标识,相当于Java中的类名。
服务发现:在服务消费工程中配置nacos服务发现相关的配置:
服务消费 /*改Controller中远程调用的代码*/ //服务id即注册中心的中的服务名 private String serviceId="nacos‐restful‐provider"; @Autowired LoadBalancerClient loadBalancerClient; @GetMapping(value = "/service") public String service(){ RestTemplate restTemplate = new RestTemplate(); //调用服务 //String providerResult = restTemplate.getForObject("" + providerAddress + "/service",String.class); ServiceInstance serviceInstance = loadBalancerClient.choose(serviceId); URI uri = serviceInstance.getUri(); String providerResult = restTemplate.getForObject(uri+"/service",String.class); return "consumer invoke | " + providerResult; }执行流程: 服务提供方将自己注册到服务注册中心 服务消费方从注册中心获取服务地址 进行远程调用 5.负载均衡在RESTful服务发现的流程中,ServiceA通过负载均衡调用ServiceB; 它分为服务端负载均衡和客户端负载均衡。 服务器端负载均衡: 在负载均衡器中维护一个可用的服务实例清单,当客户端请求时,负载均衡服务器按照某种配置好的规则(负载均衡算法)从可用服务实例清单中选取其一去处理客户端的请求。这就是服务端负载均衡。 例如Nginx,通过Nginx进行负载均衡,客户端发送请求至Nginx,Nginx通过负载均衡算法,在多个服务器 之间选择一个进行访问。即在服务器端再进行负载均衡算法分配。 客户端服务负载均衡: 上边使用的LoadBalancerClient就是一个客户端负载均衡器,具体使用的是Ribbon客户端负载均衡器。 Ribbon在发送请求前通过负载均衡算法选择一个服务实例,然后进行访问,这是客户端负载均衡。即在客户端就进行负载均衡的分配。 RibbonRibbon是一个客户端负载均衡器,其责任是从一组实例列表中挑选合适的实例,如何挑选,取决于负载均衡策略 。 RoundRobinRule(默认):轮询,即按一定的顺序轮换获取实例的地址; RandomRule:随机,即以随机的方式获取实例的地址; AvailabilityFilteringRule:会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,以及并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问; WeightedResponseTimeRule:根据平均响应时间计算所有服务的权重,响应时间越快,服务权重越大,被选中的机率越高;刚启动时,如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够时,会切换到 WeightedResponseTimeRule; RetryRule:先按照RoundRobinRule的策略获取服务,如果获取服务失败,则在指定时间内会进行重试,获取可用的服务; BestAvailableRule: 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务; ZoneAvoidanceRule:默认规则,复合判断server所在区域的性能和server的可用性选择服务器; 在服务消费方的配置文件中修改默认的负载均衡策略: nacos‐restful‐provider: #服务提供方的服务名称 ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #com.netflix.loadbalancer.RandomRule:负载均衡类路径 idea中端口设置启动多个服务提供方进程,为保证端口不冲突,通过启动参数配置端口,并启动这两个进程。 启动参数配置端口会优先于配置文件中的配置; Dubbo是阿里巴巴公司开源的RPC框架,其微服务开发组件相对Spring Cloud来说并不那么完善。 Spring Cloud Alibaba微服务开发框架集成了Dubbo,可实现微服务对外暴露Dubbo协议的接口,Dubbo协议相 比RESTful协议速度更快。 RPC:RPC是远程过程调用(Remote Procedure Call),调用RPC远程方法就像调用本地方法一样,非常方便。 6.1.Dubbo服务架构微服务采用Dubbo协议的系统架构图: 组件说明: 客户端:前端或外部系统 API网关:系统唯一入口,路由转发 application-1 :应用1,前端提供Http接口,接收用户的交互请求 service-1 :微服务1,提供业务逻辑处理服务 service-2:微服务2,提供业务逻辑处理服务 交互流程: 网关负责客户端请求的统一入口,路由转发,前端通过网关请求后端服务。 网关收到前端请求,转发请求给应用。 应用接收前端请求,调用微服务进行业务逻辑处理 微服务为应用提供业务逻辑处理的支撑,为应用提供Dubbo协议接口 优势分析: 此架构同时提供RESTful和Dubbo接口服务,应用层对前端提供RESTful接口,RESTful是互联网通用的轻量级交互协议,方便前端接入系统;微服务层向应用层提供Dubbo接口,Dubbo接口基于RPC通信协议速度更快。 本架构采用阿里开源的Nacos,集服务发现和配置中心于一身,支持RESTful及Dubbo服务的注册。 Dubbo使用
需要依赖 <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring‐cloud‐starter‐dubbo</artifactId> </dependency>
定义配置文件bootstrap.yml server: port: 56040 #启动端口 命令行注入 spring: application: name: dubbo‐service2 main: allow‐bean‐definition‐overriding: true # Spring Boot 2.1 需要设定 cloud: nacos: discovery: server‐addr: 127.0.0.1:8848 dubbo: scan: # dubbo 服务扫描基准包 base‐packages: com.itheima.microservice.service2.service protocol: # dubbo 协议 name: dubbo # dubbo 协议端口 port: 20891 registry: address: nacos://127.0.0.1:8848 application: qos‐enable: false #dubbo运维服务是否开启 consumer: check: false #启动时就否检查依赖的服务bootstrap.yml配置说明: bootstrap.yml内容中以dubbo开头的为dubbo服务的配置: dubbo.scan.base-packages:指定 Dubbo 服务实现类的扫描基准包,将 @org.apache.dubbo.config.annotation.Service注解标注的service暴露为dubbo服务。 dubbo.protocol :Dubbo 服务暴露的协议配置,其中子属性 name 为协议名称, port 为dubbo协议端口,可以指定多协议,如:dubbo.protocol.rmi.port=1099 dubbo.registry:Dubbo 服务注册中心配置,其中子属性 address 的值 nacos://127.0.0.1:8848,说明 dubbo服务注册到nacos 相当于原生dubbo的xml配置中的 <dubbo:registry address=“10.20.153.10:9090” /> bootstrap.yml内容的上半部分为SpringCloud的相关配置: spring.application.name :Spring 应用名称,用于 Spring Cloud 服务注册和发现。 spring.cloud.nacos.discovery :Nacos 服务发现与注册配置,其中子属性 server-addr 指定 Nacos 服务器 主机和端口
定义接口实现
启动service2-server:启动成功观察nacos的服务列表;
application1调用service2
引用service2 <dependency> <groupId>com.itheima.nacos</groupId> <artifactId>service2‐api</artifactId> <version>1.0‐SNAPSHOT</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring‐cloud‐starter‐dubbo</artifactId> </dependency>
实现远程调用 注意:@Reference注解是 org.apache.dubbo.config.annotation.Reference 显示:consumer dubbo invoke | dubboService2 表明service2调用成功。 7.服务发现数据模型 7.1.Namespace 隔离设计命名空间(Namespace)用于进行租户粒度的隔离,Namespace 的常用场景之一是不同环境的隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。 从一个租户(用户)的角度来看,如果有多套不同的环境,那么这个时候可以根据指定的环境来创建不同的 namespce,以此来实现多环境的隔离。如有开发,测试和生产三个不同的环境,那么使用一套 nacos 集群可以分别建以下三个不同的 namespace。 从多个租户(用户)的角度来看,每个租户(用户)可能会有自己的 namespace,每个租户(用户)的配置数据以及注册的服务数据都会归属到自己的 namespace 下,以此来实现多租户间的数据隔离。例如超级管理员分配了三 个租户,分别为张三、李四和王五。分配好了之后,各租户用自己的账户名和密码登录后,创建自己的命名 空间。 命名空间(Namespace)是用于隔离多个环境的(如开发、测试、生产),而每个应用在不同环境的同一个配置(如数据库数据源)的值是不一样的。因此,我们应针对企业项目实际研发流程、环境进行规划。 如某软件公司拥有开发、测试、生产三套环境,那么我们应该针对这三个环境分别建立三个namespace。 建立好所有namespace后,在配置管理与服务管理模块下所有页面,都会包含用于切换namespace(环境)的tab按钮; 注意: namesace 为 public 是 nacos 的一个保留空间,如需要创建自己的 namespace,不要和 public 重名,以一个实际业务场景有具体语义的名字来命名,以免带来字面上不容易区分哪一个 namespace。 在编写程序获取配置集时,指定的namespace参数一定要填写命名空间ID,而不是名称 7.3.数据模型Nacos在经过阿里内部多年生产经验后提炼出的数据模型,是一种 服务-集群-实例 的三层模型,这样基本可以满 足服务在所有场景下的数据存储和管理。
服务:对外提供的软件功能,通过网络访问预定义的接口。
实例:提供一个或多个服务的具有可访问网络地址(IP:Port)的进程,启动一个服务,就产生了一个服务实例。
元信息:Nacos数据(如配置和服务)描述信息,如服务版本、权重、容灾策略、负载均衡策略、鉴权配置、各种自定义标 签 (label), 从作用范围来分:服务级别的元信息、集群的元信息、实例的元信息。
集群:服务实例的集合,服务实例组成一个默认集群, 集群可以被进一步按需求划分,划分的单位可以是虚拟集群,相同集群下的实例才能相互感知。 应用通过Namespace、Service、Cluster(DEFAULT)的配置,描述了该服务向哪个环境(如开发环境)的哪个集群注册实例。 集群作为实例的隔离,相同集群的实例才能相互感知。 namespace、cluster-name若不填写都将采取默认值,namespace的默认是public命名空间, cluster-name的默认值为DEFAULT集群。 8.Nacos配置管理 8.1配置中心在微服务架构中为了统一管理各微服务的配置信息专门设置配置中心,配置中心就是一种统一管理各种应用配置的基础服务组件。 8.1.1.配置应用程序在启动和运行的时候往往需要读取一些配置信息,配置基本上伴随着应用程序的整个生命周期,比如:数据库连接参数、启动参数等。 配置是独立于程序的只读变量。配置对于程序是只读的,程序通过读取配置来改变自己的行为,但是程序不应该去改变配置 配置贯穿于应用的整个生命周期。应用在启动时通过读取配置来初始化,在运行时根据配置调整行为。 如:启动时需要读取服务的端口号、系统在运行过程中需要读取定时策略执行定时任务等。 配置可以有多种加载方式。常见的有程序内部hard code,配置文件,环境变量,启动参数,基于数据库等 配置需要治理。同一份程序在不同的环境(开发,测试,生产)、不同的集群(如不同的数据中心)经常需要有不同的 配置,所以需要有完善的环境、集群配置管理 8.1.2.配置中心微服务架构中,当系统从一个单体应用,被拆分成分布式系统上一个个服务节点后,配置文件也必须跟着迁移 (分割),这样配置就分散了,同时分散中还包含着冗余 配置中心将配置从各应用中剥离出来,对配置进行统一管理,应用自身不需要自己去 管理配置。 配置中心的服务流程: 用户在配置中心更新配置信息。 服务A和服务B及时得到配置更新通知,从配置中心获取配置。 配置中心就是一种统一管理各种应用配置的基础服务组件。 配置中心是整个微服务基础架构体系中的一个组件。 总结:在传统巨型单体应用纷纷转向细粒度微服务架构的历史进程中,配置中心是微服务化不可缺少的一个系统组件,在这种背景下中心化的配置服务即配置中心应运而生;配置中心特性: 配置项容易读取和修改 分布式环境下应用配置的可管理性,即提供远程管理配置的能力 支持对配置的修改的检视以把控风险 可以查看配置修改的历史记录 不同部署环境下应用配置的隔离性 8.1.3.主流配置中心对比目前市面上用的比较多的配置中心有:Spring Cloud Config、Apollo、Nacos和Disconf等。 Disconf不再维护。 性能方面Nacos的读写性能最高,Apollo次之,Spring Cloud Config依赖Git场景不适合开放的大规模自动化运维API。 功能方面Apollo最为完善,nacos具有Apollo大部分配置管理功能,而Spring Cloud Config不带运维管理界面,需要自行开发。 Nacos的一大优势是整合了注册中心、配置中心功能,部署和操作相比 Apollo都要直观简单,因此它简化了架构复杂度,并减轻运维及部署工作。
发布配置
获取配置:从配置中心获取配置添加nacos-config的依赖: <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring‐cloud‐starter‐alibaba‐nacos‐config</artifactId> </dependency>
在bootstrap.yml添加配置: spring: cloud: nacos: config: server‐addr: 127.0.0.1:8848 # 配置中心地址 file‐extension: yaml group: DEFAULT_GROUP注意:要使用配置中心就要在bootstrap.yml中来配置,bootstrap.yml配置文件的加载顺序要比application.yml要优先。
在nacos-restful-consumer工程的controller中增加获取配置的web访问端点/configs,通过标准的spring @Value 方式。 @Value("${common.name}") private String common_name; @GetMapping(value = "/configs") public String getvalue(){return common_name;}若要实现配置的动态更新,只需要进行如下改造: //注入配置文件上下文 @Autowired private ConfigurableApplicationContext applicationContext; @GetMapping(value = "/configs") public String getConfigs(){ return applicationContext.getEnvironment().getProperty("common.name"); }通过nacos控制台更新common.name的配置值,再次访问web端点/configs,发现应用程序能够获取到最新 的配置值,说明spring-cloud-starter-alibaba-nacos-config 支持配置的动态更新。可以通过配置spring.cloud.nacos.config.refresh.enabled=false来关闭动态刷新 8.2.2.配置管理模型对于Nacos配置管理,通过Namespace、group、Data ID能够定位到一个配置集。
配置集(Data ID):
配置项: 配置集中包含的一个个配置内容就是配置项。它代表一个具体的可配置的参数与其值域,通常以 key=value 的形式存在。如我们常配置系统的日志输出级别(logLevel=INFO|WARN|ERROR) 就是一个配置项。
配置分组(Group):
命名空间(Namespace): 常见实践用法: Nacos抽象定义了Namespace、Group、Data ID的概念,具体这几个概念代表什么,取决于我们把它们看成什么,如: Namespace:代表不同环境,如开发、测试、生产环境; Group:代表某项目,如XX医疗项目、XX电商项目; DataId:每个项目下往往有若干个工程,每个配置集(DataId)是一个工程的主配置文件 获取某配置集的代码: nacos服务地址,必须指定; namespace,如不指定默认public 在config中指定namespace,例子如下: config: server‐addr: 127.0.0.1:8848 # 配置中心地址 file‐extension: yaml namespace: a1f8e863‐3117‐48c4‐9dd3‐e9ddc2af90a8 #开发环境 group: DEFAULT_GROUP # xx业务组
group,如不指定默认 DEFAULT_GROUP;
dataId,必须指定,名称为应用名称+配置文件扩展名 Spring Cloud Alibaba Nacos Config可支持自定义 Data Id 的配置。 一个完整的配置案例如下所示: spring: application: name: service2 cloud: nacos: config: server‐addr: 127.0.0.1:8848 # 配置中心地址 file‐extension: yaml #namespace: a1f8e863‐3117‐48c4‐9dd3‐e9ddc2af90a8 #开发环境 group: DEFAULT_GROUP # config external configuration # 1、Data Id group:组名,refresh:动态刷新 ext‐config[0]: data‐id: ext‐config‐common01.yaml group: COMMON_GROUP #组名 refresh: true ext‐config[1]: data‐id: ext‐config‐common02.yaml group: COMMON_GROUP refresh: true
通过 spring.cloud.nacos.config.ext-config[n].data-id的配置方式来支持多个 Data Id 的配置。
通过 spring.cloud.nacos.config.ext-config[n].group 的配置方式自定义 Data Id 所在的组,不明确配置 的话,默认是 DEFAULT_GROUP。
通过 spring.cloud.nacos.config.ext-config[n].refresh的配置方式来控制该 Data Id 在配置变更时,是否支持应用中可动态刷新, 感知到最新的配置值。默认是不支持的。 spring.cloud.nacos.config.ext-config[n].data-id的值必须带文件扩展名,文件扩展名既可支持 properties,又可以支持 yaml/yml。 此时 spring.cloud.nacos.config.file-extension 的配置对自定义扩展配置的 Data Id 文件扩展名没有影响。 配置ext-config-common01.yaml: 测试: @GetMapping(value = "/configs") public String getvalue(){ String name = applicationContext.getEnvironment().getProperty("common.name"); String address = applicationContext.getEnvironment().getProperty("common.addr"); return name+address;}重启nacos-restful-consumer工程,访问::56020/configs |