源码篇--Nacos服务--中章(3):Nacos服务端启动--端口监听


前言

本文对Nacos 服务端的端口监听进行介绍。


一、BaseRpcServer 介绍:

在 Nacos 中,BaseRpcServer 是一个基础的远程过程调用(RPC)服务器组件,用于处理 Nacos 集群内部节点之间的远程通信和调用。其主要作用包括:

  1. 提供远程服务调用接口:BaseRpcServer 作为一个 RPC 服务器,提供了远程服务调用的接口,使得集群中的各个节点能够通过网络进行相互调用。通过 BaseRpcServer,节点之间可以实现远程调用服务的功能。

  2. 底层网络通信支持:BaseRpcServer 封装了底层的网络通信实现,处理了网络连接建立、消息的传输、数据的序列化和反序列化等操作。它负责管理和维护集群节点之间的通信通道,确保节点之间可以安全、可靠地进行通信。

  3. 处理远程调用请求:BaseRpcServer 接收来自其他节点的远程调用请求,并将请求转发给相应的服务处理器进行处理。它负责解析和分发远程调用请求,将请求分发给正确的服务实现,并返回调用结果。

  4. 集群节点通信协调:BaseRpcServer 在集群节点之间起到协调和调度的作用,通过 RPC 通信协议,实现集群中各个节点之间的信息交换和服务调用。它能够促进集群内部节点之间的协作和信息交流。

总的来说,BaseRpcServer 是 Nacos 集群中用于处理节点之间远程调用和通信的基础组件,承担着网络通信、远程调用、消息处理等功能。它起到了连接集群节点、协调节点之间工作、实现分布式服务调用等作用,是保证 Nacos 集群正常运行和通信的重要组件。

二、GrpcSdkServer 9848 端口监听:

GrpcSdkServer extends BaseGrpcServer 所以在构建 GrpcClusterServer bean 时 ,回先构建BaseGrpcServer 对象:

2.1 端口监听:

@PostConstruct
public void start() throws Exception {
	// 获取实例化的bean名称 GrpcSdkServer/GrpcClusterServer 
    String serverName = getClass().getSimpleName();
    Loggers.REMOTE.info("Nacos {} Rpc server starting at port {}", serverName, getServicePort());
    // 启动 端口监听
    startServer();
    // 管理和刷新 RPC 服务器 SSL 上下文
    if (RpcServerSslContextRefresherHolder.getInstance() != null) {
        RpcServerSslContextRefresherHolder.getInstance().refresh(this);
    }
    
    Loggers.REMOTE.info("Nacos {} Rpc server started at port {}", serverName, getServicePort());
    // jvm 退出 进行方法的回调 资源释放
    Runtime.getRuntime().addShutdownHook(new Thread(() -> {
        Loggers.REMOTE.info("Nacos {} Rpc server stopping", serverName);
        try {
            BaseRpcServer.this.stopServer();
            Loggers.REMOTE.info("Nacos {} Rpc server stopped successfully...", serverName);
        } catch (Exception e) {
            Loggers.REMOTE.error("Nacos {} Rpc server stopped fail...", serverName, e);
        }
    }));
    
}
    

2.2 开启端口监听:

