How to use ESB3024 Router with Edgeware CDN Request Router

How to use ESB3024 Router with ESB3008 Request Router

This page describes how to write configuration for using ESB3024 Router in conjunction with ESB3008 Request Router. It can request a host from an ESB3008 Request Router and forward the response to the client, perform load balancing between several Request Routers and handle fallback to an external CDN in case no Request Routers are able to service the request.

Simple Example

# The tuning parameter `target.requestAttempts` controls the number of attempts
# made to find a host. In this example we want to fallback to the external CDN
# in case both Request Routers are down, so we set it to at least 3.

$ confcli services.routing.tuning.target.requestAttempts 3
services.routing.tuning.target.requestAttempts = 3

# Create a classifier to filter incoming requests from Sweden.

$ confcli services.routing.classifiers -w
Running wizard for resource 'classifiers'

Hint: Hitting return will set a value to its default.
Enter '?' to receive the help string

classifiers : [
  classifier can be one of
    1: contentUrlPath
    2: contentUrlQueryParameters
    3: geoip
    4: hostName
    5: ipranges
    6: regexMatcher
    7: stringMatcher
    8: subnet
    9: userAgent
  Choose element index or name: geoip
  Adding a 'geoip' element
    classifier : {
      name (default: ): sweden_classifier
      type (default: geoip): ⏎
      inverted (default: False): ⏎
      continent (default: ): ⏎
      country (default: ): sweden
      cities : [
        city (default: ): ⏎
        Add another 'city' element to array 'cities'? [y/N]: ⏎
      ]
      asn (default: ): ⏎
    }
  Add another 'classifier' element to array 'classifiers'? [y/N]: ⏎
]
Generated config:
{
  "classifiers": [
    {
      "name": "sweden_classifier",
      "type": "geoip",
      "inverted": false,
      "continent": "",
      "country": "sweden",
      "cities": [
        ""
      ],
      "asn": ""
    }
  ]
}
Merge and apply the config? [y/n]: y

# Create a session group for the non-Swedish requests, to use in routing rules

$ confcli services.routing.sessionGroups -w
Running wizard for resource 'sessionGroups'

Hint: Hitting return will set a value to its default.
Enter '?' to receive the help string

sessionGroups : [
  sessionGroup : {
    name (default: ): sweden
    classifiers : [
      classifier (default: ): sweden_classifier
      Add another 'classifier' element to array 'classifiers'? [y/N]: ⏎
    ]
  }
  Add another 'sessionGroup' element to array 'sessionGroups'? [y/N]: ⏎
]
Generated config:
{
  "sessionGroups": [
    {
      "name": "sweden",
      "classifiers": [
        "sweden_classifier"
      ]
    }
  ]
}
Merge and apply the config? [y/n]: y

# The internal CDN uses Edgeware Request Routers that return a redirect
# location.  The router takes the content from the client request,
# and makes its own request to the Request Router using that same
# content.  The returned location is then forwarded to the client.
#
# In case the Request Router responds with an error code, or times out,
# the router will continue traversing the routing tree until a
# successful route is found or the entire tree has been evaluated.

$ confcli services.routing.hostGroups -w
Running wizard for resource 'hostGroups'

Hint: Hitting return will set a value to its default.
Enter '?' to receive the help string

hostGroups : [
  hostGroup can be one of
    1: dns
    2: host
    3: redirecting
  Choose element index or name: 3
  Adding a 'redirecting' element
    hostGroup : {
      name (default: ): internal-cdn
      type (default: redirecting): ⏎
      httpPort (default: 80): ⏎
      httpsPort (default: 443): ⏎
      hosts : [
        host : {
          name (default: ): internal-host-1
          hostname (default: ): internal-host-1.example.com
          ipv6_address (default: ): ⏎
        }
        Add another 'host' element to array 'hosts'? [y/N]: y
        host : {
          name (default: ): internal-host-2
          hostname (default: ): internal-host-2.example.com
          ipv6_address (default: ): ⏎
        }
        Add another 'host' element to array 'hosts'? [y/N]: ⏎
      ]
    }
  Add another 'hostGroup' element to array 'hostGroups'? [y/N]: ⏎
]
Generated config:
{
  "hostGroups": [
    {
      "name": "internal-cdn",
      "type": "redirecting",
      "httpPort": 80,
      "httpsPort": 443,
      "hosts": [
        {
          "name": "internal-host-1",
          "hostname": "internal-host-1.example.com",
          "ipv6_address": ""
        },
        {
          "name": "internal-host-2",
          "hostname": "internal-host-2.example.com",
          "ipv6_address": ""
        }
      ]
    }
  ]
}
Merge and apply the config? [y/n]: y

