-
Notifications
You must be signed in to change notification settings - Fork 43
Mission: AMQ Messaging Work Queue
ID | Short Name |
---|---|
|
|
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
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.
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.
-
Apply the OpenShift templates to your current project. The templates create OpenShift entities that are used in subsequent steps.
oc apply -f templates/
-
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
-
Create the frontend application. This command builds and deploys the frontend web server.
Replace
<runtime>
with your chosen runtime. The options arenodejs
,spring-boot
,wfswarm
, andvertx
.oc new-app --template=<runtime>-messaging-work-queue-frontend
-
Create the worker application. This command builds and deploys the backend worker.
oc new-app --template=<runtime>-messaging-work-queue-worker
-
Navigate to the frontend web server. Use the URL shown under the
<runtime>-messaging-work-queue-frontend
application in the project overview. -
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.
-
See the response text in uppercase under Responses.
-
In the OpenShift console, increase the number of worker pods to two.
-
In the frontend web interface, note the presence of two workers under Workers.
-
Submit multiple requests.
-
See responses returned from each worker in turn.
-
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" } ] }
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 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
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) orwork-queue/responses
(AMQP string) -
Body: Text supplied by the user (AMQP string)
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)
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)
Node.js booster - https://github.com/ssorj/nodejs-messaging-work-queue
Spring Boot booster - https://github.com/gytis/spring-boot-messaging-booster
WildFly Swarm booster - https://github.com/ssorj/wfswarm-messaging-work-queue
Vert.x booster - https://github.com/ssorj/vertx-messaging-work-queue-booster