Session Groups and Classification
ESB3024 Router provides a flexible classification engine, allowing the assignment of clients into session groups that can then be used to base routing decisions on.
Session Classification
In order to perform routing it is necessary to classify incoming sessions according to the relevant parameters. This is done through session groups and their associated classifiers.
There are different ways of classifying a request:
Strings with wildcards
: Simple case-insensitive string pattern with support for adding asterisks (’*’) in order to match any value at that point in the pattern.String with regular expressions
: A complex string matching pattern capable of matching more complicated strings than the simple wildcard matching type.
Valid string matching sources are
content_url_path
,content_url_query_parameters
,hostname
anduser_agent
, examples of which will be shown below.
GeoIP
: Based on the geographic location of the client, supporting wildcard matching. Geographic location data is provided by MaxMind. The possible values to match with are any combinations of:- Continent
- Country
- Cities
- ASN
Anonymous IP
: Classifies clients using an anonymous IP. Database of anonymous IPs is provided by MaxMind.IP range
: Based on whether a client’s IP belongs to any of the listed IP ranges or not.Subnet
: Tests if a client’s IP belongs to a named subnet, see Subnets for more details.ASN ID list
: Checks to see if a client’s IP belongs to any of the specified ASN IDs.Random
: Randomly classifies clients according to a given probability. The classifier is deterministic, meaning that a session will always get the same classification, even if evaluated multiple times.
A session group may have more than one classifier. If it does, all the classifiers must match the incoming client request for it to belong to the session group. It is also possible for a request to belong to multiple session groups, or to none.
To send certain clients to a specific host you first need to create a suitable
classifier using confcli
in wizard mode. The wizard will guide you through the
process of creating a new entry, asking you what value to input for each field
and helping you by telling you what inputs are allowed for restricted fields
such as the string comparison source mentioned above:
$ 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: anonymousIp
2: asnIds
3: contentUrlPath
4: contentUrlQueryParameters
5: geoip
6: hostName
7: ipranges
8: random
9: regexMatcher
10: stringMatcher
11: subnet
12: userAgent
Choose element index or name: geoip
Adding a 'geoip' element
classifier : {
name (default: ): sweden_matcher
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_matcher",
"type": "geoip",
"inverted": false,
"continent": "",
"country": "sweden",
"cities": [
""
],
"asn": ""
}
]
}
Merge and apply the config? [y/n]: y
$ 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: anonymousIp
2: asnIds
3: contentUrlPath
4: contentUrlQueryParameters
5: geoip
6: hostName
7: ipranges
8: random
9: regexMatcher
10: stringMatcher
11: subnet
12: userAgent
Choose element index or name: ipranges
Adding a 'ipranges' element
classifier : {
name (default: ): company_matcher
type (default: ipranges): ⏎
inverted (default: False): ⏎
ipranges : [
iprange (default: ): 90.128.0.0/12
Add another 'iprange' element to array 'ipranges'? [y/N]: ⏎
]
}
Add another 'classifier' element to array 'classifiers'? [y/N]: ⏎
]
Generated config:
{
"classifiers": [
{
"name": "company_matcher",
"type": "ipranges",
"inverted": false,
"ipranges": [
"90.128.0.0/12"
]
}
]
}
Merge and apply the config? [y/n]: y
$ 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: anonymousIp
2: asnIds
3: contentUrlPath
4: contentUrlQueryParameters
5: geoip
6: hostName
7: ipranges
8: random
9: regexMatcher
10: stringMatcher
11: subnet
12: userAgent
Choose element index or name: stringMatcher
Adding a 'stringMatcher' element
classifier : {
name (default: ): apple_matcher
type (default: stringMatcher): ⏎
inverted (default: False): ⏎
source (default: content_url_path): user_agent
pattern (default: ): *apple*
}
Add another 'classifier' element to array 'classifiers'? [y/N]: ⏎
]
Generated config:
{
"classifiers": [
{
"name": "apple_matcher",
"type": "stringMatcher",
"inverted": false,
"source": "user_agent",
"pattern": "*apple*"
}
]
}
Merge and apply the config? [y/n]: y
$ 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: anonymousIp
2: asnIds
3: contentUrlPath
4: contentUrlQueryParameters
5: geoip
6: hostName
7: ipranges
8: random
9: regexMatcher
10: stringMatcher
11: subnet
12: userAgent
Choose element index or name: regexMatcher
Adding a 'regexMatcher' element
classifier : {
name (default: ): content_matcher
type (default: regexMatcher): ⏎
inverted (default: False): ⏎
source (default: content_url_path): ⏎
pattern (default: ): .*/(live|news_channel)/.*m3u8
}
Add another 'classifier' element to array 'classifiers'? [y/N]: ⏎
]
Generated config:
{
"classifiers": [
{
"name": "content_matcher",
"type": "regexMatcher",
"inverted": false,
"source": "content_url_path",
"pattern": ".*/(live|news_channel)/.*m3u8"
}
]
}
Merge and apply the config? [y/n]: y
$ 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: anonymousIp
2: asnIds
3: contentUrlPath
4: contentUrlQueryParameters
5: geoip
6: hostName
7: ipranges
8: random
9: regexMatcher
10: stringMatcher
11: subnet
12: userAgent
Choose element index or name: subnet
Adding a 'subnet' element
classifier : {
name (default: ): company_matcher
type (default: subnet): ⏎
inverted (default: False): ⏎
pattern (default: ): company
}
Add another 'classifier' element to array 'classifiers'? [y/N]: ⏎
]
Generated config:
{
"classifiers": [
{
"name": "company_matcher",
"type": "subnet",
"inverted": false,
"pattern": "company"
}
]
}
Merge and apply the config? [y/n]: y
$ 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: anonymousIp
2: asnIds
3: contentUrlPath
4: contentUrlQueryParameters
5: geoip
6: hostName
7: ipranges
8: random
9: regexMatcher
10: stringMatcher
11: subnet
12: userAgent
Choose element index or name: hostName
Adding a 'hostName' element
classifier : {
name (default: ): host_name_classifier
type (default: hostName): ⏎
inverted (default: False): ⏎
patternType (default: stringMatch): ⏎
pattern (default: ): *live.example*
}
Add another 'classifier' element to array 'classifiers'? [y/N]: n
]
Generated config:
{
"classifiers": [
{
"name": "host_name_classifier",
"type": "hostName",
"inverted": false,
"patternType": "stringMatch",
"pattern": "*live.example*"
}
]
}
Merge and apply the config? [y/n]: y
$ 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: anonymousIp
2: asnIds
3: contentUrlPath
4: contentUrlQueryParameters
5: geoip
6: hostName
7: ipranges
8: random
9: regexMatcher
10: stringMatcher
11: subnet
12: userAgent
Choose element index or name: contentUrlPath
Adding a 'contentUrlPath' element
classifier : {
name (default: ): vod_matcher
type (default: contentUrlPath): ⏎
inverted (default: False): ⏎
patternType (default: stringMatch): ⏎
pattern (default: ): *vod*
}
Add another 'classifier' element to array 'classifiers'? [y/N]: n
]
Generated config:
{
"classifiers": [
{
"name": "vod_matcher",
"type": "contentUrlPath",
"inverted": false,
"patternType": "stringMatch",
"pattern": "*vod*"
}
]
}
Merge and apply the config? [y/n]: y
$ 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: anonymousIp
2: asnIds
3: contentUrlPath
4: contentUrlQueryParameters
5: geoip
6: hostName
7: ipranges
8: random
9: regexMatcher
10: stringMatcher
11: subnet
12: userAgent
Choose element index or name: contentUrlQueryParameters
Adding a 'contentUrlQueryParameters' element
classifier : {
name (default: ): bitrate_matcher
type (default: contentUrlQueryParameters): ⏎
inverted (default: False): ⏎
patternType (default: stringMatch): regex
pattern (default: ): .*bitrate=100000.*
}
Add another 'classifier' element to array 'classifiers'? [y/N]: n
]
Generated config:
{
"classifiers": [
{
"name": "bitrate_matcher",
"type": "contentUrlQueryParameters",
"inverted": false,
"patternType": "regex",
"pattern": ".*bitrate=100000.*"
}
]
}
Merge and apply the config? [y/n]: y
$ 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: anonymousIp
2: asnIds
3: contentUrlPath
4: contentUrlQueryParameters
5: geoip
6: hostName
7: ipranges
8: random
9: regexMatcher
10: stringMatcher
11: subnet
12: userAgent
Choose element index or name: userAgent
Adding a 'userAgent' element
classifier : {
name (default: ): iphone_matcher
type (default: userAgent): ⏎
inverted (default: False): ⏎
patternType (default: stringMatch): regex
pattern (default: ): i(P|p)hone
}
Add another 'classifier' element to array 'classifiers'? [y/N]: n
]
Generated config:
{
"classifiers": [
{
"name": "iphone_matcher",
"type": "userAgent",
"inverted": false,
"patternType": "regex",
"pattern": "i(P|p)hone"
}
]
}
Merge and apply the config? [y/n]: y
$ 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: anonymousIp
2: asnIds
3: contentUrlPath
4: contentUrlQueryParameters
5: geoip
6: hostName
7: ipranges
8: random
9: regexMatcher
10: stringMatcher
11: subnet
12: userAgent
Choose element index or name: asnIds
Adding a 'asnIds' element
classifier : {
name (default: ): asn_matcher
type (default: asnIds): ⏎
inverted (default: False): ⏎
asnIds <The list of ASN IDs to accept. (default: [])>: [
asnId: 1
Add another 'asnId' element to array 'asnIds'? [y/N]: y
asnId: 2
Add another 'asnId' element to array 'asnIds'? [y/N]: y
asnId: 3
Add another 'asnId' element to array 'asnIds'? [y/N]: ⏎
]
}
Add another 'classifier' element to array 'classifiers'? [y/N]: ⏎
]
Generated config:
{
"classifiers": [
{
"name": "asn_matcher",
"type": "asnIds",
"inverted": false,
"asnIds": [
1,
2,
3
]
}
]
}
Merge and apply the config? [y/n]: y
$ 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: anonymousIp
2: asnIds
3: contentUrlPath
4: contentUrlQueryParameters
5: geoip
6: hostName
7: ipranges
8: random
9: regexMatcher
10: stringMatcher
11: subnet
12: userAgent
Choose element index or name: random
Adding a 'random' element
classifier <A classifier randomly applying to clients based on the provided probability. (default: OrderedDict())>: {
name (default: ): random_matcher
type (default: random):
probability (default: 0.5): 0.7
}
Add another 'classifier' element to array 'classifiers'? [y/N]: n
]
Generated config:
{
"classifiers": [
{
"name": "random_matcher",
"type": "random",
"probability": 0.7
}
]
}
Merge and apply the config? [y/n]: y
$ 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: anonymousIp
2: asnIds
3: contentUrlPath
4: contentUrlQueryParameters
5: geoip
6: hostName
7: ipranges
8: random
9: regexMatcher
10: stringMatcher
11: subnet
12: userAgent
Choose element index or name: anonymousIp
Adding a 'anonymousIp' element
classifier : {
name (default: ): anon_ip_matcher
type (default: anonymousIp):
inverted (default: False):
}
Add another 'classifier' element to array 'classifiers'? [y/N]: n
]
Generated config:
{
"classifiers": [
{
"name": "anon_ip_matcher",
"type": "anonymousIp",
"inverted": false
}
]
}
Merge and apply the config? [y/n]: y
These classifiers can now be used to construct session groups and properly classify clients. Using the examples above, let’s create a session group classifying clients from Sweden using an Apple device:
$ 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: ): inSwedenUsingAppleDevice
classifiers : [
classifier (default: ): sweden_matcher
Add another 'classifier' element to array 'classifiers'? [y/N]: y
classifier (default: ): apple_matcher
Add another 'classifier' element to array 'classifiers'? [y/N]: ⏎
]
}
Add another 'sessionGroup' element to array 'sessionGroups'? [y/N]: ⏎
]
Generated config:
{
"sessionGroups": [
{
"name": "inSwedenUsingAppleDevice",
"classifiers": [
"sweden_matcher",
"apple_matcher"
]
}
]
}
Merge and apply the config? [y/n]: y
Clients classified by the sweden_matcher
and apple_matcher
classifiers
will now be put in the session group inSwedenUsingAppleDevice
. Using session
groups in routing will be demonstrated later in this document.
Advanced Classification
The above example will simply apply all classifiers in the list, and as long as they all evaluate to true for a session, that session will be tagged with the session group. For situations where this isn’t enough, classifiers can instead be combined using simple logic statements to form complex rules.
A first simple example can be a session group that accepts any viewers in either
ASN 1, 2 or 3 (corresponding to the classifier asn_matcher
or living in Sweden.
This can be done by creating a session group, and adding the following logic
statement:
'sweden_matcher' OR 'asn_matcher'
A slightly more advanced case is where a session group should only contain sessions neither in any of the three ASNs nor in Sweden. This is done by negating the previous example:
NOT ('sweden_matcher' OR 'asn_matcher')
A single classifier can also be negated, rather than the whole statement, for example to accept any Swedish viewers except those in the three ASNs:
'sweden_matcher' AND NOT 'asn_matcher'
Arbitrarily complex statements can be created using classifier names, parentheses,
and the keywords AND
, OR
and NOT
.
For example a session group accepting any Swedish viewers except those in the Stockholm region unless they are also Apple users:
'sweden_matcher' AND (NOT 'stockholm_matcher' OR 'apple_matcher')
Note that the classifier names must be enclosed in single quotes when using this syntax.
Applying this kind of complex classifier using confcli is no more difficult than adding a single classifier at a time:
$ 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: ): complex_group
classifiers : [
classifier (default: ): 'sweden_matcher' AND (NOT 'stockholm_matcher' OR 'apple_matcher')
Add another 'classifier' element to array 'classifiers'? [y/N]: ⏎
]
}
Add another 'sessionGroup' element to array 'sessionGroups'? [y/N]: ⏎
]
Generated config:
{
"sessionGroups": [
{
"name": "complex_group",
"classifiers": [
"'sweden_matcher' AND (NOT 'stockholm_matcher' OR 'apple_matcher')"
]
}
]
}
Merge and apply the config? [y/n]: y