跳到主要内容
📖 本章预览

本章为预览版本,展示部分核心内容。完整内容包含详细源码解析、实战代码和面试要点,加入知识星球即可解锁全部章节。

第三章:服务注册全链路 — 从 SDK 到服务端

本章以一次临时实例的服务注册为主线,从客户端 SDK 发起请求开始,一路追踪到服务端完成注册、触发集群同步的完整链路。

服务注册全链路时序图

3.1 全链路总览

客户端 SDK                          Nacos Server
───────────── ─────────────
NamingService.registerInstance()


NamingGrpcClientProxy
│ 构建 InstanceRequest

gRPC 长连接发送 ──────────────────→ GrpcRequestAcceptor


RequestHandlerRegistry
│ 根据 Request 类型路由

InstanceRequestHandler.handle()
│ @TpsControl 限流
│ @Secured 鉴权

EphemeralClientOperationServiceImpl

├─① ServiceManager.getSingleton(service)
├─② ClientManager.getClient(connectionId)
├─③ client.addServiceInstance(service, instanceInfo)
└─④ NotifyCenter.publishEvent(ClientRegisterServiceEvent)


ClientServiceIndexesManager.onEvent()
├─→ publishEvent(ServiceChangedEvent)
└─→ DistroProtocol.sync()

3.2 客户端 SDK 侧 — 请求的发起

当你调用 namingService.registerInstance("order-service", "192.168.1.100", 8080) 时,SDK 内部做了什么?

// 客户端入口:NacosNamingService.registerInstance()
public void registerInstance(String serviceName, String groupName, Instance instance)
throws NacosException {
// 参数校验:心跳超时时间、IP 格式等
NamingUtils.checkInstanceIsLegal(instance);
// 委托给 clientProxy 发送请求
clientProxy.registerService(serviceName, groupName, instance);
}

clientProxy 的实际类型是 NamingGrpcClientProxy,它通过 gRPC 长连接发送请求:

// NamingGrpcClientProxy.registerService()
public void registerService(String serviceName, String groupName, Instance instance)
throws NacosException {
// 构建 gRPC 请求对象
InstanceRequest request = new InstanceRequest();
request.setNamespace(namespaceId);
request.setServiceName(serviceName);
request.setGroupName(groupName);
request.setType(NamingRemoteConstants.REGISTER_INSTANCE);
request.setInstance(instance);

// 通过 gRPC 长连接发送,等待响应
requestToServer(request, Response.class);
}

关键点:客户端和服务端之间只有一条 gRPC 长连接,所有的注册、注销、订阅、心跳都复用这条连接。

3.3 服务端入口 — InstanceRequestHandler

@Component
public class InstanceRequestHandler
extends RequestHandler<InstanceRequest, InstanceResponse> {

@Override
@TpsControl(pointName = "RemoteNamingInstanceRegisterDeregister")
@Secured(action = ActionTypes.WRITE)
public InstanceResponse handle(InstanceRequest request, RequestMeta meta)
throws NacosException {
Service service = Service.newService(
request.getNamespace(), request.getGroupName(),
request.getServiceName(), true);

InstanceUtil.setInstanceIdIfEmpty(
request.getInstance(), service.getGroupedServiceName());

switch (request.getType()) {
case NamingRemoteConstants.REGISTER_INSTANCE:
return registerInstance(service, request, meta);
case NamingRemoteConstants.DE_REGISTER_INSTANCE:
return deregisterInstance(service, request, meta);
default:
throw new NacosException(NacosException.INVALID_PARAM,
"Unsupported request type");
}
}
}

🔒 解锁完整内容

本章剩余内容需要解锁后查看

以上仅为本章部分预览内容,完整内容包含更多深度源码解析、实战代码和面试要点。

加入知识星球你将获得:

  • ✅ 全部 17 章完整内容 + 持续更新
  • ✅ 配套源码 + 实战项目
  • ✅ 技术答疑交流

📚 本章完整目录

以下为本章完整目录结构,加入知识星球即可解锁全部内容。

3.4 核心注册逻辑 — EphemeralClientOperationServiceImpl

3.5 Client 模型 — v2 架构的核心抽象

3.6 ServiceManager — 全局服务注册表

3.7 事件驱动 — 注册后的连锁反应

3.8 完整时序图

3.9 面试热点