cancel
Showing results for 
Search instead for 
Did you mean: 

HowTo: Write Health Monitors in TrafficScript

Why write a health monitor in TrafficScript?

 

The Health Monitoring capabilities (as described in Feature Brief: Health Monitoring in Stingray Traffic Manager) are very comprehensive, and the built-in templates allow you to conduct sophisticated custom dialogues, but sometimes you might wish to resort to a full programming language to implement the tests you need.

 

Particularly on the Stingray Virtual Appliance, your options can be limited.  There's a minimal Perl interpreter included (see Tech Tip: Running Perl code on the Stingray Virtual Appliance), and you can upload compiled binaries (Writing a custom Stingray Health Monitor in C) and shell scripts.  This article explains how you can use TrafficScript to implement health monitors, and of course with Java Extensions, TrafficScript can 'call out' to a range of third-party libraries as well.

 

Overview

 

We'll implement the solution using a custom 'script' health monitor.  This health monitor will probe a virtual server running on the local Stingray (using an HTTP request), and pass it all of the parameters relevant to the health request.

 

A TrafficScript rule running on the Stingray can perform the appropriate health check and respond with a 'PASS' (200 OK) or 'FAIL' (500 Error) response.

 

The health monitor script

 

The health monitor script is straightforward and should not need any customization.  It will take its input from the health monitor configuration.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/bin/sh 
exec $ZEUSHOME/perl/miniperl -wx $0 ${1+"$@"
    if 0; 
   
#!/usr/bin/perl 
#line 7 
   
BEGIN{ 
       # Pull in the Stingray (Zeus) libraries for HTTP requests 
       unshift @INC, "$ENV{ZEUSHOME}/zxtmadmin/lib/perl","$ENV{ZEUSHOME}/zxtm/lib/perl"
   
use Zeus::ZXTM::Monitor qw( ParseArguments MonitorWorked MonitorFailed Log ); 
use Zeus::HTMLUtils qw( make_query_string ); 
use Zeus::HTTP; 
   
my %args = ParseArguments(); 
   
my $url = "http://localhost:$args{vsport}$args{path}?".make_query_string( %args ); 
my $http = new Zeus::HTTP( GET => $url ); 
$http->load(); 
   
Log( "HTTP GET for $url returned status: " . $http->code() ); 
   
if( $http->code() == 200 ) { 
   MonitorWorked(); 
} else
   MonitorFailed( "Monitor failed: " . $http->code() . " " . $http->body() ); 
}

 

Upload this to the Monitor Programs of the Extra Files section of the catalog, and then create an "External Program Monitor" based on that script.  You will need to add two more configuration parameters to this health monitor configuration:

 

  • vsport: This should be set to the port of the virutal server that will host the trafficscript test
  • path: This is optional - you can use it if you want to run several different health tests from the trafficscript rule

 

Your configuration should look something like this:

 

Screen Shot 2013-04-24 at 16.40.11.png

The virtual server

 

Create an HTTP virtual server listening on the appropriate port number (vsport).  You can bind this virtual server to localhost if you want to prevent external clients from accessing it.

 

The virtual server should use the 'discard' pool - we're going to add a request rule that always sends a response, so there's no need for any backend nodes.

 

The TrafficScript Rule

 

The 'business end' of your TrafficScript health monitor resides in the TrafficScript rule.  This rule is invoked every time the health monitor script is run, and it is given the details of the node which is to be checked.

 

The rule should return a 200 OK HTTP response if the node is OK, and a different response (such as 500 Error) if the node has failed the test.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
$path = http.getPath(); # Use 'path' if you would like to publish 
                        # several different tests from this rule 
   
$ip = http.getFormParam( "ipaddr" ); 
$port = http.getFormParam( "port" ); 
$nodename = http.getFormParam( "node" ); 
   
# We're going to test the node $nodename on $ip:$port 
# Useful functions include: 
#   http.request.get/put/post/delete() 
#   tcp.connect/read/write/close() 
#   auth.query() 
#   java.run() 
   
   
sub Failed( $msg ) { 
   http.sendResponse( 500, "text/plain", $msg, "" ); 
   
# Let's run a simple GET 
$req = 'GET / HTTP/1.0 
Host: www.riverbed.com 
   
'; 
$timeout = 1000; # ms 
$sock = tcp.connect( $ip, $port, $timeout ); 
tcp.write( $sock, $req, $timeout ); 
$resp = tcp.read( $sock, 102400, $timeout ); 
   
# Perform whatever tests we want on the response data.  
# For example, it should begin with '200 OK' 
   
if( ! string.startsWith( $resp, "HTTP/1.1 200 OK" ) ) { 
   Failed( "Didn't get expected response status" ); 
   
# All good 
http.sendResponse( 200, "text/plain", "", "" );

 

Version history
Revision #:
1 of 1
Last update:
‎04-24-2013 08:48:AM
Updated by:
 
Labels (1)
Comments
bmelo

Hi, I've having a hard time getting this to work. I'm using a developer Virtual Appliance v9.2.

I followed your guidelines and activated verbose on the monitor. I get "Can't open" errors on the log but both webservers are online... I checked the "Running Perl code on the Stingray Virtual Appliance" and the beginning of your perl script isn't exactly the same... Tried with that and get "No such file or directory" error...

Any ideas?