基于Nacos的微服务注册与发现实践:从安装到容错解析
·
一、Nacos安装与基础配置
1.1 Nacos安装步骤
Nacos(Naming and Configuration Service)是阿里巴巴开源的一个动态服务发现、配置管理和服务管理平台。安装过程如下:
# 1. 下载Nacos Server
wget https://github.com/alibaba/nacos/releases/download/2.0.3/nacos-server-2.0.3.tar.gz
# 2. 解压并启动
tar -zxvf nacos-server-2.0.3.tar.gz
cd nacos/bin
# 3. 启动(单机模式)
sh startup.sh -m standalone
1.2 Spring Cloud项目集成配置
在Spring Cloud项目中,通过简单配置即可接入Nacos:
# application.yml
spring:
application:
name: service-order # 服务名称
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # Nacos服务地址
namespace: public # 命名空间
# application.yml
spring:
application:
name: service-product # 服务名称
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # Nacos服务地址
namespace: public # 命名空间
二、Nacos服务注册与发现机制
2.1 服务注册原理
当微服务启动时,会自动向Nacos Server注册自身信息,包括:
-
服务名称(spring.application.name)
-
IP地址和端口
-
集群信息
-
健康状态
2.2 服务发现实现方式
方式一:基于DiscoveryClient的原始方式
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private DiscoveryClient discoveryClient;
private Product getProductFromRemote(Long productId) {
// 1. 获取所有商品服务实例
List<ServiceInstance> instances =
discoveryClient.getInstances("service-product");
// 2. 手动选择实例并拼接URL
ServiceInstance instance = instances.get(0);
String url = "http://" + instance.getHost() + ":" +
instance.getPort() + "/product/" + productId;
// 3. 发起远程调用
return restTemplate.getForObject(url, Product.class);
}
}
方式二:基于LoadBalancerClient的负载均衡
private Product getProductFromRemoteWithLoadBalancer(Long productId) {
// 1. 负载均衡选择服务实例
ServiceInstance choose =
loadBalancerClient.choose("service-product");
// 2. 拼接URL
String url = "http://" + choose.getHost() + ":" +
choose.getPort() + "/product/" + productId;
return restTemplate.getForObject(url, Product.class);
}
方式三:基于@LoadBalanced注解的优雅实现(推荐)
@Configuration
public class OrderConfig {
@LoadBalanced // 关键注解,启用负载均衡
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@Service
public class OrderServiceImpl {
@Autowired
private RestTemplate restTemplate; // 已具备负载均衡能力
private Product getProductFromRemoteWithAnnotation(Long productId) {
// 直接使用服务名,RestTemplate会自动处理服务发现和负载均衡
String url = "http://service-product/product/" + productId;
return restTemplate.getForObject(url, Product.class);
}
}
三、微服务远程调用实践
3.1 完整订单创建示例
@Override
public Order createOrder(Long productId, Long userId) {
// 1. 通过服务发现获取商品信息
Product product = getProductFromRemoteWithAnnotation(productId);
// 2. 构建订单对象
Order order = new Order();
order.setId(System.currentTimeMillis());
order.setUserId(userId);
order.setUserName("张三");
order.setAddress("北京");
// 3. 计算订单总价
BigDecimal total = product.getPrice()
.multiply(new BigDecimal(product.getNum()));
order.setTotal(total);
// 4. 设置商品列表
List<Product> productList = new ArrayList<>();
productList.add(product);
order.setProductList(productList);
return order;
}
四、核心面试题解析:注册中心宕机,远程调用还能实现吗?
4.1 短期影响分析
可以,但有限制条件:
-
服务消费者本地缓存:
-
微服务客户端会缓存从注册中心获取的服务实例列表
-
缓存有效期内(默认30秒),仍可使用缓存的地址进行调用
-
-
心跳检测机制:
-
Nacos客户端与服务实例保持心跳连接
-
即使Nacos Server宕机,现有TCP连接不会立即断开
-
4.2 技术实现原理
// Nacos客户端缓存机制伪代码
public class NacosDiscoveryClient {
private Map<String, List<ServiceInstance>> serviceCache = new ConcurrentHashMap<>();
private long lastUpdateTime = System.currentTimeMillis();
public List<ServiceInstance> getInstances(String serviceId) {
// 1. 首先检查本地缓存
if (cacheIsValid() && cacheContains(serviceId)) {
return getFromCache(serviceId);
}
// 2. 缓存过期或不存在,尝试从注册中心获取
try {
List<ServiceInstance> instances = fetchFromNacos(serviceId);
updateCache(serviceId, instances);
return instances;
} catch (NacosException e) {
// 3. 注册中心不可用,使用最后一次有效的缓存
if (cacheContains(serviceId)) {
log.warn("Nacos不可用,使用缓存数据");
return getFromCache(serviceId);
}
throw new ServiceUnavailableException(serviceId);
}
}
}
4.3 长期影响与风险
|
时间段 |
影响程度 |
具体表现 |
|---|---|---|
|
0-30秒 |
几乎无影响 |
客户端使用本地缓存,调用正常 |
|
30秒-5分钟 |
部分影响 |
新服务无法注册,已有服务实例变更无法感知 |
|
5分钟以上 |
严重影响 |
健康检查失效,故障实例无法剔除,可能导致调用失败 |
通过本文的实践,我们不仅掌握了Nacos的基本使用,更重要的是理解了微服务架构中注册中心的核心作用及其容错机制。这种深入理解对于构建高可用的分布式系统至关重要。
更多推荐



所有评论(0)