Skip to content
This repository has been archived by the owner on May 29, 2024. It is now read-only.

Mission: AMQ Messaging Work Queue

Ladislav Thon edited this page Jun 29, 2018 · 1 revision

Messaging Work Queue

ID Short Name

200

messaging-work-queue

Description

This mission demonstrates how to dispatch tasks to a scalable set of worker services using a message queue. It uses the AMQP 1.0 message protocol to send and receive messages. The workers can be implemented in a variety of different languages and application runtimes.

Having a single, well-known shared resource for adding and consuming work makes it easier to scale the number of workers up and down. The frontend does not need to know any of the details of the backend workers. The use of a standard messaging protocol enables frontends and workers written in any language to interoperate.

This mission covers:

  • Sending work requests to a common work queue

  • Receiving and processing work requests as they come in

  • Sending the processed result back to the requesting service

  • Adding new workers as demand increases or removing workers as it dies down

  • Monitoring the current state of the worker services

User Problem

The user has a large number of discrete tasks that require processing. To make sure they are processed with satisfactory speed, the user wants to be able to add worker services on demand as the number of outstanding tasks grows.

One could achieve this by telling every requesting service about every worker service, but that requires updating many potential requesters. Instead, the user wants to design the system so that the requester does not need to know how many workers there are, and the workers do not need to know which service the request came from.

Concepts and Architectural Patterns

This mission contains a distributed messaging application that demonstrates the request-response messaging pattern. It contains multiple components that communicate using a messaging server.

The frontend, a web server, registers requests to perform work by sending a request message to a well known queue. A backend worker then fetches the work request from the queue and performs the work.

When the frontend creates the request message, it also establishes a queue for responses. It includes the address of this queue in its request. After processing the work, the backend worker sends the result as a response to the pre-established response queue.

  • Sending and receiving messages. The application uses the AMQP message protocol to communicate using queues and topics on a message server.

  • Sending request messages and receiving response messages. The application demonstrates how the request-response messaging pattern is implemented in AMQP.

  • Periodically sending broadcast updates. The application demonstrates use of the publish-subscribe messaging pattern for distributing information to multiple consumers.

  • Maintaining connections between services. The frontend and backend components reconnect to the message server if the connection is lost.

  • Scaling backend workers up and down. The operator can freely add and remove backend workers.

The frontend uses HTTP to communicate with a browser. The browser submits new requests by performing HTTP POSTs, and it polls for responses by performing periodic HTTP GETs. This approach may or may not fit the needs of your application. An alternative approach might consume push events delivered directly to the browser.

Use Case

Deployment

  1. Apply the OpenShift templates to your current project. The templates create OpenShift entities that are used in subsequent steps.

    oc apply -f templates/
  2. Create the broker application. This command configures and deploys the broker.

    oc new-app --template=amq63-basic \
      -p APPLICATION_NAME=work-queue-broker \
      -p IMAGE_STREAM_NAMESPACE=$(oc project -q) \
      -p MQ_PROTOCOL=amqp \
      -p MQ_QUEUES=work-queue/requests,work-queue/responses \
      -p MQ_TOPICS=work-queue/worker-updates \
      -p MQ_USERNAME=work-queue \
      -p MQ_PASSWORD=work-queue
  3. Create the frontend application. This command builds and deploys the frontend web server.

    Replace <runtime> with your chosen runtime. The options are nodejs, spring-boot, wfswarm, and vertx.

    oc new-app --template=<runtime>-messaging-work-queue-frontend
  4. Create the worker application. This command builds and deploys the backend worker.

    oc new-app --template=<runtime>-messaging-work-queue-worker

Operation

  1. Navigate to the frontend web server. Use the URL shown under the <runtime>-messaging-work-queue-frontend application in the project overview.

  2. Enter text in the Requests form field. The system will be responsible for perfoming a "to upper case" operation on the input, returning the result, which is also tagged with the worker ID.

  3. See the response text in uppercase under Responses.

  4. In the OpenShift console, increase the number of worker pods to two.

  5. In the frontend web interface, note the presence of two workers under Workers.

  6. Submit multiple requests.

  7. See responses returned from each worker in turn.

Acceptance Criteria

Frontend

  • An HTTP POST to http://<frontend>/api/send-request with the following JSON payload succeeds. The processed result is not returned in the HTTP response.

    {
      "text": "abc"
    }
  • Subsequent GET requests to http://<frontend>/api/data contain the following JSON, which represents all requests that have been processed by the system.

    {
      "responses": [
        {
          "workerId": "<worker-id>",
          "text": "ABC"
        }
      ]
    }

Queues and Topics

All queues and topics use the prefix work-queue to avoid collisions with any other applications using the broker.

  • Queue work-queue/requests

  • Topic work-queue/worker-updates

Some runtime environments do not allow for creation of dynamic reply queues. In these cases, a queue named work-queue/responses is used.

  • Queue work-queue/responses

Worker IDs

Worker IDs take the form worker-<runtime>-<four-digit-unique-ID>, where <runtime> is one of nodejs, spring, wfswarm, or vertx. Examples:

  • worker-nodejs-4d78

  • worker-wfswarm-18ac

  • worker-spring-dc7e

Request Message Format

On receiving user input, the frontend sends a request message to the work-queue/requests queue. Workers consume new requests from the queue.

The request message must have the following elements.

  • Property reply-to: Either a dynamically generated reply queue (if possible) or work-queue/responses (AMQP string)

  • Body: Text supplied by the user (AMQP string)

Response Message Format

After processing a request, the worker sends a response message to the queue indicated by the reply-to property of the request message.

The response message must have the following elements.

  • Application property workerId: The worker ID (AMQP string)

  • Body: The user text after processing (AMQP string)

Worker Update Message Format

Workers send update messages every five seconds to the work-queue/worker-updates topic. The frontend subscribes to the topic and keeps the latest status for each worker.

The update message must have the following elements.

  • Application property timestamp: The current time in milliseconds (AMQP long)

  • Application property workerId: The worker ID (AMQP string)

  • Application property requestsProcessed: The total number of requests processed (AMQP long)

Integration Requirements

Tags