With the routing rules feature of dynamic routing, you can select requests for special
routing behavior based on request information.
Before you begin
Enable Dynamic Routing in a collective controller. Complete the steps in Setting up dynamic routing for Liberty collectives.
Tip: To use routing rules to route to multiple collectives, each collective must have a
different name. Use the
--collectiveName
option when you run the
collective create command to name a collective. If the collective is already
created, you can provide a logical name for the collective with the
connectorClusterName property of the
<dynamicRouting>
XML
element. If the
connectorClusterName property is specified, the value takes
precedence over the
collectiveName
specified with the
--collectiveName
option. See
Setting up dynamic routing for multiple Liberty collectives.
About this task
By default, dynamic routing balances the request load across all servers that can handle the
request. Configure routing rules to override the default behavior so that routing rules can route
requests to specific server resources, redirect requests, or reject requests.
Note: All collective controllers in the collective must provide the same set of routing rules
through the dynamic routing service. Add an
.xml file that contains the routing
rules to the
configDropins/defaults directory of one of the controllers to
ensure that all controllers use the same routing rules. For more information, see
Automatically sharing configurations among replicas.
Procedure
-
Add the
<routingRules>
element as a child of the
<dynamicRouting>
element in the controller server.xml
file.
Specify the webServers
attribute of the
<routingRules>
element. Each <routingRules>
element can
define the applicable set of web servers where the rules are published. When a web server connects
to the DynamicRouting service, the service delivers rules to that web server. If you specify no web
servers, the service delivers rules to all web servers that connect. If you specify more than one
web server, use a comma (,
) as the delimiter. Any rules that are specified with a
webServers
attribute value of *
are delivered to all web servers.
See the following example:
<dynamicRouting>
<routingRules webServers="webserver1,webserver2">
...
</routingRules>
</dynamicRouting>
Specify the
overrideAffinity attribute of the
<routingRules>
element. By default, a request that has affinity to a particular
server is sent to that server, even if the request matches a routing rule that does not contain the
affinity server as a destination. If the
overrideAffinity property is set to
true
, then selecting a destination that is in a matched rule takes precedence over
selecting the affinity server. If the affinity server satisfies the matched rule, the affinity
server is chosen, even if the affinity server is in a failover set of endpoints. The
overrideAffinity property applies to all routing rules and cannot be set for
individual rules.
<dynamicRouting>
<routingRules webServers="webserver1"
overrideAffinity="true">
...
</routingRules>
</dynamicRouting>
-
Add
<routingRule>
elements as children of the
<routingRules>
element.
- Specify an order attribute for the routing rule and set it to an integer.
The order attribute is required. Rules are evaluated from lowest order to
highest. If more than one rule is assigned the same order attribute, the first
rule that is found is published and all other rules with the same order attribute are discarded. A
good practice is to leave gaps between the order numbers of the rules to provide space for future
rules.
- Specify a matchExpression attribute for the routing rule. Set it to an
expression that can find matching incoming requests. Match expressions combine a set of fixed
operands with operators. You can combine sets of operands and operators by using
AND
and OR
operators.
<dynamicRouting>
<routingRules webServers="webserver1,webserver2">
<routingRule order="100" matchExpression="URI LIKE'/myapp%'">
...
</routingRule>
</routingRules>
</dynamicRouting>
Table 1. matchExpression operands. Include an operand in a matchExpression definition.
Operand |
Syntax |
Description |
Client IPV4 |
clientipv4 |
The IP address of the client that uses the Internet Protocol version 4 (IPv4) dotted quad
address type of n.n.n.n. |
Client IPV6 |
clientipv6 |
The Internet Protocol version 6 (IPv6) 128-bit address type of
x:x:x:x:x:x:x:x that follows Request for Comments 1924 (RFC 1924) of the client
computer. |
Cookie name |
cookie$name |
A cookie name. For example, the expression
cookie$My_Cookie_Name='My_Cookie_Value' tests a request to see whether it contains
a cookie that is named My_Cookie_Name with a My_Cookie_Value
value. To test for the presence or absence of a particular cookie, use one of the following
expressions:
cookie$MyCookieName IS NOT NULL
cookie$MyCookieName IS NULL
|
Header name |
header$name |
A header name and value. For example, the expression
header$Host='localhost' tests a request to see whether it contains an HTTP host
header with a locahost value. To test for presence or absence of the host header,
use one of the following
expressions:
header$Host IS NOT NULL
header$Host IS NULL
|
Percentage |
percentage$val |
The percentage operand evaluates to true some percentage of the time.For
example, percentage$50 evaluates to true on average 50% of the
time.
|
Query parameter |
queryparm$name |
A query parameter name and value. For example, the expression
queryparm$timezone='EST' tests a request to see whether the request contains an
HTTP query parameter that is named timezone with an EST value. To
test for the presence or absence of a query parameter, use one of the following
forms:
queryparm$timezone IS NOT NULL
queryparm$timezone IS NULL
|
URI |
uri |
Uniform Resource Identifier |
Virtual host |
virtualhost |
Virtual host target of the request |
Virtual port |
numeric |
Virtual port target of the request |
Table 2. matchExpression operators. Include an operator in a matchExpression definition as needed.
Operator |
Syntax |
Description |
Equals |
= |
The equality operator expresses a case-sensitive match. |
Equals ignore case |
EQUALSIGNORECASE |
Identical to 'String = String' except that the case of the strings is
ignored. For example, 'ABC' EQUALSIGNORECASE 'abc' evaluates to
true and ('ABC' = 'abc') evaluates to
false . |
IN |
IN |
Expresses an operand with multiple values in a single expression. For example, for an operand
that is called port , to express that the port value can be any or
all of the integers 9080, 9090, and 9091, the expression fragment is port IN
(9080,9090,9091) . How the values inside the parentheses are expressed depends on the
data type. For example, if port is an integer, the correct syntax is the value
without quotation marks. If port is a string, the correct syntax is port IN
('9080','9090','9091') .
|
Is not null |
IS NOT NULL |
Evaluates to true if the specified operand exists. |
Is null |
IS NULL |
Evaluates to true if the specified operand does not exist. |
Like |
LIKE |
Expresses pattern matching for string operand values. The value must contain the wildcard
character percent sign (% ) in the position where the pattern matching starts. For
example:
- The
host LIKE %blanca expression matches the word blanca or
any other word that ends in blanca .
- The
host LIKE blanca% expression matches the word blanca or
any other word that starts with blanca .
- The
host LIKE %blanca% expression matches the word blanca or
any word that contains blanca .
|
Like ignore case |
LIKEIGNORECASE |
Identical to 'string LIKE string' except that the case of the strings is
ignored. |
Like in |
LIKEIN |
Evaluates whether a string exists in a list of strings. For example, string likein
(string1%, string2%, string3%, etc.) evaluates to true if
string matches one or more of the strings in the parentheses. In this example, the
parentheses contain three string values. |
-
Specify an action type for a routing rule.
The three possible action types are permitAction
,
redirectAction
, or rejectAction
. Specify only one of the three
action types for each routing rule.
- Specify the
permitAction
action type to route requests to identified endpoints.
- Add the
<permitAction>
element to a <routingRule>
element.
- Optionally, add the allowMaintenanceModeServers attribute to the
<permitAction>
element to specify whether requests that match the rules are sent
to servers in maintenance mode. The default value for this attribute is false
. When
this attribute is set to true
, requests that match this rule can be sent to servers
that are in maintenance mode.
- Add one or more
<loadBalanceEndPoints>
elements to the
<permitAction>
element.If a <permitAction>
element has
more than one <loadBalanceEndPoints>
element, the first
<loadBalanceEndPoints>
element acts as the primary set of destinations. All
subsequent <loadBalanceEndPoints>
elements act as failover destinations. The
order in which the <loadBalanceEndPoints>
elements are defined determines the
failover priority.
- Add one or more
<endpoint>
elements to each
<loadBalanceEndPoints>
element.
- Add a destination attribute to each
<endpoint>
element.
Set the destination attributes to either a server type or a cluster type. To
specify a server-typed endpoint, specify server=
followed by a four-part server
specification, with parts delimited by a
comma:
<endpoint destination="server=collective_name,host_name,wlp.user.dir,server_name"/>
- collective_name is the name of the collective where the server is a
member.
- host_name is the host address.
- wlp.user.dir is the Liberty user directory on the host system where
the server is defined. You can possibly use the ${wlp.user.dir} variable here,
but it might not be appropriate. When this server.xml is evaluated, the value
of ${wlp.user.dir} is the directory where the controller server is defined. This
might not be the same directory where the member server is defined.
- server_name is the server name.
To specify a cluster-typed endpoint, specify cluster=
followed by a
two-part server specification, with parts delimited by a
comma:
<endpoint destination="cluster=collective_name,cluster_name"/>
- collective_name is the name of the collective where the cluster is
defined.
- cluster_name is the cluster name.
All parts of a server or cluster destination specification can use the wildcard character
(*
) to match any string. To use routing rules to route to multiple collectives,
each collective must have a different name. If the connectorClusterName
attribute of the <dynamicRouting>
element is specified, the collective name is
the value of the connectorClusterName attribute. If the
connectorClusterName attribute of <dynamicRouting>
is not
specified, the collective name is the value that is used for the --collectiveName
option when you run the collective create command. If the
connectorClusterName attribute is not specified, and the
--collectiveName
option is not used, the collective name is
defaultCollective
.
The following example shows a <permitAction>
element with a server-typed
endpoint:
<dynamicRouting maxRetries="5" retryInterval="10000">
<routingRules webServers="myWebServer">
<routingRule order="100" matchExpression="URI LIKE '/myapp%'">
<permitAction>
<loadBalanceEndPoints>
<endpoint destination="server=collective1,myhost,/opt/IBM/liberty/wlp/usr,member1"/>
</loadBalanceEndPoints>
</permitAction>
</routingRule>
</routingRules>
</dynamicRouting>
- Specify the
redirectAction
action type to route a request to another location.
- Add the
<redirectAction>
element to a <routingRule>
element.
- Add a location attribute to the
<redirectAction>
element. Set the location attribute to the new destination for the request.
The following example shows a <redirectAction>
element:
<dynamicRouting maxRetries="5" retryInterval="10000">
<routingRules webServers="myWebServer">
<routingRule order="200" matchExpression="URI LIKE '/myapp%'">
<redirectAction location="http://some.other.destination" />
</routingRule>
</routingRules>
</dynamicRouting>
- Specify the
rejectAction
action type to reject a request with a specific
response code.
- Add the
<rejectAction>
element to a <routingRule>
element.
- Add a code attribute to the
<rejectAction>
element. Set
the code attribute to the HTTP response code to use when the request matches
the rule. The code must be an error code that the web server supports.
The following example shows a <rejectAction>
element:
<dynamicRouting maxRetries="5" retryInterval="10000">
<routingRules webServers="myWebServer">
<routingRule order="300" matchExpression="URI LIKE '/myapp%'">
<rejectAction code="503" />
</routingRule>
</routingRules>
</dynamicRouting>
Results
After the rules are defined, when a web server connects to the dynamic routing service, the rules
that are associated with that web server, and the rules that are associated with all web servers,
are delivered. The web server matches requests against the match expressions that are found in the
rules. The expressions are evaluated according to the rule order, from lowest order to highest. The
first rule with a matching expression is used. The action that is associated with the rule
determines how the request is handled. If no rules are matched, the request load is balanced across
all servers that can handle the request.
By default, when a request has session affinity, server selection is based on affinity. If an
affinity server is found, that server is chosen and the routing rules are not evaluated. To enable
routing rules to override affinity selection, the overrideAffinity attribute
can be added to the <routingRules>
element of the
server.xml file.
Example
The following example combines multiple rules:
<dynamicRouting>
<routingRules webServers="myWebServer">
<routingRule order="100" matchExpression="URI LIKE '/myapp%'">
<permitAction>
<loadBalanceEndPoints>
<endpoint destination="cluster=collective1,clusterB"/>
<endpoint destination="cluster=collective2,clusterB"/>
</loadBalanceEndPoints>
</permitAction>
</routingRule>
<routingRule order="200" matchExpression="uri like '/AppX%' AND queryparm$test = 'true'">
<permitAction allowMaintenanceModeServers="true">
<loadBalanceEndPoints>
<endpoint destination="server=collective1,*,*,member1"/>
</loadBalanceEndPoints>
<loadBalanceEndPoints>
<endpoint destination="server=collective2,*,*,member1"/>
</loadBalanceEndPoints>
</permitAction>
</routingRule>
<routingRule order="300" matchExpression=" uri like '/AppX%' ">
<permitAction>
<loadBalanceEndPoints>
<endpoint destination="cluster=collective1,clusterA"/>
<endpoint destination="cluster=collective2,clusterA"/>
</loadBalanceEndPoints>
</permitAction>
</routingRule>
<routingRule order="400" matchExpression="URI LIKE '/myoldapp'">
<redirectAction location="http://mysite/mynewapp" />
</routingRule>
<routingRule order="500" matchExpression="URI LIKE '/myveryoldapp'">
<rejectAction code="503" />
</routingRule>
</routingRules>
</dynamicRouting>
The routing rule with -order 100
limits the destinations where requests for
/AppX
are routed to two particular clusters across two collectives.
The routing rule with -order 200
shows an example of routing test requests to a
server that is in maintenance mode. If test=true
is added as a query parameter,
then those requests are sent to server
in collective1
, even if
that server is in maintenance mode.
The routing rule with -order 300
shows how to enable failover from one set of
endpoints to another. Rule 300 routes all requests that match the expression to any clusters that
can handle the request in collective1
. If all clusters that can handle the request
in collective1
are not available, clusters that can handle the request in
collective2
are chosen for requests that match the rule expression.
The routing rule with -order 400
shows an example of a redirect rule.
The routing Rule with -order 500
shows an example of a reject rule.