How to store per-session director data / VSLP director design

Nils Goroll slink at schokola.de
Thu Mar 25 17:59:37 CET 2010


Hi Poul-Henning,

>> I am working on a new director which needs per-session state.
>>
>> Any advise on this?
> 
> It would probably be a good idea if you started out by telling
> me what you are trying to do here...

Oh, yes, absolutely, sorry.

I've written something I would like to call the "Varnish StateLess Persistence"
(VSLP) director: It generalizes some aspects of the hash director and something
I've written before (but not published).

Comment from bin/varnishd/cache_dir_vslp.c:

 * VSLP*) Director - Varnish StateLess Persistence Director
 *
 * The purpose of this director is to provide stateless persistence (or
 * persistency if you prefer) for backend requests based upon this simple
 * concept:
 *
 * - Generate a load balancing key, which will be used to select the backend
 *
 *   The key values should be as uniformly distributed as possible.
 *
 *   For all requests which need to hit the same backend server, the same
 *   key must be generated.
 *
 *   For strings, a hash function is used to generate the key.
 *
 * - Select the preferred backend server as (key mod nservers), nservers being
 *   the number of backend servers for this director.
 *
 * - (Only) If the preferred backend server becomes unavailable, an alternative
 *   backend server is selected using the same method from the set of healhy
 *   servers.
 *
 * This technique allowes to implement persistence without keeping any state,
 * and, in particular, without the need to synchronize state between nodes of a
 * cluster of Varnish servers.
 *
 * Still, all members of a cluster will, if otherwise configured equally,
 * implement the same persistence, in other words, requests sharing a common
 * persistence criterium will be balanced onto the same backend server no matter
 * which Varnish server handles the request.
 *
 * The drawbacks are:
 *
 * - the distribution of requests depends on the number of requests per key and
 *   the uniformity of the distribution of key values. In short, this technique
 *   will generally lead to less good load balancing compared to stateful
 *   techniques.
 *
 * - When a backend server becomes unavailable, every persistence technique has
 *   to reselect a new backend server, but this technique will also switch back
 *   to the preferred server once it becomes healthy again, so the persistence
 *   is generally less stable compared to stateful techniques.
 *
 * - Persistence will generally be lost when the number of hosts configured for
 *   the director is changed (so the configuration should be kept stable).
 *
 * *) The name VSLP was chosen to accompany VTLA as another VETR (Varnish
 *    Exception To the Rule) ;-) http://varnish-cache.org/wiki/VTLA

The purpose I wrote this director for requires the flexibility to chose the
persistence key either directly, generate it from an IP address or from a string
by means of a hash value. The main point is really that it must be possible to
generate the key from some arbitrary data.

Effectively, this resembles the client.id which had been proposed before, and I
would also be happy to chose that notion instead if that's preferred.

Another requirement is to be able to change the hash function for strings on the
fly.

As both the key and the hash function are to be changed in the VCL, I suppose
they should best be linked to the session, so my struct director_sess currently
looks like this:

struct director_sess {
        unsigned                magic;
#define DIRECTOR_SESS_MAGIC     0xd36e6208 /* crc32 */

        /* stateless persistence */
        uint32_t                persistence_key;
        enum vbe_digest_e       digest;
};

In my current implementation, the key can be set using some write-only accessors
and read as an integer value:

# (varnish 2.0 vcc_gen_obj.tcl)

    # XXX: stateless persistence director requirement:

    # XXX: we want to be able to use "any" value as a key, so ideally
    #      we should have some kind of lookahead in the parser and be
    #      able to specify different assignment funktions to overload
    #      assignment / argument passing.
    #      but I don't see how this can be done within the current
    #      framework, so I work around by defining different WO and RO
    #      objects, all accessing the same data
    { dir.key.ip
        WO IP
        {recv pipe pass hash miss hit fetch                        error }
        "struct sess *"
    }
    { dir.key.string
        WO STRING
        {recv pipe pass hash miss hit fetch                        error }
        "struct sess *"
    }
    { dir.key.int
        WO UINT32
        {recv pipe pass hash miss hit fetch                        error }
        "struct sess *"
    }
    # However the key gets set, it is always really an int
    { dir.key
        RO UINT32
        {recv pipe pass hash miss hit fetch                        error }
        "struct sess *"
    }
    # digest alogrithm selection
    { dir.digest
        RW DIGEST
        {recv pipe pass hash miss hit fetch                        error }
        "struct sess *"
    }

Again, I'd really appreciate your advice.

Nils



More information about the varnish-dev mailing list