Beginning

Creating and running a HTTP workload using fhb and a workload configuration File

If you need a simple workload that generates HTTP Get/Post requests to multiple URLs, then it's possible to do that very easily in Faban using the fhb command line. All you need to do is to configure the workload using fhb configuration file. The fhb configuration file is essentially a stripped down Faban configuration file. An example is provided at samples/fhb/run.xml.

To control the mix of URLs accessed in the benchmark run, it's possible to assign weights to the URLs. This is similar to an operation mix in a general purpose driver. It's also possible to generate random values for parameters in the request strings by using pre-defined tokens.

1. Starting the fhb driver definition

We start the fhb driver definition with a runConfig element. The namespace rules for this configuration file is the same as any generic Faban configuration file and is documented in the Faban Harness Developers Guide. The Faban driver part of the configuration file is documented in the Faban Driver Developers Guide. Since almost all of the elements used in the fhb configuration file will use the driver namespace, we declare the driver namespace http://faban.sunsource.net/ns/fabandriver as the default namespace in the root element of the configuration file, which happens to be runConfig. Then you will want to provide your basic run parameters, scale, ramp up, steady state, and rampdown. These parameters override whatever you may have specified in the fhb command line. In the example below, we set a scale of 10 for 10 simulated users.

<fa:runConfig xmlns:fa="http://faban.sunsource.net/ns/faban"
              xmlns="http://faban.sunsource.net/ns/fabandriver">

    <fa:scale>10</fa:scale>
    <fa:runControl unit="time">
        <fa:rampUp>60</fa:rampUp>
        <fa:steadyState>120</fa:steadyState>
        <fa:rampDown>60</fa:rampDown>
    </fa:runControl>

.....
</fa:runConfig>

2. Define the benchmark

A Benchmark is defined using the <benchmarkDefinition> element. The benchmarkDefinition element and its child elements are defined by the driver namespace, but since we're using this as a default namespace (above) already, we can omit any namespace aliases for these elements.

    <benchmarkDefinition>
        <name>my_http_driver</name>
        <version>1.0a</version>
        <metric>ops/sec</metric>
        <scaleName>scale</scaleName>
        <scaleUnit>suppliers</scaleUnit>
    </benchmarkDefinition>

The <benchmarkDefinition> element is optional and can be omitted if all default values are accepted.

3. Define the driver

In the HTTP driver, the definition of the driver is part of the the <driverConfig> element of the fhb config file. The name of the driver is specified in the <driverConfig> element as follows:

   <driverConfig name="http_driver1">

At this point of time, only one HTTP driver can be defined in a benchmark.

4. Declare the operations

Operations define the logic to generate load to the severs. All operations for a driver are defined under the driverConfig element with an operation child element.

        <operation>
            <name>getCustomerInfo</name>
            <url>http://lifeboat.sfbay:8000/</url>
            <get><![CDATA[?zd=rahul&id=@@faban.
                getRandomString(1,10)@@&xd=abcdef&yd=@@faban.
                getRandomInt(1,200)@@]]></get>

            <!--<post><![CDATA[id=@@faban.
                getRandomString(1, 10)@@&xd=abcdef&yd=@@faban.
                getRandomInt(1,200)@@]]></post>-->

            <!--<get/>-->
            <max90th>2</max90th>
            <!--timing is AUTO-->
            <!--override benchmark level requestLagTime-->
            <requestLagTime>
                <fixedTime>
                    <cycleType>cycletime</cycleType>
                    <cycleTime>1000</cycleTime>
                    <cycleDeviation>5</cycleDeviation>
                </fixedTime>
                <!-- other types can be specified in a similar manner-->
            </requestLagTime>
        </operation>

Each operation requires a name, an HTTP URL, an HTTP request string and the 90th percentile limit for the response time. The HTTP request can be specified either as a GET or a POST. If a GET is used, then the element must be <GET> and the CDATA section must start with “?”. If a POST is used then the element must be <POST> and the CDATA section should not start with a “?”. You must specify either a GET or a POST element. If your request string is empty, you can leave the value for the GET/POST element empty.

The request string specified in the <get> or <post> elements needs to be in an HTTP get/post format, with each name value pair separated by an “&”. Faban can generate random values (both numbers and strings) for any parameter in the request string. There are two kinds of random value generation supported by faban currently.

1. Random number between X, Y where X < Y.
2. Random string of length between X, Y where X < Y.


The value part of the name-value combination must have either of the following tokens


@@faban.getRandomInt(X,Y)@@ -- for a random number in the range of X, Y

@@faban.getRandomString(X,Y)@@ -- for a random string of length in the range of X, Y.



5. Choose a mix

A mix tells the driver framework the policy or algorithm it should use to select operations. While the Faban driver framework may be extended to support additional mixes over time, currently it supports four mixes:

This mix is specified in the faban config file: 

        <operationMix>
            <name>getCustomerInfo</name><r>1</r>
        </operationMix>
        <operationMix>
            <name>getSupplierInfo</name><r>1</r>
        </operationMix>

The above defines a FlatMix. Other examples for mix are in the sample faban config file in Appendix D.

6. Choose the cycle timings

Cycle timings tell the driver framework the policy or algorithm to be used for inter-operation times. Currently, three timing characteristics are supported:

    1. NegativeExponential - Randomly selects the cycle or think time from a negative exponential distribution. This is the timing characteristic that most appropriately simulates the cycle of a large number of users such as web workloads.
    2. Uniform - Randomly selects the cycle or think time from a uniform distribution.
    3. FixedTime - Presets the cycle or think time. This is useful for simulating user operations that are driven by external factors such as factory or production line workers.

