了解完微服务的蜕变和各个架构的优缺点,下面接着聊聊Nacos
nacos简介
Nacos是一个易于使用的动态服务发现,配置和服务管理平台,用于构建云本机应用程序。它有以下作用:
1. 服务注册发现和服务健康监测
使服务更容易注册,并通过DNS或HTTP接口发现其他服务,还提供服务的实时健康检查,以防 止向不健康的主机或服务实例发送请求
Nacos提供对服务的实时的健康检查,阻止向不健康的主机或服务实例发送请求
2.动态配置服务
以中心化、外部化和动态化的方式管理所有环境的应用配置和服务配置
提供了一个简洁易用的UI (控制台样例 Demo) 帮助管理所有的服务和应用的配置。
3.动态 DNS 服务
动态 DNS 服务支持权重路由,更容易地实现中间层负载均衡、更灵活的路由策略、流量控制以及数据中心内网的简单DNS解析服务。
4.服务及其元数据管理
从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、
服务的健康状态、服务的流量管理、路由及安全策略、服务的 SLA 以及最首要的 metrics 统计数据。
一、注册中心
1 服务注册与发现
服务注册,就是将提供某个服务的模块信息(通常是这个服务的ip和端⼝)注册到nacos的组件上去
服务发现,就是新注册的这个服务模块能够及时的被其他调⽤者发现。不管是服务新增 和服务删减都能实现⾃动发现。
用户服务,启动以后就会在注册中心登记自己的ip和端口(服务注册),物流系统如果想要调用用户服务,只需要在注册中心查找用户服务的名称,就能找到用户服务的ip和端口,然后就能调用用户服务了。(服务发现)
2注册中心对比
nacos有注册中心的作用,我们常见的配置中心还有zk和eureka,他们的区别见下表:
3 nacos注册中心工作流程
服务注册: 客户端会通过发送REST请求的方式向Nacos Server注册自己的服务,提供自身的元数据,比如服务名称、ip地址、端口等信息。Nacos Server接收到注册请求后,就会把这些元数据信息存储在一个双层的内存Map中。
服务心跳: 在服务注册后,客户端会维护一个定时心跳来持续通知Nacos Server,说明服务一直处于可用状态,防止被剔除。默认5s发送一次心跳。
服务同步: Nacos Server集群之间会互相同步服务实例,用来保证服务信息的一致性。
服务发现:服务消费者(Nacos Client)在调用服务提供者的服务时,会发送一个REST请求给NacosServer,获取上面注册的服务清单,并缓存在Nacos Client本地,同时会在Nacos Client本地开启一个定时任务定时拉去服务端最新的注册表信息更新到缓存。
服务健康检测:Nacos Service会开启一个定时任务用来检查注册服务实例的健康情况,对于超过15s没有收到客户端心跳的实例会将它的healthy属性设置为false(此时客户端服务发现时不会被发现),如果某个实例超过30s没有收到心跳,直接剔除该实例(被剔除的实例如果恢复的话又会被重新注册)
4 nacos功能
-
名字服务 (Naming Service): 命名服务是指通过指定的服务名称来获取资源或者服务的地址,提供者的信息 ,mall-user(ip1 端口1,...)
-
配置服务 (Configuration Service):动态配置服务让您能够以中⼼化、外部化和动态化的⽅式管理所有环境的配置。动态配置消除 了配置变更时重新部署应⽤和服务的需要。配置中⼼化管理让实现⽆状态服务更简单,也让按 需弹性扩展服务更容易
二、nacos的安装
地址:Tags · alibaba/nacos · GitHub
1.单机操作
1.1在cmd打开所在盘符 startup.cmd -m standalone(记得添加,不然默认是集群) 快速开启单机模式
1.2访问http://192.168.2.8:8848/nacos/index.htmlhttp://localhosthttp://192.168.2.8:8848/nacos/index.html,默认账号密码都是nacos
1.3进入界面表示成功
2服务器操作
地址:Tags · alibaba/nacos · GitHub
2.1 上传到linux上并且解压
2.2目录结构
- bin 启动nacos服务的脚本目录
- conf nacos的配置文件目录
- target nacos的启动依赖存放目录
- data nacos启动成功后保存数据的目录
2.3 进入conf目录,查看nacos配置文件 vi application.proerties
将数据库注释信息放开,并且修改数据库地址和账号密码
2.4数据库
在conf目录下面有数据库nacos-mysql.sql文件,将文件下载出来,并在数据库中执行
将该sql文件导入数据库,如下:
2.5 启动
进入naocs下的bin目录,执行以下命令 ./startup.sh -m stardalone
2.6访问http://自己服务器ip:8848/nacos
用户名和密码都是nacos,看到下面这个页面就是成功了
三、nacos的使用
3.1新建maven父工程,在pom文件中添加一下依赖
<?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.xinzhi</groupId>
<artifactId>spring_cloud_Alibaba</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.12</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
</dependencies>
</dependencyManagement>
</project>
3.2创建maven子工程,项目名称cloud-goods 并且pom中导入
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.12</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.xinzhi</groupId>
<artifactId>cloud-goods</artifactId>
<version>1.0-SNAPSHOT</version>
<name>cloud-goods</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring.cloud.version>2020.0.5</spring.cloud.version>
<spring.cloud.alibaba.version>2021.1</spring.cloud.alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- web的场景依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 端点监控的场景依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.4.12</version>
</dependency>
<!-- nacos场景依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.xinzhi</groupId>
<artifactId>cloud-model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.3 在子项目yml中添加
spring:
application:
name: cloud-goods #服务名称,必须,保证唯⼀
cloud:
nacos:
discovery:
server-addr: 124.222.170.32:8848 #指定nacos-server的地址
username: nacos
password: nacos
server:
port: 9001
3.4在子项目cloud-goods启动类添加@EnableDiscoveryClient//注册发现 将微服务注册到nacos中
package com.xinzhi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient//注册发现
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
3.5启动服务,查看nacos控制台
3.6创建maven子工程,名称cloud-model ,导入lombok依赖,创建Good实体类,该工程为了存放实体类,不需要注册到nacos上,通过在xml中添加依赖就可以使用。
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class Goods {
private String goodName;
private double price;
}
3.7在cloud-goods项目中引入
<dependency>
<groupId>com.xinzhi</groupId>
<artifactId>cloud-model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
3.8在cloud-goods项目中创建controller
@RestController
@RequestMapping("goods")
public class GoodsController {
@RequestMapping("findById/{id}")
public Goods findById(@PathVariable String id){
System.out.println("id"+id);
return new Goods("⼩⽶", 99);
}
}
3.9创建maven子工程,项目名称cloud-order 并且pom中导入
<dependencies>
<!-- web的场景依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 端点监控的场景依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- nacos场景依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
4.0配置cloud-order子工程的application.yml
spring:
application:
name: cloud-order #服务名称,必须,保证唯⼀
cloud:
nacos:
discovery:
server-addr: 82.157.173.221:8848 #指定nacos-server的地址
username: nacos
password: nacos
server:
port: 9002
4.1在cloud-order启动类上添加注解@EnableDiscoveryClient,将该微服务注册到nacos中
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient //服务发现
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
4.2启动服务,查看nacos控制台
四、远程调用
-
微服务之间是可以互相通信的,比如说order调用goods服务
-
在order服务的启动类中添加 RestTemplate并组件化(@Bean)
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient //服务发现
public class OrderApplication {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
-
编写OrderController 调用Goods服务
import com.alibaba.fastjson.JSON;
import com.xinzhi.model.Goods;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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")
@Slf4j
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/save/{id}")
public String save(@PathVariable String id){
Goods good = restTemplate.getForObject("http://localhost:9001/goods/findById/"+id, Goods.class);
log.info("查询到的商品:"+ JSON.toJSONString(good));
return "保存成功";
}
}
访问 http://localhost:9002/order/save/1 是可以成功的。
-
但是我们在调用goods服务的时候将代码写死了,其实在nacos中包含了ribbon(负载均衡方式之一)
-
在注入RestTemplate的时候添加 @LoadBalanced
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
- 改造OrderController
import com.alibaba.fastjson.JSON;
import com.xinzhi.model.Goods;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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")
@Slf4j
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/save/{id}")
public String save(@PathVariable String id){
String serviceName = "cloud-goods";
String url = "http://" + serviceName + ":9001/goods/findById/" + id;
Goods good = restTemplate.getForObject(url, Goods.class);
log.info("查询到的商品:"+ JSON.toJSONString(good));
return "保存成功";
}
}
再去访问 http://localhost:9002/order/save/1 是可以成功的。这次访问是通过服务名称获取的。
五、模拟集群演示
修改goods端口号,添加多个实例化
修改启动端口 -DServer.port=9003
- 修改goods配置文件端口
-
修改goodsController,区分服务
-
启动服务,再次调用http://localhost:9002/order/save/1
可以看到oder可以直接调用goods的两个服务,并且是交替调用(默认为轮询)。
六、Nacos领域模型
6.1概念
nacos的服务由三元组唯⼀确定 (namespace、group、servicename)
nacos的配置由三元组唯⼀确定 (namespace、group、dataId)
不同的namespace是相互隔离的,相同namespace但是不同的group也是相互隔离的
默认的namespace是public ,不能删除
默认的group是DEFAULT-GROUP
每个组之间也有隔离(不同的组做不同的项目)
6.2发布服务到指定的namespace
指定一下namespace和group
重新启动服务查看nacos
同样的方式将order服务指定到pro的命名空间下
再去访问 http://localhost:9002/order/save/1 ,这时控制台会报错,因为调用服务的时候找不到goods实例,把他们放到同一个组就好了
七、nacos配置中心
7.1 概念
配置中⼼,中⼼化管理配置⽂件
1 传统方式配置文件:
-
配置文件太分散,不便于管理
-
太多的冗余配置,通用配置不能共享
-
不支持配置文件的动态刷新,改了配置文件,必须重启服务
7.2 配置中心使用
1 nacos页面配置
2使用配置中心的配置方式如下
#从配置中⼼加载配置⽂件
#⽂件名是通过公式来拼接${prefix}-${spring.profiles.active}.${file-extension}
spring:
cloud:
nacos:
config:
server-addr: 124.222.170.32:8848 #配置服务器的地址
namespace: ae33e3ea-ac58-4495-9b60-6a91c960c083 # 命名空间
username: nacos
password: nacos
prefix: cloud-jifen # 配置文件前缀
file-extension: yml # 配置文件后缀
group: DEFAULT_GROUP # 分组
profiles:
active: test # 激活环境