コックローチBatchRequest実行プロセス

dist_sender.go

func (ds *DistSender) sendToReplicas(
    ctx context.Context,
    ba roachpb.BatchRequest,
    opts SendOptions,
    rangeID roachpb.RangeID,
    replicas ReplicaSlice,
    nodeDialer *nodedialer.Dialer,
    cachedLeaseHolder roachpb.ReplicaDescriptor,
    withCommit bool,
) (*roachpb.BatchResponse, error) {
    ...
    br, err := transport.SendNext(ctx, ba)
    ...
}

kv / transport.go

// SendNext invokes the specified RPC on the supplied client when the
// client is ready. On success, the reply is sent on the channel;
// otherwise an error is sent.
func (gt *grpcTransport) SendNext(
    ctx context.Context, ba roachpb.BatchRequest,
) (*roachpb.BatchResponse, error) {
  ...
    client := gt.orderedClients[gt.clientIndex]
    ctx, iface, err := gt.NextInternalClient(ctx)
    ...
    reply, err := gt.sendBatch(ctx, client.replica.NodeID, iface, ba)
    ...
}

rpc / context.go

func (a internalClientAdapter) Batch(
    ctx context.Context, ba *roachpb.BatchRequest, _ ...grpc.CallOption,
) (*roachpb.BatchResponse, error) {
    return a.InternalServer.Batch(ctx, ba)
}

server / node.go

func (n *Node) Batch(
    ctx context.Context, args *roachpb.BatchRequest,
) (*roachpb.BatchResponse, error) {
  ...
    br, err := n.batchInternal(ctx, args)
  ...
}

func (n *Node) batchInternal(
    ctx context.Context, args *roachpb.BatchRequest,
) (*roachpb.BatchResponse, error) {
    ...
      br, pErr = n.stores.Send(ctx, *args)
    ...
}

storage /stores.go

func (ls *Stores) Send(
    ctx context.Context, ba roachpb.BatchRequest,
) (*roachpb.BatchResponse, *roachpb.Error) {
    ...
    store, err := ls.GetStore(ba.Replica.StoreID)
    ...
    br, pErr := store.Send(ctx, ba)
    ...
}

storage / store.go

func (s *Store) Send(
    ctx context.Context, ba roachpb.BatchRequest,
) (br *roachpb.BatchResponse, pErr *roachpb.Error) {
 ...
 br, pErr = repl.Send(ctx, ba)
 ...
}

storage / Replica.go

func (r *Replica) Send(
    ctx context.Context, ba roachpb.BatchRequest,
) (*roachpb.BatchResponse, *roachpb.Error) {
    return r.sendWithRangeID(ctx, r.RangeID, &ba)
}

クライアントとサーバーが同じノードであるかどうかを確認します
rpc / context.go

func IsLocal(iface roachpb.InternalClient) bool {
    _, ok := iface.(internalClientAdapter)
    return ok // internalClientAdapter is used for local connections.
}

サーバー側で対応する関数を直接呼び出します。ネットワーク送信によるrpcの回避

func (a internalClientAdapter) Batch(
    ctx context.Context, ba *roachpb.BatchRequest, _ ...grpc.CallOption,
) (*roachpb.BatchResponse, error) {
    return a.InternalServer.Batch(ctx, ba)
}

コックローチBatchRequest実行プロセス
InternalServerはノードクラスです

context.go

// SetLocalInternalServer sets the context's local internal batch server.
func (ctx *Context) SetLocalInternalServer(internalServer roachpb.InternalServer) {
    ctx.localInternalClient = internalClientAdapter{internalServer}
}

server.go

func (s *Server) Start(ctx context.Context) error {
    ...
    s.rpcContext.SetLocalInternalServer(s.node)
    ...
}

dist_sender.go

ds.transportFactory = GRPCTransportFactory

transport_regular.go

// GRPCTransportFactory is the default TransportFactory, using GRPC.
func GRPCTransportFactory(
    opts SendOptions, nodeDialer *nodedialer.Dialer, replicas ReplicaSlice,
) (Transport, error) {
    return grpcTransportFactoryImpl(opts, nodeDialer, replicas)
}

transport.go

func grpcTransportFactoryImpl(
    opts SendOptions, nodeDialer *nodedialer.Dialer, replicas ReplicaSlice,
) (Transport, error) {
clients := make([]batchClient, 0, len(replicas))
    for _, replica := range replicas {
        healthy := nodeDialer.ConnHealth(replica.NodeID) == nil    // 核心代码
        clients = append(clients, batchClient{ 
            replica: replica.ReplicaDescriptor,
            healthy: healthy,
        })
    }
}

node_dialer.go

func (n *Dialer) ConnHealth(nodeID roachpb.NodeID) error {
    if n == nil || n.resolver == nil {
        return errors.New("no node dialer configured")
    }
    if !n.getBreaker(nodeID).Ready() {
        return circuit.ErrBreakerOpen
    }
    addr, err := n.resolver(nodeID)
    if err != nil {
        return err
    }
    // TODO(bdarnell): GRPCDial should detect local addresses and return
    // a dummy connection instead of requiring callers to do this check.
    if n.rpcContext.GetLocalInternalClientForAddr(addr.String()) != nil {  // 核心代码,本地
        // The local client is always considered healthy.
        return nil
    }
    conn := n.rpcContext.GRPCDial(addr.String())
    return conn.Health()
}

つまり、クライアントとサーバーが同じノードの場合、gRPC呼び出しは使用されません。

Cockroach BatchRequestリクエストの
結論:
1)。gRpcを使用して要求を実行する場合、シリアル化と逆シリアル化は避けられません。 
2)crdbは、クライアントとサーバーが同じノードであるというロジックを追加するため、gRPCは使用されず、node.goのBatchメソッドが直接呼び出されます。現時点では、pbのシリアル化と逆シリアル化はありません。

3)シリアル化と逆シリアル化にpbを使用すると、バイトタイプコーデックに対して2つのメモリコピー操作があるため、unsafe.Pointerポインタを使用してC層byte []をコピーするよりも多くのCPUリソースを消費します。

おすすめ

転載: blog.51cto.com/1196740/2578072