The cycle timings can be defined at the driver level under the <driverConfig> element or at the operation level under the <operation> element. The driver level definition covers all operations in that driver. The operation level definition specifies the cycle timings for only that operation. It also overrides the driver level definition if there is one, just for the given operation.

The followings example shows specifying the uniform distribution for cycle time at the driver level:

        <requestLagTime>
            <uniform>
                <cycleType>thinktime</cycleType>
                <cycleMin>1000</cycleMin>
                <cycleMax>1000</cycleMax>
                <cycleDeviation>5</cycleDeviation>
            </uniform>
        </requestLagTime>


The following example shows specifying the fixed time distribution for cycle time at the operation level:

        <requestLagTime>
            <fixedTime>
                <cycleType>cycletime</cycleType>
                <cycleTime>1000</cycleTime>
                <cycleDeviation>5</cycleDeviation>
            </fixedTime>
        </requestLagTime>


Configuration File Recap

When putting the configuration file together, we should see the whole config file as shown in the fhb sample faban/samples/fhb/run.xml. The whole configuration file will be like the following:

<?xml version="1.0" encoding="UTF-8"?>
<fa:runConfig xmlns:fa="http://faban.sunsource.net/ns/faban"
              xmlns="http://faban.sunsource.net/ns/fabandriver">
    <fa:scale>10</fa:scale>
    <fa:runControl unit="time">
        <fa:rampUp>60</fa:rampUp>
        <fa:steadyState>120</fa:steadyState>
        <fa:rampDown>60</fa:rampDown>
    </fa:runControl>
    <benchmarkDefinition>
        <name>my_http_driver</name>
        <version>1.0a</version>
        <metric>ops/sec</metric>
        <scaleName>scale</scaleName>
        <scaleUnit>suppliers</scaleUnit>
    </benchmarkDefinition>
    <outputDir>/home/rb125607/work/http_driver/driver/output</outputDir>
    <audit>false</audit>
    <threadStart>
        <delay>1000</delay>
        <simultaneous>false</simultaneous>
        <parallel>false</parallel>
    </threadStart>
    <runtimeStats enabled="false">
        <interval>5</interval>
    </runtimeStats>
    <driverConfig name="http_driver1">
        <threads>5</threads>
        <agents>1</agents>
        <runtimeStats target="9988"/>
        <metric>ops/sec</metric>
        <requestLagTime>
            <!--<fixedTime>
                <cycleType>cycletime</cycleType>
                <cycleTime>1000</cycleTime>
                <cycleDeviation>5</cycleDeviation>
            </fixedTime>-->
            <uniform>
                <cycleType>thinktime</cycleType>
                <cycleMin>1000</cycleMin>
                <cycleMax>1000</cycleMax>
                <cycleDeviation>5</cycleDeviation>
            </uniform>
            <!-- other types can be specified in a similar manner-->
        </requestLagTime>
        <operation>
            <name>getCustomerInfo</name>
            <url>http://lifeboat.sfbay:8000/</url>
            <get><![CDATA[?zd=rahul&id=@@faban.
                getRandomString(1, 10)@@&xd=abcdef&yd=@@faban.
                getRandomInt(1,200)@@]]></get>
            <!--<post><![CDATA[id=@@faban.
                getRandomString(1, 10)@@&xd=abcdef&yd=@@faban.
                getRandomInt(1,200)@@]]></post>-->
            <!--<get/>-->
            <max90th>2</max90th>
            <!--timing is AUTO-->
            <!--override benchmark level requestLagTime-->
            <requestLagTime>
                <fixedTime>
                    <cycleType>cycletime</cycleType>
                    <cycleTime>1000</cycleTime>
                    <cycleDeviation>5</cycleDeviation>
                </fixedTime>
                <!-- other types can be specified in a similar manner-->
            </requestLagTime>
        </operation>
        <operation>
            <name>getSupplierInfo</name>
            <url>http://lifeboat.sfbay:8000</url>
            <!--<get><![CDATA[?zd=rahul&id=@@faban.
                getRandomString(1, 10)@@&xd=abcdef&yd=@@faban.
                getRandomInt(1,200)@@]]></get>-->
            <post><![CDATA[id=@@faban.
                getRandomString(1, 10)@@&xd=abcdef&yd=@@faban.
                getRandomInt(1,200)@@]]></post>
            <!--<get/>-->
            <max90th>2</max90th>
            <!--timing is AUTO-->
            <!--override benchmark level requestLagTime-->
            <!--<requestLagTime>
                <uniform>
                <cycleType>thinktime</cycleType>
                <cycleMin>10</cycleMin>
                <cycleMax>10</cycleMax>
                <cycleDeviation>5</cycleDeviation>
                </uniform>-->
                <!-- other types can be specified in a similar manner-->
            <!--</requestLagTime>-->
        </operation>
 
        <operationMix>
            <name>getCustomerInfo</name><r>1</r>
        </operationMix>
        <operationMix>
            <name>getSupplierInfo</name><r>1</r>
        </operationMix>
        <properties>
            <property>
                <name>put</name>
                <value>ORACLE</value>
            </property>            
            <property>
                <name>serverURL</name>
                <value>http://lifeboat.sfbay:8000/pb/PBServletDriver?action=</value>
            </property>            
        </properties>
    </driverConfig>
</fa:runConfig>

Run the test

Modify that according to your needs. You do not need to follow any other steps in this document for defining a driver if your needs are satisfied with a simple HTTP based driver. Then just simply run the workload by calling:

$fhb -f run.xml

Observe the output from the run and follow the locations in the output. You'll be able to see the run output written to the terminal as well as in the target directories that store the output.

Beginning