# The offload CDN is non-redirecting, meaning that router does not
# make any request to its associated hosts to ask for a redirect location
# to forward to the clients, instead it simply returns a location using
# one of the CDN's hosts substituted for the router's host in the
# client request possibly with some kind of respsonse translation to add
# e.g. tokens or path prefixes.

$ confcli services.routing.hostGroups -w
Running wizard for resource 'hostGroups'

Hint: Hitting return will set a value to its default.
Enter '?' to receive the help string

hostGroups : [
  hostGroup can be one of
    1: dns
    2: host
    3: redirecting
  Choose element index or name: 2
  Adding a 'host' element
    hostGroup : {
      name (default: ): offload-cdn
      type (default: host): ⏎
      httpPort (default: 80): ⏎
      httpsPort (default: 443): ⏎
      hosts : [
        host : {
          name (default: ): offload-host
          hostname (default: ): offload-host.example.com
          ipv6_address (default: ): ⏎
        }
        Add another 'host' element to array 'hosts'? [y/N]: ⏎
      ]
    }
  Add another 'hostGroup' element to array 'hostGroups'? [y/N]: ⏎
]
Generated config:
{
  "hostGroups": [
    {
      "name": "offload-cdn",
      "type": "host",
      "httpPort": 80,
      "httpsPort": 443,
      "hosts": [
        {
          "name": "offload-host",
          "hostname": "offload-host.example.com",
          "ipv6_address": ""
        }
      ]
    }
  ]
}
Merge and apply the config? [y/n]: y

# Begin with adding a load balancing route rule between the two internal
# hosts. Let's make internal-host-2 have twice the capacity of
# internal-host-1 by using a weighted rule.

$ confcli services.routing.rules -w
Running wizard for resource 'rules'

Hint: Hitting return will set a value to its default.
Enter '?' to receive the help string

rules : [
  rule can be one of
    1: allow
    2: consistentHashing
    3: contentPopularity
    4: deny
    5: firstMatch
    6: random
    7: rawGroup
    8: rawHost
    9: split
    10: weighted
  Choose element index or name: weighted
  Adding a 'weighted' element
    rule : {
      name (default: ): balancer
      type (default: weighted): ⏎
      targets : [
        target : {
          target (default: ): internal-host-1
          weight (default: 100): 1,
          rule (default: always()): always()
        }
        Add another 'target' element to array 'targets'? [y/N]: y
        target : {
          target (default: ): internal-host-2
          weight (default: 100): 2,
          rule (default: always()): always()
        }
        Add another 'target' element to array 'targets'? [y/N]: ⏎
      ]
    }
  Add another 'rule' element to array 'rules'? [y/N]: ⏎
]
Generated config:
{
  "rules": [
    {
      "name": "balancer",
      "type": "weighted",
      "targets": [
        {
          "target": "internal-host-1",
          "weight": "1",
          "rule:": "always()"
        },
        {
          "target": "internal-host-2",
          "weight": "2",
          "rule:": "always()"
        }
      ]
    }
  ]
}
Merge and apply the config? [y/n]: y

# Make an offload rule to route any traffic not in Sweden to the
# offload CDN.

$ confcli services.routing.rules -w
Running wizard for resource 'rules'

Hint: Hitting return will set a value to its default.
Enter '?' to receive the help string

