大学生涯 spring SpringCloud核心组件(三) Jie 2024-11-12 2024-12-25 Nacos 注册中心 1. 简介 Nacos
是 Dynamic Naming and Configuration Service
的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
Nacos
致力于帮助您发现、配置和管理微服务。Nacos
提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
Nacos
帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos
是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
服务(Service)是 Nacos 世界的一等公民。Nacos 支持几乎所有主流类型的“服务”的发现、配置和管理:
Kubernetes Service gRPC & Dubbo RPC Service Spring Cloud RESTful Service 功能 1.服务发现和服务健康监测 Nacos 支持基于 DNS 和基于 RPC 的服务发现。服务提供者使用 原生 SDK、OpenAPI、或一个独立的 Agent 注册 Service 后,服务消费者可以使用 DNS TODO 或 HTTP&API 查找和发现服务。
Nacos 提供对服务的实时的健康检查,阻止向不健康的主机或服务实例发送请求。Nacos 支持传输层 (PING 或 TCP)和应用层 (如 HTTP、MySQL、用户自定义)的健康检查。 对于复杂的云环境和网络拓扑环境中(如 VPC、边缘网络等)服务的健康检查,Nacos 提供了 agent 上报模式和服务端主动检测 2 种健康检查模式。Nacos 还提供了统一的健康检查仪表盘,帮助您根据健康状态管理服务的可用性及流量。
2.动态配置服务 动态配置服务可以让您以中心化、外部化和动态化的方式管理所有环境的应用配置和服务配置。
动态配置消除了配置变更时重新部署应用和服务的需要,让配置管理变得更加高效和敏捷。
配置中心化管理让实现无状态服务变得更简单,让服务按需弹性扩展变得更容易。
Nacos 提供了一个简洁易用的 UI (控制台样例 Demo) 帮助您管理所有的服务和应用的配置。Nacos 还提供包括配置版本跟踪、金丝雀发布、一键回滚配置以及客户端配置更新状态跟踪在内的一系列开箱即用的配置管理特性,帮助您更安全地在生产环境中管理配置变更和降低配置变更带来的风险。
3. 动态 DNS 服务 动态 DNS 服务支持权重路由,让您更容易地实现中间层负载均衡、更灵活的路由策略、流量控制以及数据中心内网的简单 DNS 解析服务。动态 DNS 服务还能让您更容易地实现以 DNS 协议为基础的服务发现,以帮助您消除耦合到厂商私有服务发现 API 上的风险。 Nacos 提供了一些简单的 DNS APIs TODO 帮助您管理服务的关联域名和可用的 IP 列表.
4. 服务及其元数据管理 Nacos 能让您从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略、服务的 SLA 以及最首要的 metrics 统计数据。
优势 设计理念 我们相信一切都是服务,每个服务节点被构想为一个星球,每个服务都是一个星系。Nacos 致力于帮助建立这些服务之间的连接,助力每个面向星辰的梦想能够透过云层,飞在云上,更好的链接整片星空。
Nacos 希望帮助用户在云原生时代,在私有云、混合云或者公有云等所有云环境中,更好的构建、交付、管理自己的微服务平台,更快的复用和组合业务服务,更快的交付商业创新的价值,从而为用户赢得市场。正是基于这一愿景,Nacos 的设计理念被定位为易于使用、面向标准、高可用和方便扩展
。
易于使用 易于使用是 Nacos 的一个核心理念,它通过提供用户友好的 Web 界面和简洁的 API 来简化服务的注册、发现和配置管理过程。开发者可以轻松集成 Nacos 到他们的应用中,无需投入大量时间在复杂的设置和学习上。
面向标准 Nacos 采用面向标准的设计理念,遵循云原生应用开发的最佳实践和标准协议,以确保其服务发现和配置管理功能与广泛的技术栈和平台无缝对接。
高可用 为了满足企业级应用对高可用的需求,Nacos 实现了集群模式,确保在节点发生故障时,服务的发现和配置管理功能不会受影响。集群模式也意味着 Nacos 可以通过增加节点来水平扩展,提升系统的整体性能和承载能力。
方便扩展 Nacos 还注重易于扩展,它采用了模块化的设计使得各个组件都可以独立地进行扩展或替换。这也为社区贡献者提供了方便,使他们能够针对特定的需求开发新的功能或者改善现有功能,进一步推动 Nacos 的生态发展。
通过上述设计理念的实现,Nacos 为用户提供了一个强大而灵活的平台,以支持不断变化的业务需求,加速业务创新和数字转型,最终帮助用户在竞争激烈的市场中占据有利地位。
部署模式 Nacos 提供了两种两种部署运行模式:单机模式
和集群模式
单机模式 单机模式又称单例模式, 拥有所有 Nacos 的功能及特性,具有极易部署、快速启动等优点。但无法与其他节点组成集群,无法在节点或网络故障时提供高可用能力。单机模式同样可以使用内置 Derby 数据库(默认)和外置数据库进行存储。
单机模式主要适合于工程师于本地搭建或于测试环境中搭建 Nacos 环境,主要用于开发调试及测试使用;也能够兼顾部分对稳定性和可用性要求不高的业务场景。
集群模式 集群模式通过自研一致性协议 Distro 以及 Raft 协议,将多个 Nacos 节点构建成了高可用的 Nacos 集群。数据将在集群中各个节点进行同步,保证数据的一致性。集群模式具有高可用、高扩展、高并发等优点,确保在故障发生时不影响业务的运行。集群模式默认采用外置数据库进行存储,但也可以通过内置数据库进行存储。
该模式主要适合于生产环境,也是社区最为推荐的部署模式。
Nacos 生态: Nacos 几乎支持所有主流语言,其中 Java/Golang/Python 已经支持 Nacos 2.0 长链接协议,能最大限度发挥 Nacos 性能。
阿里微服务 DNS(Dubbo+Nacos+Spring-cloud-alibaba/Seata/Sentinel)最佳实践,是 Java 微服务生态最佳解决方案;除此之外,Nacos 也对微服务生态活跃的技术做了无缝的支持,如目前比较流行的 Envoy、Dapr 等,能让用户更加标准获取微服务能力。
2. 安装 Nacos 这里采用 Linux 部署,使用 docker 镜像安装服务
第一步:拉取镜像 1 docker pull nacos/nacos-server:v2.1.1
第二步:启动 1 2 3 4 5 6 7 8 docker run -d \ -e MODE=standalone \ -p 8848:8848 \ -p 9848:9848 \ -p 9849:9849 \ --name nacos2.1.1 \ --restart=always \ nacos/nacos-server:v2.1.1
第三步: 测试 在本地输入http://192.168.146.128:8848/nacos/
账号密码都初始默认为 nacos
3. 入门案例 使用订单和支付服务,在订单微服务中调用支付微服务,演示Nacos作为注册中心
Nacos Server:Nacos注册中心 order: 服务消费者(customer) payment: 服务提供者(provide) a.创建springNacos_demo项目,引入SpringBoot与SpringCloud相关依赖pom.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 <?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" > <modelVersion > 4.0.0</modelVersion > <groupId > com.nianxi</groupId > <artifactId > springNacos_demo</artifactId > <version > 1.0-SNAPSHOT</version > <packaging > pom</packaging > <modules > <module > order</module > <module > payment</module > </modules > <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 3.3.5</version > <relativePath /> </parent > <properties > <maven.compiler.source > 17</maven.compiler.source > <maven.compiler.target > 17</maven.compiler.target > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > <spring-cloud.version > 2023.0.2</spring-cloud.version > <alibaba-cloud.version > 2023.0.1.0</alibaba-cloud.version > </properties > <dependencyManagement > <dependencies > <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-dependencies</artifactId > <version > ${spring-cloud.version}</version > <type > pom</type > <scope > import</scope > </dependency > <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 > <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-actuator</artifactId > </dependency > <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-starter-bootstrap</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-devtools</artifactId > <scope > runtime</scope > <optional > true</optional > </dependency > <dependency > <groupId > org.apache.commons</groupId > <artifactId > commons-lang3</artifactId > </dependency > <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > </dependency > </dependencies > <build > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > <configuration > <excludes > <exclude > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > </exclude > </excludes > </configuration > </plugin > </plugins > </build > </project >
b.创建payment子模块作为服务提供者 在pox.xml中引入spring-boot-starter-web与spring-cloud-starter-alibaba-nacos-discovery依赖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <?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" > <modelVersion > 4.0.0</modelVersion > <parent > <groupId > com.nianxi</groupId > <artifactId > springNacos_demo</artifactId > <version > 1.0-SNAPSHOT</version > </parent > <artifactId > payment</artifactId > <properties > <maven.compiler.source > 17</maven.compiler.source > <maven.compiler.target > 17</maven.compiler.target > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > </properties > <dependencies > <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 >
创建配置文件application.yml对端口号与nacos注册中心进行配置 1 2 3 4 5 6 7 8 9 10 server: port: ${port:9001} spring: application: name: payment-service cloud: nacos: discovery: server-addr: 192.168 .146 .128 :8848
配置文件port: ${port:9001}
表示,没有port参数,使用9001端口,有port参数则使用port参数指定的端口
创建启动类PaymentApplication并添加相应注解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.nianxi;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication @EnableDiscoveryClient public class PaymentApplication { public static void main (String[] args) { SpringApplication.run(PaymentApplication.class, args); } }
@EnableDiscoveryClient注解用来扫描配置中服务,与Eureka中启动类@EnableEurekaClient作用相同.
在SpringBoot3中,即从Spring Cloud Edgware开始,@EnableDiscoveryClient 或@EnableEurekaClient 可省略。只需加上相关依赖,并进行相应配置,即可将微服务注册到服务发现组件上。
创建PaymentController,编写部分逻辑代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package com.nianxi.controller;import org.springframework.beans.factory.annotation.Value;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController @RequestMapping("/payment") public class PaymentController { @Value("${server.port}") private String serverPort; @GetMapping("/{id}") public ResponseEntity<String> payment (@PathVariable("id") Long id) { return ResponseEntity.ok("订单号 = " + id + ",支付成功,server.port" + serverPort); } }
启动支付服务 启动两个服务实例端口号分别为9001和9002,注册到nacos中
c.创建order子模块作为服务使用者 在pox.xml中引入spring-cloud-starter-loadbalancer与spring-cloud-starter-alibaba-nacos-discovery,spring-cloud-starter-openfeign依赖 注意:必须依赖spring-cloud-starter-loadbalancer组件,spring-cloud-starter-alibaba-nacos-discovery,不在默认继承ribbon,而是使用Spring Cloud Common总的loadbalancer组件,实现负载均衡
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 <?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" > <modelVersion > 4.0.0</modelVersion > <parent > <groupId > com.nianxi</groupId > <artifactId > springNacos_demo</artifactId > <version > 1.0-SNAPSHOT</version > </parent > <artifactId > order</artifactId > <properties > <maven.compiler.source > 17</maven.compiler.source > <maven.compiler.target > 17</maven.compiler.target > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > </properties > <dependencies > <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 > <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-starter-openfeign</artifactId > </dependency > <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-starter-loadbalancer</artifactId > </dependency > </dependencies > </project >
创建配置文件application.yml对端口号与nacos注册中心进行配置 1 2 3 4 5 6 7 8 9 10 server: port: 84 spring: application: name: order-service cloud: nacos: discovery: server-addr: 192.168 .146 .128 :8848
创建启动类OrderApplication并添加相应注解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.nianxi;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.openfeign.EnableFeignClients;@SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class OrderApplication { public static void main (String[] args) { SpringApplication.run(OrderApplication.class, args); } }
创建配置类MyConfig配置RestTemplate Nacos
底层使用Spring Cloud Common
中的Spring Cloud LoadBalancer
组件实现负载均衡
,注入RestTemplate
,使用注解@LoadBalanced
开启负载均衡功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.nianxi.config;import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.client.RestTemplate;@Configuration public class MyConfig { @Bean @LoadBalanced public RestTemplate restTemplate () { return new RestTemplate (); } }
创建OrderController 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package com.nianxi.controller;import com.nianxi.service.PaymentService;import jakarta.annotation.Resource;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;@RestController @RequestMapping("/order") public class OrderController { public static final String SERVICE_URL = "http://payment-service" ; @Resource private RestTemplate restTemplate; @GetMapping("/lb/{id}") public ResponseEntity<String> consumer_ribbon (@PathVariable("id") Integer id) { String result = restTemplate.getForObject("http://payment-service" + "/payment/" + id, String.class); return ResponseEntity.ok(result); } @Resource private PaymentService paymentService; @GetMapping(value = "/feign/{id}") public ResponseEntity<String> consumer_feign (@PathVariable("id") Long id) { return paymentService.payment(id); } }
PaymentService 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.nianxi.service;import com.nianxi.service.Impl.PaymentFallbackService;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;@FeignClient(value = "payment-service", fallback = PaymentFallbackService.class) public interface PaymentService { @GetMapping("/payment/{id}") ResponseEntity<String> payment (@PathVariable("id") Long id) ; }
PaymentFallbackService 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.nianxi.service.Impl;import com.nianxi.service.PaymentService;import org.springframework.http.HttpStatus;import org.springframework.http.ResponseEntity;import org.springframework.stereotype.Service;@Service public class PaymentFallbackService implements PaymentService { @Override public ResponseEntity<String> payment (Long id) { return new ResponseEntity <String>("feign调用,异常降级方法" , HttpStatus.INTERNAL_SERVER_ERROR); } }
启动 访问http://localhost:9003/order/lb/2
发现服务端口9001与9002交替执行,负载均衡已经成功,因为nacos底层也是采用Spring Cloud Loadbalancer
进行负载均衡处理。