@Override
public void startServer() throws Exception {
    // 创建多处理器监测对象
    final MutableHandlerRegistry handlerRegistry = new MutableHandlerRegistry();
    // 增加各种handler 处理器 ,用于处理客户端的请求
    // getSeverInterceptors() 服务端的拦截器,addServices 添加服务端的请求处理器
    addServices(handlerRegistry, getSeverInterceptors().toArray(new ServerInterceptor[0]));
    // grpc构建要监听的 端口
    // getServicePort() 8848 + 偏移量 GrpcClusterServer +1001 ; GrpcSdkServer +1000
    // getRpcExecutor 获取GrpcClusterServer 或者 GrpcSdkServer 的线程池
    NettyServerBuilder builder = NettyServerBuilder.forPort(getServicePort()).executor(getRpcExecutor());
    // 创建grpc 调用存根
    Optional<InternalProtocolNegotiator.ProtocolNegotiator> negotiator = newProtocolNegotiator();
    if (negotiator.isPresent()) {
        InternalProtocolNegotiator.ProtocolNegotiator actual = negotiator.get();
        Loggers.REMOTE.info("Add protocol negotiator {}", actual.getClass().getCanonicalName());
        builder.protocolNegotiator(actual);
    }
    //  添加处理服务器端传输层过滤器的组件,主要作用是在服务器端对传入的请求进行预处理和处理
    for (ServerTransportFilter each : getServerTransportFilters()) {
        builder.addTransportFilter(each);
    }
    // Server 端netty 初始化
    server = builder.maxInboundMessageSize(getMaxInboundMessageSize()).fallbackHandlerRegistry(handlerRegistry)
            .compressorRegistry(CompressorRegistry.getDefaultInstance())
            .decompressorRegistry(DecompressorRegistry.getDefaultInstance())
            .keepAliveTime(getKeepAliveTime(), TimeUnit.MILLISECONDS)
            .keepAliveTimeout(getKeepAliveTimeout(), TimeUnit.MILLISECONDS)
            .permitKeepAliveTime(getPermitKeepAliveTime(), TimeUnit.MILLISECONDS).build();
    // 服务器监听端口
    server.start();
}

2.2.1 客户端请求处理器:

(1) 客户端请求处理器添加 addServices:

private void addServices(MutableHandlerRegistry handlerRegistry, ServerInterceptor... serverInterceptor) {
        
    // unary common call register. 注册普通的注册器
    //  unaryPayloadMethod 进行方法的定义
    final MethodDescriptor<Payload, Payload> unaryPayloadMethod = MethodDescriptor.<Payload, Payload>newBuilder()
            .setType(MethodDescriptor.MethodType.UNARY).setFullMethodName(MethodDescriptor
                    .generateFullMethodName(GrpcServerConstants.REQUEST_SERVICE_NAME,
                            GrpcServerConstants.REQUEST_METHOD_NAME))
            .setRequestMarshaller(ProtoUtils.marshaller(Payload.getDefaultInstance()))
            .setResponseMarshaller(ProtoUtils.marshaller(Payload.getDefaultInstance())).build();
    // 定义处理器,客户端调用服务端 交由payloadHandler 处理器处理请求
    final ServerCallHandler<Payload, Payload> payloadHandler = ServerCalls.asyncUnaryCall(
            (request, responseObserver) -> grpcCommonRequestAcceptor.request(request, responseObserver));
    // 定义一个 Request 服务名称  并绑定unaryPayloadMethod 方法对应的处理器是 payloadHandler
    final ServerServiceDefinition serviceDefOfUnaryPayload = ServerServiceDefinition
            .builder(GrpcServerConstants.REQUEST_SERVICE_NAME).addMethod(unaryPayloadMethod, payloadHandler)
            .build();
    // 将定义好的方法处理绑定到grpc server 上
    handlerRegistry.addService(ServerInterceptors.intercept(serviceDefOfUnaryPayload, serverInterceptor));
    
    // bi stream register. 注册双向流的 处理器
    final ServerCallHandler<Payload, Payload> biStreamHandler = ServerCalls.asyncBidiStreamingCall(
            (responseObserver) -> grpcBiStreamRequestAcceptor.requestBiStream(responseObserver));
    // 定义方法描述
    final MethodDescriptor<Payload, Payload> biStreamMethod = MethodDescriptor.<Payload, Payload>newBuilder()
            .setType(MethodDescriptor.MethodType.BIDI_STREAMING).setFullMethodName(MethodDescriptor
                    .generateFullMethodName(GrpcServerConstants.REQUEST_BI_STREAM_SERVICE_NAME,
                            GrpcServerConstants.REQUEST_BI_STREAM_METHOD_NAME))
            .setRequestMarshaller(ProtoUtils.marshaller(Payload.newBuilder().build()))
            .setResponseMarshaller(ProtoUtils.marshaller(Payload.getDefaultInstance())).build();
    // 定义一个 BiRequestStream 服务名称  biStreamMethod 方法对应的处理器是 biStreamHandler
    final ServerServiceDefinition serviceDefOfBiStream = ServerServiceDefinition
            .builder(GrpcServerConstants.REQUEST_BI_STREAM_SERVICE_NAME).addMethod(biStreamMethod, biStreamHandler)
            .build();
    // 将定义好的方法处理绑定到grpc server 上
    handlerRegistry.addService(ServerInterceptors.intercept(serviceDefOfBiStream, serverInterceptor));
    
}

