Nacos - 服务发现和配置管理
教学目标
1)能够理解微服务架构的特点
2)能够理解服务发现的流程
3)能够说出Nacos的功能
4)掌握Nacos的安装方法
5)掌握RESTful服务发现开发方法
6)掌握Dubbo服务发现开发方法
7)理解Nacos服务发现的数据模型
8)能够掌握Nacos配置管理方法
9)掌握Nacos扩展配置方法
1 理解服务发现
1.1 微服务架构
为适应企业的业务发展,提高软件研发的生产力,降低软件研发的成本,软件架构也作了升级和优化,将一个独立 的系统拆分成若干小的服务,每个小服务运行在不同的进程中,服务与服务之间采用RESTful、RPC等协议传输数据,每个服务所拥有的功能具有独立性强的特点,这样的设计就实现了单个服务的高内聚,服务与服务之间的低耦 合效果,这些小服务就是微服务,基于这种方法设计的系统架构即微服务架构。
下图是基于微服务架构的电商系统:
特点:
1、服务层按业务拆分为一个一个的微服务。
2、微服务的职责单一。
3、微服务之间采用RESTful、RPC等轻量级协议传输。
4、有利于采用前后端分离架构。
1.2 理解服务发现
1.2.1 测试环境
在微服务架构中,整个系统会按职责能力划分为多个服务,通过服务之间协作来实现业务目标。这样在我们的代码 中免不了要进行服务间的远程调用,服务的消费方要调用服务的生产方,为了完成一次请求,消费方需要知道服务 生产方的网络位置(IP地址和端口号)。
我们的代码可以通过读取配置文件的方式读取服务生产方网络位置,如下:
我们通过Spring boot技术很容易实现:
1、创建nacos-discovery父工程
pom.xml如下:
<?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>om.yh.nacos</groupId>
<artifactId>nacos-discovery</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<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>
</dependencies>
</dependencyManagement>
</project>
2、Service B(服务生产者)
创建服务提供者 nacos-restful-provider。
pom.xml如下:
<?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>nacos-discovery</artifactId>
<groupId>om.yh.nacos</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-restful-provider</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
Service B是服务的生产方,暴露/service服务地址,实现代码如下:
1、创建Controller
package com.yh.nacos.provider.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class RestProviderController {
@GetMapping(value = "service")
public String service(){
System.out.println("provider invoke");
return "provider invoke";
}
}
2、创建启动类
package com.yh.nacos.provider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringRestProviderBootstrap {
public static void main(String[] args) {
SpringApplication.run(SpringRestProviderBootstrap.class,args);
}
}
配置文件:
创建application.yml,内容如下:
server:
port: 56010
3、Service A(服务消费者)
创建nacos-restful-consumer 服务消费工程。
pom.xml如下:
<?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>nacos-discovery</artifactId>
<groupId>om.yh.nacos</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-restful-consumer</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
</dependencies>
</project>
实现代码:
1、创建controller
package com.yh.nacos.consumer.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class RestConsumerController {
@Value("${provider.address}")
private String providerAddress;
@GetMapping("service")
public String service() {
RestTemplate restTemplate = new RestTemplate();
//调用服务
String providerResult = restTemplate.getForObject("http://" + providerAddress + "/service", String.class);
return "consumer invoke | " + providerResult;
}
}
2、创建启动类
package com.yh.nacos.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
//@EnableDiscoveryClient
public class SpringRestConsumerBootstrap {
public static void main(String[] args) { SpringApplication.run(SpringRestConsumerBootstrap.class,args);
}
}
配置文件:
创建application.yml,内容如下:
server:
port: 56020
provider:
address: 127.0.0.1:56010
访问 http://127.0.0.1:56020/service,输出以下内容:
consumer invoke | provider invoke
1.2.2 服务发现流程
上边的例子看上去很完美,但是,仔细考虑以下,此方案对于微服务应用而言行不通。首先,微服务可能是部署在 云环境的,服务实例的网络位置或许是动态分配的。另外,每一个服务一般会有多个实例来做负载均衡,由于宕机 或升级,服务实例网络地址会经常动态改变。再者,每一个服务也可能应对临时访问压力增加新的服务节点。正如 下图所示:
基于以上的问题,服务之间如何相互发现?服务如何管理?这就是服务发现的问题了。
服务发现就是服务消费方通过服务发现中心智能发现服务提供方,从而进行远程调用的过程。 如下图:
上图中服务实例本身并不记录服务生产方的网络地址,所有服务实例内部都会包含服务发现客户端。
(1)在每个服务启动时会向服务发现中心上报自己的网络位置。这样,在服务发现中心内部会形成一个服务注册 表,服务注册表是服务发现的核心部分,是包含所有服务实例的网络地址的数据库。
(2)服务发现客户端会定期从服务发现中心同步服务注册表 ,并缓存在客户端。
(3)当需要对某服务进行请求时,服务实例通过该注册表,定位目标服务网络地址。若目标服务存在多个网络地 址,则使用负载均衡算法从多个服务实例中选择出一个,然后发出请求。
总结,在微服务环境中,由于服务运行实例的网络地址是不断动态变化的,服务实例数量的动态变化 ,因此无法使用固定的配置文件来记录服务提供方的网络地址,必须使用动态的服务发现机制用于实现微服务间的相互感知。 各服务实例会上报自己的网络地址,这样服务中心就形成了一个完整的服务注册表,各服务实例会通过服务发现中 心来获取访问目标服务的网络地址,从而实现服务发现的机制。
2 Nacos 服务发现
2.1 Nacos简介
2.1.1 服务发现产品对比
目前市面上用的比较多的服务发现中心有:Nacos、Eureka、Consul和Zookeeper。
对比项目 | Nacos | Eureka | Consul | Zookeeper |
一致性协议 | 支持AP和CP模型 | AP模型 | CP模型 | CP模型 |
健康检查 | TCP/HTTP/MYSQL/Client Beat | Client Beat | TCP/HTTP/gRPC/Cmd | Keep Alive |
负载均衡策略 | 权重/metadata/Selector | Ribbon | Fabio | - |
雪崩保护 | 有 | 有 | 无 | 无 |
自动注销实例 | 支持 | 支持 | 不支持 | 支持 |
访问协议 | HTTP/DNS | HTTP | HTTP/DNS | TCP |
监听支持 | 支持 | 支持 | 支持 | 支持 |
多数据中心 | 支持 | 支持 | 支持 | 不支持 |
跨注册中心同步 | 支持 | 不支持 | 支持 | 不支持 |
SpringCloud集成 | 支持 | 支持 | 支持 | 不支持 |
Dubbo集成 | 支持 | 不支持 | 不支持 | 支持 |
k8s集成 | 支持 | 不支持 | 支持 | 不支持 |
从上面对比可以了解到,Nacos作为服务发现中心,具备更多的功能支持项,且从长远来看Nacos在以后的版本会 支持SpringCLoud+Kubernetes的组合,填补 2 者的鸿沟,在两套体系下可以采用同一套服务发现和配置管理的解决方案,这将大大的简化使用和维护的成本。另外,Nacos 计划实现 Service Mesh,也是未来微服务发展的趋势。
2.1.2 Nacos简介
Nacos是阿里的一个开源产品,它是针对微服务架构中的服务发现、配置管理、服务治理的综合型解决方案。
官方介绍是这样的:
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您实现动态服务发现、服务配置管理、服务及流量管理。 Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。
Nacos 是构建以“服务”为中心的现代应用架构的服务基础设施。
官网地址:https://nacos.io
2.1.3 Nacos特性
Nacos主要提供以下四大功能:
1. 服务发现与服务健康检查
Nacos使服务更容易注册,并通过DNS或HTTP接口发现其他服务,Nacos还提供服务的实时健康检查,以防止向不健康的主机或服务实例发送请求。
2. 动态配置管理
动态配置服务允许您在所有环境中以集中和动态的方式管理所有服务的配置。Nacos消除了在更新配置时重新 部署应用程序,这使配置的更改更加高效和灵活。
3. 动态DNS服务
Nacos提供基于DNS 协议的服务发现能力,旨在支持异构语言的服务发现,支持将注册在Nacos上的服务以域名的方式暴露端点,让三方应用方便的查阅及发现。
4. 服务和元数据管理
Nacos 能让您从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略。
这里1、3、4说明了服务发现的功能特性。
2.2 安装Nacos Server
2.2.1 预备环境准备
Nacos 依赖 Java 环境来运行。如果您是从代码开始构建并运行Nacos,还需要为此配置 Maven环境,请确保是在以下版本环境中安装使用:
- 64 bit OS,支持 Linux/Unix/Mac/Windows,推荐选用 Linux/Unix/Mac。
- 64 bit JDK 1.8+;下载 & 配置。
- Maven 3.2.x+;下载 & 配置。
2.2.2 下载源码或者安装包
git clone https://github.com/alibaba/nacos.git 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
你可以通过源码和发行包两种方式来获取 Nacos。**从** **Github** **上下载源码方式
下载编译后压缩包方式
您可以从 最新稳定版本 下载
下载地址:https://github.com/alibaba/nacos/releases 下载后解压包,本教程使用nacos-server-1.1.3版本。
unzip nacos-server-$version.zip
或者
tar -xvf nacos-server-$version.tar.gz
2.2.3 启动服务器
nacos的默认端口是8848,需要保证8848默认端口没有被其他进程占用。进入安装程序的bin目录:
cd nacos/bin
Linux/Unix/Mac启动方式:
启动命令(standalone代表着单机模式运行,非集群模式):
sh startup.sh -m standalone
如果您使用的是ubuntu系统,或者运行脚本报错提示[[符号找不到,可尝试如下运行:
bash startup.sh -m standalone
Windows启动方式: 启动命令:
cmd startup.cmd 或者 双击startup.cmd运行文件。
启动成功,可通过浏览器访问 http://127.0.0.1:8848/nacos ,打开如下nacos控制台登录页面:
使用默认用户名:nacos,默认密码:nacos 登录即可打开主页面。
2.2.4 外部mysql数据库支持
单机模式时nacos默认使用嵌入式数据库实现数据的存储,若想使用外部mysql存储nacos数据,需要进行以下步骤:
- 安装数据库,版本要求:5.6.5+,mysql 8 以下
- 初始化mysql数据库,新建数据库 nacos_config,数据库初始化文件:${nacoshome}/conf/nacos-mysql.sql
- 修改${nacoshome}/conf/application.properties文件,增加支持mysql数据源配置(目前只支持mysql),添加mysql数据源的url、用户名和密码。
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&serverTimezone=GMT%2B8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=root
2.3 RESTful服务发现
2.3.1 测试环境
Spring Cloud是一套微服务开发框架集合,包括微服务开发的方方页面,Spring Cloud是一套微服务开发的标准, 集成了很多优秀的开源框架,比如有名的Netflix公司的众多项目。
Spring Cloud 项目地址:https://spring.io/projects/spring-cloud
本测试环境采用阿里开源的Spring Cloud Alibaba微服务开发框架,Spring Cloud Alibaba是阿里巴巴公司基于Spring Cloud标准实现一套微服务开发框架集合,它和Netflix一样都是Spring Cloud微服务开发实现方案。
Spring Cloud Alibaba项目地址:https://github.com/alibaba/spring-cloud-alibaba
通过Spring Cloud Alibaba实现解决:
1、服务发现客户端从服务发现中心获取服务列表
2、服务消费方通过负载均衡获取服务地址
在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>
<!-- 增加下面jar设定 -->
<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>
2.3.2 服务注册
在服务提供工程中添加依赖,此依赖的作用是服务发现
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
在服务提供工程中配置nacos服务发现相关的配置:
服务提供:
server:
port: 56010
spring:
application:
name: nacos-restful-provider
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
启动nacos
启动服务提供方
观察nacos服务列表,nacos-restful-provider注册成功
服务名称:每个服务在服务注册中心的标识,相当于Java中的类名。
服务实例:网络中提供服务的实例,具有IP和端口,相当于Java中的对象,一个实例即为运行在服务器上的一个进程。
2.3.3 服务发现
在服务消费工程中添加依赖,此依赖的作用是服务发现
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
在服务消费工程中配置nacos服务发现相关的配置:
服务消费方:
nacos:
server:
addr: 127.0.0.1:8848
spring:
application:
name: nacos_consumer
cloud:
nacos:
discovery:
server-addr: ${nacos.server.addr} # 配置中心地址
修改Controller中远程调用的代码:
为了区别和之前的代码,也可以自己创建一个新的控制器.
@Autowired
LoadBalancerClient loadBalancerClient;
//待查找的服务id
private String serviceId = "nacos-restful-provider";
@GetMapping("service")
public String service() {
RestTemplate restTemplate = new RestTemplate();
// 调用服务
// String providerResult = restTemplate.getForObject("http://" + providerAddress + "/service", String.class);
ServiceInstance choose = loadBalancerClient.choose(serviceId);
URI uri = choose.getUri();
String providerResult = restTemplate.getForObject(uri + "/service", String.class);
return "consumer invoke | " + providerResult;
}
执行流程:
1、服务提供方将自己注册到服务注册中心
2、服务消费方从注册中心获取服务地址
3、进行远程调用
2.3.4 负载均衡
在RESTful服务发现的流程中,ServiceA通过负载均衡调用ServiceB,下边来了解一下负载均衡:
负载均衡就是将用户请求(流量)通过一定的策略,分摊在多个服务实例上执行,它是系统处理高并发、缓解网络 压力和进行服务端扩容的重要手段之一。它分为服务端负载均衡和客户端负载均衡。
服务器端负载均衡:
在负载均衡器中维护一个可用的服务实例清单,当客户端请求来临时,负载均衡服务器按照某种配置好的规则(负 载均衡算法)从可用服务实例清单中选取其一去处理客户端的请求。这就是服务端负载均衡。
例如Nginx,通过Nginx进行负载均衡,客户端发送请求至Nginx,Nginx通过负载均衡算法,在多个服务器之间选择一个进行访问。即在服务器端再进行负载均衡算法分配。
客户端服务负载均衡:
上边使用的LoadBalancerClient就是一个客户端负载均衡器,具体使用的是Ribbon客户端负载均衡器。
Ribbon在发送请求前通过负载均衡算法选择一个服务实例,然后进行访问,这是客户端负载均衡。即在客户 端就进行负载均衡的分配。
Ribbon是一个客户端负载均衡器,它的责任是从一组实例列表中挑选合适的实例,如何挑选?取决于负载均衡策略 。
Ribbon核心组件IRule是负载均衡策略接口,它有如下实现,大家仅做了解:
- 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:负载均衡类路径。
2.3.5 小结
服务注册与发现流程:
1、服务提供方将自己注册到服务注册中心
2、服务消费方从注册中心获取服务地址
3、通过客户端负载均衡器进行远程调用
2.4 Dubbo服务发现
Dubbo是阿里巴巴公司开源的RPC框架,在国内有着非常大的用户群体,但是其微服务开发组件相对Spring Cloud来说并不那么完善。
Spring Cloud Alibaba微服务开发框架集成了Dubbo,可实现微服务对外暴露Dubbo协议的接口,Dubbo协议相比RESTful协议速度更快。
RPC:RPC是远程过程调用(Remote Procedure Call)的缩写形式,调用RPC远程方法就像调用本地方法一样,非常方便,后边案例讲解具体过程。
2.4.1 Dubbo服务架构
下图是微服务采用Dubbo协议的系统架构图:
组件说明:
1、客户端:前端或外部系统
2、API网关:系统唯一入口,路由转发
3、application-1 :应用1,前端提供Http接口,接收用户的交互请求
4、service-1 :微服务1,提供业务逻辑处理服务
5、service-2:微服务2,提供业务逻辑处理服务交互流程:
1、网关负责客户端请求的统一入口,路由转发,前端通过网关请求后端服务。
2、网关收到前端请求,转发请求给应用。
3、应用接收前端请求,调用微服务进行业务逻辑处理
4、微服务为应用提供业务逻辑处理的支撑,为应用提供Dubbo协议接口
优势分析:
此架构同时提供RESTful和Dubbo接口服务,应用层对前端提供RESTful接口,RESTful是互联网通用的轻量级交互协议,方便前端接入系统;微服务层向应用层提供Dubbo接口,Dubbo接口基于RPC通信协议 速度更快。
本架构采用阿里开源的Nacos,集服务发现和配置中心于一身,支持RESTful及Dubbo服务的注册。
2.4.2 测试环境
父工程:仍然使用nacos-dicovery。
application1:使用nacos-restful-consumer。
service1微服务:需要新建
service2微服务:需要新建
api网关:后边的课程内容讲解。
2.4.3 service2微服务
service2对外暴露dubbo协议的接口,考虑远程接口可能 会被其它多个服务调用,这里将service2的接口单独抽取出api工程,service2微服务工程的结构如下:
service2-api:存放接口,独立成一个工程方便被其它服务工程依赖。service2-server:存放接口实现,即dubbo服务的实现部分。
2.4.3.1 定义service2-api
1、创建service2工程
<?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>nacos-discovery</artifactId>
<groupId>com.yh.nacos</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<artifactId>nacos-dubbo-service2</artifactId>
</project>
2、创建service2-api工程
<?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>nacos-dubbo-service2</artifactId>
<groupId>com.yh.nacos</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service2-api</artifactId>
</project>
3、定义接口
package com.yh.microservice.service2.api;
public interface Service2Api {
public String dubboService2();
}
2.4.3.2 定义service2-server
1、创建service2-server工程
<?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>nacos-dubbo-service2</artifactId>
<groupId>com.yh.nacos</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service2-server</artifactId>
<dependencies>
<dependency>
<groupId>com.yh.nacos</groupId>
<artifactId>service2-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
</dependencies>
</project>
2、定义接口实现
【注意:使用 @org.apache.dubbo.config.annotation.Service
注解 标记dubbo服务】
package com.yh.microservice.service2.service;
import com.yh.microservice.service2.api.Service2Api;
@org.apache.dubbo.config.annotation.Service
public class Service2ApiImpl implements Service2Api {
public String dubboService2() {
return "dubboService2";
}
}
3、定义启动类
package com.yh.microservice.service2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Service2Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Service2Bootstrap.class,args);
}
}
4、定义配置文件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.yh.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 #启动时就否检查依赖的服务
5、启动service2-server
启动成功观察nacos的服务列表
6、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 服务注册和发现。该值在 Dubbo Spring Cloud 加持下被视作 dubbo.application.name,因此,无需再显示地配置
- speing.cloud.nacos.discovery: Nacos 服务发现与注册配置,其中子属性 server-addr 指定 Nacos 服务器主机和端口
2.4.4 application1 调用 service2
根据dubbo服务的架构图,本章节将nacos-restful-consumer作为application1,实现application1调用service2。
2.4.4.1 引用service2
在nacos-restful-consumer工程中引用service2依赖 在pom.xml中引入service2-api的依赖
<dependency>
<groupId>com.yh.nacos</groupId>
<artifactId>service2-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
引入 spring-cloud-starter-dubbo依赖,它会根据接口生成代理对象
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
2.4.4.2 实现远程调用
修改nacos-restful-consumer工程的RestConsumerController:
@org.apache.dubbo.config.annotation.Reference
private Service2Api service2Api;
@GetMapping(value = "/service2")
public String service2() {
//远程调用service2
String providerResult = service2Api.dubboService2();
return "consumer dubbo invoke | " + providerResult;
}
测试
请求:http://127.0.0.1:56020/service2
显示:consumer dubbo invoke | dubboService2 表明service2调用成功。
2.4.5 service1微服务
service1采用和service2相同的工程结构。
本节实现service1对外暴露dubbo接口,并用实现service1调用service2。
2.4.5.1 定义service1-api
1、创建service1工程
<?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>nacos-discovery</artifactId>
<groupId>com.yh.nacos</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-dubbo-service1</artifactId>
<packaging>pom</packaging>
<modules>
<module>service1-api</module>
<module>service1-server</module>
</modules>
</project>
2、创建service1-api工程
<?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>nacos-dubbo-service1</artifactId>
<groupId>com.yh.nacos</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service1-api</artifactId>
</project>
3、定义接口
package com.yh.microservice.service1.api;
public interface Service1Api {
public String dubboService1();
}
2.4.5.2 定义service1-server
创建service1-server工程
由于实现service1调用service2,这里需要引入 service2依赖。
<?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>nacos-dubbo-service1</artifactId>
<groupId>com.yh.nacos</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service1-server</artifactId>
<dependencies>
<dependency>
<groupId>com.yh.nacos</groupId>
<artifactId>service1-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.yh.nacos</groupId>
<artifactId>service2-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
</dependencies>
</project>
2、定义接口实现
package com.yh.microservice.service1.service;
import com.yh.microservice.service1.api.Service1Api;
import com.yh.microservice.service2.api.Service2Api;
import org.apache.dubbo.config.annotation.Reference;
@org.apache.dubbo.config.annotation.Service
public class Service1ApiImpl implements Service1Api {
@Reference
Service2Api service2Api;
public String dubboService1() {
return "dubboService1 | "+service2Api.dubboService2();
}
}
3、定义启动类
package com.yh.microservice.service1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Service1Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Service1Bootstrap.class,args);
}
}
4、定义配置文件bootstrap.yml
server:
port: 56030 #启动端口 命令行注入
spring:
application:
name: dubbo-service1
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.yh.microservice.service1.service
protocol:
#dubbo 协 议
name: dubbo
#dubbo 协议端口
port: 20881
registry:
address: nacos://127.0.0.1:8848
application:
qos-enable: false #dubbo运维服务是否开启
consumer:
check: false #启动时就否检查依赖的服务
5、启动service1-server
启动成功观察nacos的服务列表
2.4.5.3 application1调用service1
参考 application1调用service2的方法实现。
1、在application1引入 service1-api的依赖略
<dependency>
<groupId>com.yh.nacos</groupId>
<artifactId>service1-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
2、在application1的controller中调用service1接口
@org.apache.dubbo.config.annotation.Reference
private Service1Api service1Api;
@GetMapping(value = "/service3")
public String service3() {
//远程调用service1
String providerResult = service1Api.dubboService1();
return "consumer dubbo invoke | " + providerResult;
}
3、测试,请求http://127.0.0.1:56020/service3
显示 :consumer dubbo invoke | dubboService1|dubboService2,
表明调用service1成功,service1调用service2成功。
2.5 服务发现数据模型
2.5.1 Namespace 隔离设计
命名空间**(Namespace)**用于进行租户粒度的隔离,Namespace 的常用场景之一是不同环境的隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
从一个租户(用户)的角度来看,如果有多套不同的环境,那么这个时候可以根据指定的环境来创建不同的
namespce,以此来实现多环境的隔离。例如,你可能有开发,测试和生产三个不同的环境,那么使用一套
nacos 集群可以分别建以下三个不同的 namespace。如下图所示:
从多个租户(用户)的角度来看,每个租户(用户)可能会有自己的 namespace,每个租户(用户)的配置数据以及注册的服务数据都会归属到自己的 namespace 下,以此来实现多租户间的数据隔离。例如超级管理员分配了三个租户,分别为张三、李四和王五。分配好了之后,各租户用自己的账户名和密码登录后,创建自己的命名空间。如下图所示:
注意**