一 Nacos 基础
1 介绍
Nacos 是阿里巴巴开源的微服务核心组件,集成服务发现、动态配置管理与元数据存储,支持实时监控、热更新及多框架兼容,助力高效构建高可用云原生架构。
2 下载安装
官网下载所需要的版本,此处选用 2.5.0版本
3 通过cmd启动
# 以单机模式启动
startup.cmd -m standalone
4 访问8848
端口
http://localhost:8848/nacos
二 Nacos 注册中心
1 添加Web依赖 – service-order
在微服务架构中,每个微服务(如订单服务)本质是独立的 Spring Boot 应用,spring-cloud-starter 已隐式依赖 Spring Boot 核心模块(如 spring-boot-starter)。若需开发 Web 功能(REST API/前端页面),按需添加 spring-boot-starter-web 即可。
此处还应该添加服务发现依赖(将该服务注册到注册中心)spring-cloud-starter-alibaba-nacos-discovery
,但该依赖已经在父工程中进行公共导入,无需再次导入
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
2 编辑主启动类 – OrderMainApplication
@SpringBootApplication
public class OrderMainApplication {
public static void main(String[] args) {
SpringApplication.run(OrderMainApplication.class, args);
}
}
3 编辑配置文件 – application.properties
# 定义当前微服务的名称为service-order(订单服务)
spring.application.name=service-order
# 指定当前服务启动时占用的端口号为 8000
server.port=8000
# 服务启动时会自动向该地址的 Nacos 服务器注册自己的信息(服务名、IP、端口等)
# 同时服务会从 Nacos 获取其他微服务的注册信息,实现服务间的相互发现
spring.cloud.nacos.server-addr=127.0.0.1:8848
4 产品微服务同上 – service-product
① 依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
② 编辑主启动类 – ProductMainApplication
@SpringBootApplication
public class ProductMainApplication {
public static void main(String[] args) {
SpringApplication.run(ProductMainApplication.class, args);
}
}
③ 编辑配置文件 – application.properties
spring.application.name=service-product
server.port=9000
spring.cloud.nacos.server-addr=127.0.0.1:8848
5 启动查看详情
6 多副本启动
本机通过启动不同端口模拟集群
修改配置实参 – 端口号
实例数增加,每个运行中的服务进程就是一个「实例」(如同一台服务器启动 2 个service-order进程,或 3 台服务器各启动 1 个,总实例数为 3)。
三 Nacos 服务发现 – EnableDiscoveryClient
1 开启服务发现功能 – OrderMainApplication
每一个微服务都需要添加@EnableDiscoveryClient
注解,便于互相调用
// 开启服务发现功能注解
@EnableDiscoveryClient
@SpringBootApplication
public class OrderMainApplication {
public static void main(String[] args) {
SpringApplication.run(OrderMainApplication.class, args);
}
}
2 导入单元测试依赖 – service-order
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
3 测试类 – DiscoveryTest
@SpringBootTest
public class DiscoveryTest {
// 自动注入 Spring Cloud 的服务发现客户端(通用接口),可以用于 Eureka、Consul、Nacos 等多种服务发现组件
@Autowired
DiscoveryClient discoveryClient;
// 自动注入 Nacos 专属的服务发现客户端,提供 Nacos 特有的功能(如更丰富的元数据操作)
@Autowired
NacosServiceDiscovery nacosServiceDiscovery;
// 测试 Spring Cloud 通用 DiscoveryClient 的服务发现功能,适用于所有兼容 Spring Cloud 的服务发现组件
@Test
void discoveryClientTest() {
// 1. 获取所有已注册的服务名称列表
// 注意:某些实现可能返回空列表如果注册中心中没有服务
for (String service : discoveryClient.getServices()) {
System.out.println("service = " + service);
// 2. 获取指定服务的所有实例信息
// 每个实例包含 host、port、uri 等信息
List<ServiceInstance> instances = discoveryClient.getInstances(service);
for (ServiceInstance instance : instances) {
// 3. 打印实例关键信息
System.out.println("ip: " + instance.getHost() + "; " + "port = " + instance.getPort());
}
}
}
/**
* 测试 Nacos 专属服务发现功能
* 需要确保:
* 1. 项目引入了 spring-cloud-starter-alibaba-nacos-discovery
* 2. Nacos 服务器正常运行,有服务注册到 Nacos
* @throws NacosException 当与 Nacos 服务器交互失败时抛出
*/
@Test
void nacosServiceDiscoveryTest() throws NacosException {
// 1. 获取所有注册的服务名称
// Nacos 特有:可能包含 Spring Cloud 通用接口无法获取的额外服务
List<String> services = nacosServiceDiscovery.getServices();
for (String service : services) {
System.out.println("service = " + service);
// 2. 获取服务的所有实例
// 注意:这里获取的是原始 Nacos 实例,可能比 Spring Cloud 抽象更丰富
List<ServiceInstance> instances = nacosServiceDiscovery.getInstances(service);
for (ServiceInstance instance : instances) {
// 3. 打印实例信息
System.out.println("ip: " + instance.getHost() + "; port = " + instance.getPort());
}
}
}
}
// 运行结果 discoveryClientTest
service = service-order
ip: 192.168.44.1; port = 8001
ip: 192.168.44.1; port = 8000
service = service-product
ip: 192.168.44.1; port = 9000
// nacosServiceDiscoveryTest
service = service-order
ip: 192.168.44.1; port = 8001
ip: 192.168.44.1; port = 8000
service = service-product
ip: 192.168.44.1; port = 9000
四 调用准备
1 基本流程
1. 订单服务向注册中心询问商品服务地址列表
2. 注册中心返回商品服务地址列表
3. 订单服务根据列表选择地址发送请求
4. 商品服务根据请求返回数据
2 业务流程
用户下单(对订单服务发起请求),订单服务生成订单需获取订单中所有商品信息,远程调用商品服务获取商品数据,商品服务返回数据,生成订单交给用户。其中1张订单对应多件商品,是一对多的关系。
3 聚合模块导入lombok依赖 – services
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>annotationProcessor</scope>
</dependency>
4 商品实体类 – Product
@Data
public class Product {
private Long id;
private BigDecimal price;
private String productName;
private int num;// 购买数量
}
5 商品Controller – ProductController
@RestController
public class ProductController {
@Autowired
ProductService productService;
// 根据ID获取商品数据
@GetMapping("/product/{id}")
public Product getProduct(@PathVariable("id") Long productId) {
Product product=productService.getProductById(productId);
return product;
}
}
6 商品Service-- ProductController
接口 – ProductService
public interface ProductService {
Product getProductById(Long productId);
}
实现类 – ProductServiceImpl
@Service
public class ProductServiceImpl implements ProductService {
@Override
public Product getProductById(Long productId) {
// 假数据
Product product = new Product();
product.setId(productId);
product.setPrice(new BigDecimal(648));
product.setProductName("大黄"+productId);
product.setNum(8);
return product;
}
}
7 测试商品服务
8 订单实体类 – Order
@Data
public class Order {
private Long id;
// 总金额 = 商品单价 * 数量
private BigDecimal totalAmount;
private Long userId;
private String nickname;
// 订单地址
private String address;
// 远程查询商品列表
private List<Object> productlist;
}
9 订单Controller – OrderController
@RestController
public class OrderController {
@Autowired
OrderService orderService;
// 创建订单
@GetMapping("/create")
public Order createOrder(@RequestParam("productId") Long productId,
@RequestParam("userId") Long userId) {
Order order = orderService.createOrder(productId, userId);
return order;
}
}
10 商品Service-- OrderService
接口 – OrderService
public interface OrderService {
Order createOrder(Long productId,Long userId);
}
实现类 – OrderServiceImpl
@Service
public class OrderServiceImpl implements OrderService {
@Override
public Order createOrder(Long productId, Long userId) {
Order order = new Order();
order.setId(1L);
// 总金额 = 商品单价 * 数量
order.setTotalAmount(new BigDecimal("0"));
order.setUserId(userId);
order.setNickname("huang");
order.setAddress("涠洲岛");
// 远程查询商品列表
order.setProductlist(null);
return order;
}
}