rules : [
  rule can be one of
    1: allow
    2: consistentHashing
    3: contentPopularity
    4: deny
    5: firstMatch
    6: random
    7: rawGroup
    8: rawHost
    9: split
    10: weighted
  Choose element index or name: firstMatch
  Adding a 'firstMatch' element
    rule : {
      name (default: ): offload
      type (default: firstMatch): ⏎
      targets : [
        target : {
          onMatch (default: ): offload-host
          rule (default: ): not in_session_group('sweden')
        }
        Add another 'target' element to array 'targets'? [y/N]: y
        target : {
          onMatch (default: ): balancer
          rule (default: ): in_session_group('sweden')
        }
        Add another 'target' element to array 'targets'? [y/N]: ⏎
      ]
      onMiss (default: ): offload-host
    }
  Add another 'rule' element to array 'rules'? [y/N]: ⏎
]
Generated config:
{
  "rules": [
    {
      "name": "offload",
      "type": "firstMatch",
      "targets": [
        {
          "onMatch": "offload-host",
          "condition": "not in_session_group('sweden')"
        },
        {
          "onMatch": "balancer",
          "condition": "in_session_group('sweden')"
        }
      ],
      "onMiss": "offload-host"
    }
  ]
}
Merge and apply the config? [y/n]: y
{
  "tuning": {
    // "target_request_attempts" controls the number of attempts to find a host.
    // In this example we want to fallback to the external CDN in case both
    // Request Routers are down, so we set it to 3.
    "target_request_attempts": 3
  },
  "session_groups": [
    {
      "id": 1,
      "name": "not_sweden",
      "classifiers": [
        [
          {
            "id": 1,
            "inverted": true,
            "name": "not_sweden_classifier",
            "rule": {
              "rule_type": "geoip_rule",
              "source": "session/client_ip",
              "country": "Sweden"
            }
          }
        ]
      ]
    }
  ],
  "cdns": [
    {
      "id": "internal-cdn",
      "http_port": 80,
      "https_port": 443,
      // The internal CDN uses Edgeware Request Routers that return a redirect
      // location.  The router takes the content from the client request,
      // and makes its own request to the Request Router using that same
      // content.  The returned location is then forwarded to the client.
      //
      // In case the Request Router responds with an error code, or times out,
      // the router will continue traversing the routing tree until a
      // successful route is found or the entire tree has been evaluated.
      "redirecting": true,
      "manifest_availability_check": {
        "enabled": false,
        "session_group_ids": []
      }
    },
    {
      "id": "offload-cdn",
      "http_port": 80,
      "https_port": 443,
      // The offload CDN is non-redirecting, meaning that router does not
      // make any request to its associated hosts to ask for a redirect location
      // to forward to the clients, instead it simply returns a location using
      // one of the CDN's hosts substituted for the router's host in the
      // client request possibly with some kind of respsonse translation to add
      // e.g. tokens or path prefixes.
      "redirecting": false,
      "manifest_availability_check": {
        "enabled": false,
        "session_group_ids": []
      }
    }
  ],
  "hosts": [
    {
      "id": "internal-host-1",
      "cdn_id": "internal-cdn",
      "address_family": "ipv4",
      "host": "internal-host-1.example"
    },
    {
      "id": "internal-host-2",
      "cdn_id": "internal-cdn",
      "address_family": "ipv4",
      "host": "internal-host-2.example"
    },
    {
      "id": "offload-host",
      "cdn_id": "offload-cdn",
      "address_family": "ipv4",
      "host": "offload-host.example"
    }
  ],
  "routing": {
    "id": "routing_table",
    // "sequential" - Go through the rules at this level one by one, and pick
    // the first that returns a positive weight.
    "member_order": "sequential",
    "members": [
      {
        "id": "reject-node",
        "host_id": "offload-host",
        // Send filtered-out clients to an offload host.
        "weight_function": "return session_groups.not_sweden and 1 or 0"
      },
      {
        "id": "internal_routing",
        // Return 1 to make sure this tree is evaluated at all.
        "weight_function": "return 1"
        // "weighted" - Evaluate all the rules at this level, and pick one of
        // them randomly based on their respective weights.
        //
        // In this example host 1 has half the capacity of host 2, so we just
        // randomly route twice as many clients to host 2.
        "member_order": "weighted",
        "members": [
          {
            "id": "internal-node-1",
            "host_id": "internal-host-1",
            // Half the weight of the other host -> half as likely to be picked.
            "weight_function": "return 1"
          },
          {
            "id": "internal-node-2",
            "host_id": "internal-host-2",
            // Twice the weight of the other -> twice as likely to be picked.
            "weight_function": "return 2"
          }
        ]
      },
      {
        // Add a non-redirecting offload host as the last target in case all the
        // internal redirecting hosts are unavailable or respond with some kind
        // of error code.
        "id": "offload-node",
        "host_id": "offload-host",
        "weight_function": "return 1"
      }
    ]
  }
}