(2)grpc 请求存根:
nacos_grpc_service.proto:


/*
 * Copyright 1999-2020 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

syntax = "proto3";

import "google/protobuf/any.proto";
import "google/protobuf/timestamp.proto";

option java_multiple_files = true;
option java_package = "com.alibaba.nacos.api.grpc.auto";

message Metadata {
  string type = 3;
  string clientIp = 8;
  map<string, string> headers = 7;
}

message Payload {
  Metadata metadata = 2;
  google.protobuf.Any body = 3;
}
// 普通请求处理对应  payloadHandler 处理器
service Request {
  // Sends a commonRequest 调用 payloadHandler # request 
  rpc request (Payload) returns (Payload) {
  }
}
// 流请求 处理对应  biStreamHandler
service BiRequestStream {
  // Sends a biStreamRequest 调用 BiRequestStream # requestBiStream 
  rpc requestBiStream (stream Payload) returns (stream Payload) {
  }
}

2.2.2 监听端口启动:

public ServerImpl start() throws IOException {
    synchronized(this.lock) {
    	// 获取锁
    	// 正在启动 & 服务没有停掉 状态监测
        Preconditions.checkState(!this.started, "Already started");
        Preconditions.checkState(!this.shutdown, "Shutting down");
        // 创建监听器
        // 服务器端监控和处理各种事件的发生,以及向客户端发送事件通知 监听
        ServerListenerImpl listener = new ServerListenerImpl();
        // netty 端口监听
        this.transportServer.start(listener);
        this.executor = (Executor)Preconditions.checkNotNull((Executor)this.executorPool.getObject(), "executor");
        this.started = true;
        return this;
    }
}

2.2.3 netty 端口的绑定:

this.transportServer.start(listener) 方法中,进行端口绑定的关键方法;

 Future<Map<ChannelFuture, SocketAddress>> bindCallFuture = this.bossExecutor.submit(new Callable<Map<ChannelFuture, SocketAddress>>() {
   public Map<ChannelFuture, SocketAddress> call() {
       Map<ChannelFuture, SocketAddress> bindFutures = new HashMap();
       
       Iterator var2 = NettyServer.this.addresses.iterator();
		
       while(var2.hasNext()) {
           SocketAddress address = (SocketAddress)var2.next();
           //   0.0.0.0/0.0.0.0:9848 / 0.0.0.0/0.0.0.0:9849 端口的监听
           ChannelFuture future = b.bind(address);
           NettyServer.this.channelGroup.add(future.channel());
           bindFutures.put(future, address);
       }

       return bindFutures;
   }
});

三、GrpcClusterServer 9849 端口监听

GrpcClusterServer extends BaseGrpcServer 所以在构建 GrpcClusterServer bean 时 ,回先构建BaseGrpcServer 对象:同GrpcSdkServer 流程相同,不同的是开通 9849 进行端口的监听;


总结:

Nacos 服务端在启动时 实际上会对3个端口进行监听:

  • 8848+ 1000 = 9848 GrpcsdkServer 客户端与服务端连接的端口,用于客户端向服务端发起连接和请求;
  • 8848+ 1001 = 9849 GrpcClusterServer 服务端gRPC请求服务端端口,用于服务间同步等;
  • 8848- 1000 = 7848 jraft请求服务端端口,用于处理服务端间的Raft相关请求;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值