Sniffing on startup

edit

Connection pools that return true for SupportsReseeding will sniff on startup by default.

We can demonstrate this by creating a virtual Elasticsearch cluster using NEST’s Test cluster framework.

Here we create a 10 node cluster that uses a Sniffing connection pool, setting sniff to fail on all nodes *except* 9202

var audit = new Auditor(() => VirtualClusterWith
    .Nodes(10)
    .Sniff(s => s.Fails(Always))
    .Sniff(s => s.OnPort(9202).Succeeds(Always))
    .Ping(c=>c.SucceedAlways())
    .ClientCalls(r => r.SucceedAlways())
    .SniffingConnectionPool()
    .AllDefaults()
);

When the client call is made, from the audit trail we see that the pool first tried to sniff on startup, with a sniff failure on 9200 and 9201, followed by a sniff success on 9202. A ping and then healthy response are made on 9200

await audit.TraceCall(
     new ClientCall
     {
        { SniffOnStartup},
        { SniffFailure, 9200},
        { SniffFailure, 9201},
        { SniffSuccess, 9202},
        { PingSuccess , 9200},
        { HealthyResponse, 9200}
    }
 );

Occurs once

edit

A sniff on startup only happens once. That is,

  1. a sniff is attempted on a node
  2. if that node fails, a sniff is attempted on the next node
  3. this continues until a sniff succeeds
  4. a sniff on startup does not occur again.
var audit = new Auditor(() => VirtualClusterWith
    .Nodes(10)
    .Sniff(s => s.Fails(Always))
    .Sniff(s => s.OnPort(9202).Succeeds(Always))
    .ClientCalls(r => r.SucceedAlways())
    .Ping(c=>c.SucceedAlways())
    .SniffingConnectionPool()
    .AllDefaults()
);

await audit.TraceCalls(
     new ClientCall
     {
        { SniffOnStartup},
        { SniffFailure, 9200},
        { SniffFailure, 9201},
        { SniffSuccess, 9202},
        { PingSuccess , 9200},
        { HealthyResponse, 9200}
    },
    new ClientCall
    {
        { PingSuccess, 9201},
        { HealthyResponse, 9201}
    }
);

Uses cluster state

edit

A sniff on startup will use the returned cluster state.

In this next example, the state of the cluster returned from the successful sniff is used for subsequent client requests

var audit = new Auditor(() => VirtualClusterWith
    .Nodes(10)
    .Sniff(s => s.Fails(Always))
    .Sniff(s => s.OnPort(9202).Succeeds(Always,
        VirtualClusterWith.Nodes(8, startFrom: 9204)
            .Ping(c=>c.SucceedAlways())
            .ClientCalls(c=>c.SucceedAlways())

        )) 
    .ClientCalls(r => r.SucceedAlways())
    .Ping(c=>c.SucceedAlways())
    .SniffingConnectionPool()
    .AllDefaults()
);

await audit.TraceCall(new ClientCall {
    { SniffOnStartup},
    { SniffFailure, 9200},
    { SniffFailure, 9201},
    { SniffSuccess, 9202},
    { PingSuccess, 9204}, 
    { HealthyResponse, 9204}
});

Sniffing returns 8 nodes, starting from 9204

After successfully sniffing, the ping now happens on 9204

Prefers master eligible nodes

edit

Sniffing prefers to run on master eligible nodes

var audit = new Auditor(() => VirtualClusterWith
    .Nodes(new[] {
        new Node(new Uri("http://localhost:9200")) { MasterEligible = false },
        new Node(new Uri("http://localhost:9201")) { MasterEligible = false },
        new Node(new Uri("http://localhost:9202")) { MasterEligible = true },
    })
    .Sniff(s => s.Succeeds(Always))
    .Ping(s => s.Succeeds(Always))
    .ClientCalls(r => r.SucceedAlways())
    .SniffingConnectionPool()
    .AllDefaults()
);

await audit.TraceCall(new ClientCall {
    { SniffOnStartup},
    { SniffSuccess, 9202},
    { PingSuccess, 9200},
    { HealthyResponse, 9200}
});

although it will fail over to non-master eligible nodes when sniffing fails on master eligible nodes

var audit = new Auditor(() => VirtualClusterWith
    .Nodes(new[] {
        new Node(new Uri("http://localhost:9200")) { MasterEligible = true },
        new Node(new Uri("http://localhost:9201")) { MasterEligible = true },
        new Node(new Uri("http://localhost:9202")) { MasterEligible = false },
    })
    .Sniff(s => s.Fails(Always))
    .Sniff(s => s.OnPort(9202).Succeeds(Always))
    .Ping(c=>c.SucceedAlways())
    .ClientCalls(r => r.SucceedAlways())
    .SniffingConnectionPool()
    .AllDefaults()
);

await audit.TraceCall(new ClientCall {
    { SniffOnStartup},
    { SniffFailure, 9200},
    { SniffFailure, 9201},
    { SniffSuccess, 9202},
    { PingSuccess, 9200},
    { HealthyResponse, 9200}
});