The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Perlbal::Plugin::SessionAffinity - Sane session affinity (sticky sessions) for Perlbal

VERSION

version 0.004

SYNOPSIS

    LOAD SessionAffinity

    CREATE POOL backends
      POOL backends ADD 10.20.20.100
      POOL backends ADD 10.20.20.101
      POOL backends ADD 10.20.20.102

    CREATE SERVICE balancer
      SET listen          = 0.0.0.0:80
      SET role            = reverse_proxy
      SET pool            = backends
      SET persist_client  = on
      SET persist_backend = on
      SET verify_backend  = on
      SET plugins         = sessionaffinity
    ENABLE balancer

DESCRIPTION

Perlbal doesn't support session affinity (or otherwise known as "sticky sessions") out of the box. There is a plugin on CPAN called Perlbal::Plugin::StickySessions but there's a few problems with it.

This plugin should be do a much better job. Go ahead and read why you should use this one and how it works.

WHY YOU SHOULD USE IT

Here are things that are unique in this plugin. I am comparing this with the current available session affinity implementation available on CPAN (Perlbal::Plugin::StickySessions).

  • It supports session affinity for all requests

    Unlike the other plugin, this one uses a proper hook that supports not just file fetching, but for each and every request.

  • No patches required

    Unlike the other plugin, that comes with two patches (which were not integrated into Perlbal core), this one requires no patches whatsoever.

  • It's up-to-date

    Unlike the other plugin, that still requires a patch that includes a hook that was already introduced (which shows it's clearly outdated), this plugin is very much up to speed with things.

  • It's thin and sane

    Unlike the other plugin, which is basically copy-pasted from some handling code in Perlbal itself (seriously!), this module contains no copy-pasted code, is much smaller and leaner, and is much less likely to break between new versions of Perlbal.

  • No breakage

    Unlike the other plugin, which - after close inspection - seemed breakable (to say the least, since connect-aheads don't seem to get cleaned up), this plugin uses a completely different method which emphasizes correctness and the least intervention with Perlbal itself, and keeps Perlbal in charge of the critical operations.

  • Much less security risk

    Unlike the other plugin, which sets a cookie with the backend ID correlating to the backend order in the pool, this plugin uses SHA1 checksum IDs (with a randomly created salt) for each server, and allows you to change the header name and the checksum salt (for those seeking predictability) for the cookie.

    This makes it harder for an attacker to understand what the header represents and how many backends exist (since there is no counter).

  • Features

    Unlike the other plugin, that simply has things hardcoded, this plugin allows to change both the header name and the salt used to create the ID.

HOW DOES IT WORK

Basic stuff

Basically, the module creates a SHA1 checksum for each backend node, and provides the user with a cookie request. If the user provides that cookie in return, it will try and find and provide the user with that specific node.

If the node is no longer in the service's pool, or the cookie matches a node that doesn't exist, it will provide the user with a cookie again.

Advanced stuff

The plugin sets up dedicated pools and services for each service's node. This is required since Perlbal has no way of actually allowing you to specify the node a user will go to, only the service. Not to worry, this creation is done lazily so it saves as much memory as it can.

When a user comes in with a cookie of a node that exist in the service's pool it will create a pool for it (if one doesn't exist), and a matching service for it (if one doesn't exist) and then direct to user to it.

The check against nodes and pools is done live and not against the static configuration file. This means that if you're playing with the pools (changing them live, for example), it will still work just fine.

A new service is created using configurations from the existing service. The more interesting details is that reuse is emphasized so no new sockets are created and instead this new service uses the already existing sockets (along with existing connections) instead of firing new ones. It doesn't open a new socket for listening or anything like that. This also means your SSL connections work seamlessly. Yes, it's insanely cool, I know! :)

ATTRIBUTES

The name of the cookie header for the session.

Default: X-SERVERID.

affinity_salt

The salt that is used to create the backend's SHA1 IDs.

Default: the following code is run when you load Perlbal::Plugin::SessionAffinity to create the salt on start up:

    join q{}, map { $_ = rand 999; s/\.//; $_ } 1 .. 10;

If you want predictability, you can override the salt.

SUBROUTINES/METHODS

register

Registers our events.

unregister

Unregister our hooks and setters events.

get_ip_port

Parses a request's cookies and finds the specific cookie relating to session affinity and get the backend details via the ID in the cookie.

find_backend_by_id

Given a SHA1 ID, find the correct backend to which it belongs.

create_id

Creates a SHA1 checksum ID using Digest::SHA. The checksum is composed of the IP, port and salt. If you want to have more predictability, you can provide a salt of 0 or string and then the checksum would be predictable.

DEPENDENCIES

Perlbal

Obviously.

CGI::Cookies

To parse and create cookies.

Digest::SHA

To provide a SHA1 checksum.

Carp

To provide croak. It's core, don't worry.

SEE ALSO

Perlbal::Plugin::StickySessions

AUTHOR

Sawyer X <xsawyerx@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2012 by Sawyer X.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.