enterprise

In a SignServer system with multiple workers configured to serve different types of signing requests, Request Prioritization allows you to assign different priority levels to different signing requests. When the overall system load requires resources to be prioritized, SignServer system resources are used in a way that means high-priority requests are served with a faster response time than low-priority requests.

Request Prioritization is enabled using a SignServer global configuration property and allows assigning the priority of each request based on the worker the request is targeted to.

The following sections describe how to configure request prioritization and set up the worker, followed by instructions for how to optionally test the feature using stress tests to collect response times.

Step 1 - Configure Global Properties

To enable Request Prioritization on SignServer, set the global configuration property GLOB.QOS_FILTER_ENABLED to true. The feature is by default be disabled (false) in a newly installed or upgraded system.

When enabled, any worker that has not been specifically assigned a high-priority level will have the lowest priority level (0). 

By specifying Worker IDs in combination with priority levels (a higher value means higher priority) the listed workers are assigned higher priority as per the configuration of the parameter GLOB.QOS_PRIORITIES.

Priorities are specified as integers ranging from 0 to the maximum value (GLOB.QOS_MAX_PRIORITY), where a higher number means requests to the worker (when using the /worker servlet) gets a higher priority when requests are getting queued.

Global Properties

The following table lists the global properties and provides a sample for setting priorities on selected workers.

Property

Description

GLOB.QOS_FILTER_ENABLED

Set to true to enable request prioritization in the filter. By default, the filter acts as a pass-through, with the standard behavior of treating all requests the same.

GLOB.QOS_PRIORITIES

Comma-separated list of colon-separated Worker ID-priority pairs.

For example: 1:1,2:2,4:5 will assign the following priority levels (a higher value means higher priority):

  • Priority level 1 to worker with Worker ID 1
  • Priority level 2 to worker with worker ID 2
  • Priority level 5 to worker with worker ID 4

For more information on Worker IDs, see Worker Status Properties Page.

GLOB.QOS_MAX_REQUESTS

Maximum number of requests handled before starting to queue. Default 10. This might need to be adjusted when changing appserver thread pool settings.

GLOB.QOS_MAX_PRIORITY

Maximum priority level. Default 5. Higher priority levels have higher priority. Priority level 0 is the default for workers not assigned a specific priority.


To avoid excessive EJB lookups, the global configuration values are kept cached in the web filter for a default duration of 10 seconds. Thus, depending on timing, updating a global property might take a while before having an effect on assigned priority levels for requests.

Step 2 - Add QoS Status Worker

Follow the steps below to add the QoS Status Worker, providing the status of the prioritization web filter, using the sample configuration file qos-status-worker.properties as a template.

The QoS status worker has the fully qualified class name: org.signserver.server.signers.QoSStatusWorker

  1. Select the SignServer AdminWeb Workers tab, and click Add to add a new worker.
  2. Choose the method From Template.
  3. Select qos-status-worker.properties in the Load from Template list and click Next.
  4. Click Apply to load the configuration and list the worker in the All Workers list.
  5. Select the added worker in the list to open the Worker page.
  6. Check if the Worker status is Offline and if there are any errors listed.

For a list of all QoS Status Worker specific properties, see QoS Status Worker.

Test Request Prioritization

To optionally test Request Prioritization you can set up a system using a specific type of Worker called SleepWorker, allowing the processing time of each request to be configured.

Set up SleepWorkers for Testing

Follow the steps below to set up two SleepWorkers with different priority levels, in the following examples named SleepWorkerHigh and SleepWorkerLow.

  1. Select the SignServer AdminWeb Workers tab.
    • Click Add to create a SleepWorkerHigh worker for sending requests with high priority.
    • Choose the method By Properties.
    • Specify for example the following configuration properties:
      • Name: Specify a name for the worker to be added, in this example, SleepWorkerHigh.
      • Implementation Class: Specify qualified class name of the implementation for the worker.
      • Additional Properties: Click Add to add any other properties to the worker, for example:

        • AUTHTYPE=NOAUTH

        • SLEEP_TIME=1000

        • Click Add again to list the added properties.

    • Click Next and then Apply to load the configuration and list the worker in the All Workers list, displaying the name of the worker followed by its Worker ID in parentheses.

    • Ensure that your SleepWorkerHigh worker is assigned a high-priority level using the GLOB.QOS_PRIORITIES parameter as described in Step 1 - Configure Global Properties.

  2. Next, select the SignServer AdminWeb Workers tab, and click Add to create a SleepWorkerLow worker for sending requests with low priority.
    • Choose the method By Properties.
    • Specify for example the following configuration properties:
      • Name: Specify a name for the worker to be added, in this example, SleepWorkerLow.
      • Implementation Class: Specify qualified class name of the implementation for the worker.
      • Additional Properties: Click Add to add any other properties to the worker, for example:

        • AUTHTYPE=NOAUTH

        • SLEEP_TIME=1000

        • Click Add again to list the added properties.

    • Click Next and then Apply to load the configuration and list the worker in the All Workers list, displaying the name of the worker followed by its Worker ID in parentheses.

    • Ensure that your SleepWorkerLow worker is assigned a low-priority level using the GLOB.QOS_PRIORITIES parameter as described in Step 1 - Configure Global Properties.

With your two SleepWorkers (SleepWorkerHigh and SleepWorkerLow) set up with different priority levels, you can now run stress tests and send requests with both high and low priority.

Run Stress Tests

Run two parallel stress tests using SleepWorkerHigh and SleepWorkerLow and collect the response times.

./bin/stresstest -data "foo" -threads 5 -testsuite DocumentSigner1 -worker SleepWorkerHigh -workerurl http://localhost:8080/signserver/worker -timelimit 60000
./bin/stresstest -data "foo" -threads 100 -testsuite DocumentSigner1 -worker SleepWorkerLow -workerurl http://localhost:8080/signserver/worker -timelimit 60000

After 60 seconds time limit, the output from the stress tests should indicate a lower average response time for requests targeting SleepWorkerHigh than for SleepWorkerLow. 

The following provides an example of the output.

Operations performed: 248
Minimum response time: 1028 ms
Average response time: 1172.1 ms
Maximum response time: 1520 ms
Run time: 61399 ms
Transactions per second: 4.0 tps

Next, while running the performance test, check the queue stats change over time in SignServer AdminWeb.

  1. Select the SignServer AdminWeb Workers tab, select the QoSStatusWorker in the list to open the Worker page.
  2. View the status summary and reload the page to check queue stats change over time.

The following provides an example of the Admin Web output.

Status of Worker with ID 15 (QoSStatusWorker) is: 
Filter enabled : true 
Maximum requests : 1 
Maximum priority level: 5 
Queue size(0) : 0 
Queue size(1) : 0 
Queue size(2) : 0 
Queue size(3) : 0 
Queue size(4) : 0 
Queue size(5) : 0

While running the performance tests, you can also verify from the command line by running the following command.

./bin/signclient signdocument -workername QoSStatusWorker -data ""

The following provides an example of the ACLI output.

FILTER_ENABLED=true
MAX_REQUESTS=10
MAX_PRIORITY_LEVEL=5
QUEUE_SIZE(0)=0
QUEUE_SIZE(1)=0
QUEUE_SIZE(2)=0
QUEUE_SIZE(3)=0
QUEUE_SIZE(4)=0
QUEUE_SIZE(5)=0