-
Notifications
You must be signed in to change notification settings - Fork 422
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: add Worker Services to docs site. (#2785)
<!-- Provide summary of changes --> <!-- Issue number, if available. E.g. "Fixes #31", "Addresses #42, 77" --> By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
- Loading branch information
Showing
10 changed files
with
234 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# Publish/Subscribe Architectures | ||
|
||
Copilot [Worker Services](../manifest/worker-service.en.md) take advantage of the `publish` field common to all service and job types to allow customers to easily create publish/subscribe logic for passing messages between services. | ||
|
||
A common pattern in AWS is the combination of SNS and SQS to deliver and process messages. [SNS](https://docs.aws.amazon.com/sns/latest/dg/welcome.html) is a robust message delivery system which can send messages to a variety of subscribed endpoints with guarantees about message delivery. | ||
|
||
[SQS](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html) is a message queue to allow asynchronous processing of messages. Queues can be populated by one or more SNS topics or AWS EventBridge event filters. | ||
|
||
The combination of these two services effectively decouples the sending and receipt of messages, meaning publishers don't have to care what queues are actually subscribed to their topics, and worker service code doesn't have to care where the messages come from. | ||
|
||
## Sending Messages from a Publisher | ||
|
||
To allow an existing service to publish messages to SNS, simply set the `publish` field in its manifest. You'll need a name for the topic which describes its function, and an optional list of the worker services you'd like to grant permission to subscribe to this topic. These services don't necessarily have to exist when you write them down in the publisher's manifest. | ||
|
||
```yaml | ||
# manifest.yml for api service | ||
name: api | ||
type: Backend Service | ||
|
||
publish: | ||
topics: | ||
- name: orders | ||
allowed_workers: [orders-worker, receipts-worker] | ||
``` | ||
This will create an [SNS topic](https://docs.aws.amazon.com/sns/latest/dg/welcome.html) and set a resource policy on the topic to allow Copilot services called `orders-worker` and `receipts-worker` to create subscriptions. | ||
|
||
Copilot also injects the ARNs of any SNS topics into your container under the environment variable `COPILOT_SNS_TOPIC_ARNS`. | ||
|
||
### Javascript Example | ||
Once the publishing service has been deployed, you can send messages to SNS via the AWS SDK for SNS. | ||
|
||
```javascript | ||
const { SNSClient, PublishCommand } = require("@aws-sdk/client-sns"); | ||
const client = new SNSClient({ region: "us-west-2" }); | ||
const {orders} = JSON.parse(process.env.COPILOT_SNS_TOPIC_ARNS); | ||
const out = await client.send(new PublishCommand({ | ||
Message: "hello", | ||
TopicArn: orders, | ||
})); | ||
``` | ||
|
||
## Subscribing to a topic with a Worker Service | ||
|
||
To subscribe to an existing SNS topic with a worker service, you'll need to edit the worker service's manifest. Using the [`subscribe`](../manifest/worker-service/#subscribe) field in the manifest, you can define subscriptions to existing SNS topics exposed by other services in your environment. In this example, we'll use the `orders` topic which the `api` service from the last section exposed. We'll also customize the worker service's queue to enable a dead-letter queue. The `tries` field tells SQS how many times to try redelivering a failed message before sending it to the DLQ for further inspection. | ||
|
||
```yaml | ||
name: orders-worker | ||
type: Worker Service | ||
subscribe: | ||
topics: | ||
- name: orders | ||
service: api | ||
queue: | ||
dead_letter: | ||
tries: 5 | ||
``` | ||
|
||
Copilot will create a subscription between this worker service's queue and the `orders` topic from the `api` service. It will also inject the queue URI into the service container under the environment variable `COPILOT_QUEUE_URI`. | ||
|
||
### Javascript Example | ||
|
||
The central business logic of a worker service's container involves pulling messages from the queue. To do this with the AWS SDK, you can use the SQS Clients for your language of choice. In Javascript, the logic for pulling, processing, and deleting messages from the queue would look like the following code snipped. | ||
|
||
```javascript | ||
const { SQSClient, ReceiveMessageCommand, DeleteMessageCommand } = require("@aws-sdk/client-sqs"); | ||
const client = new SQSClient({ region: "us-west-2" }); | ||
const out = await client.send(new ReceiveMessageCommand({ | ||
QueueUrl: process.env.COPILOT_QUEUE_URI, | ||
WaitTimeSeconds: 10, | ||
})); | ||
console.log(`results: ${JSON.stringify(out)}`); | ||
|
||
if (out.Messages === undefined || out.Messages.length === 0) { | ||
return; | ||
} | ||
|
||
// Process the message here. | ||
|
||
await client.send( new DeleteMessageCommand({ | ||
QueueUrl: process.env.COPILOT_QUEUE_URI, | ||
ReceiptHandle: out.Messages[0].ReceiptHandle, | ||
})); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<div class="separator"></div> | ||
|
||
<a id="publish" href="#publish" class="field">`publish`</a> <span class="type">Map</span> | ||
The `publish` section allows services to publish messages to one or more SNS topics. By default, no worker services are allowed to subscribe to the created topics. Worker services in the environment can be allowlisted using the `allowed_workers` field on each topic. | ||
|
||
```yaml | ||
publish: | ||
topics: | ||
- name: order-events | ||
allowed_workers: [database-worker, receipts-worker] | ||
``` | ||
In the example above, this manifest declares an SNS topic named `order-events` and authorizes the worker services named `database-worker` or `receipts-worker` which are deployed to the Copilot environment to subscribe to this topic. | ||
|
||
<span class="parent-field">publish.</span><a id="publish-topics" href="#publish-topics" class="field">`topics`</a> <span class="type">Array of topics</span> | ||
List of [`topic`](#publish-topics-topic) objects. | ||
|
||
<span class="parent-field">publish.topics.</span><a id="publish-topics-topic" href="#publish-topics-topic" class="field">`topic`</a> <span class="type">Map</span> | ||
Holds naming information and permissions for a single SNS topic. | ||
|
||
<span class="parent-field">topic.</span><a id="topic-name" href="#topic-name" class="field">`name`</a> <span class="type">String</span> | ||
Required. The name of the SNS topic. Must contain only upper and lowercase letters, numbers, hyphens, and underscores. | ||
|
||
<span class="parent-field">topic.</span><a id="topic-allowed-workers" href="#topic-allowed-workers" class="field">`allowed_workers`</a> <span class="type">Array of strings</span> | ||
An array containing the names of worker services which are authorized to subscribe to this SNS topic. If this field is not specified, no workers will be able to create subscriptions to this SNS topic. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
List of all available properties for a `'Worker Service'` manifest. To learn about Copilot services, see the [Services](../concepts/services.en.md) concept page. | ||
|
||
???+ note "Sample manifest for a worker service" | ||
|
||
```yaml | ||
# Your service name will be used in naming your resources like log groups, ECS services, etc. | ||
name: orders-worker | ||
type: Worker Service | ||
|
||
# Configuration for your containers and service. | ||
image: | ||
build: ./orders/Dockerfile | ||
|
||
subscribe: | ||
topics: | ||
- name: events | ||
service: api | ||
- name: events | ||
service: fe | ||
queue: | ||
retention: 96h | ||
timeout: 30s | ||
dead_letter: | ||
tries: 10 | ||
|
||
cpu: 256 | ||
memory: 512 | ||
count: 1 | ||
|
||
variables: | ||
LOG_LEVEL: info | ||
secrets: | ||
GITHUB_TOKEN: GITHUB_TOKEN | ||
|
||
# You can override any of the values defined above by environment. | ||
environments: | ||
test: | ||
count: | ||
spot: 2 | ||
production: | ||
count: 2 | ||
``` | ||
|
||
<a id="name" href="#name" class="field">`name`</a> <span class="type">String</span> | ||
The name of your service. | ||
|
||
<div class="separator"></div> | ||
|
||
<a id="type" href="#type" class="field">`type`</a> <span class="type">String</span> | ||
The architecture type for your service. [Worker Services](../concepts/services.en.md#worker-service) are not reachable from the internet or elsewhere in the VPC. They are designed to pull messages from their associated SQS queues, which are populated by their subscriptions to SNS topics created by other Copilot services' `publish` fields. | ||
|
||
<div class="separator"></div> | ||
|
||
<a id="subscribe" href="#subscribe" class="field">`subscribe`</a> <span class="type">Map</span> | ||
The `subscribe` section allows worker services to create subscriptions to the SNS topics exposed by other Copilot services in the same application and environment. Each topic can define its own SQS queue, but by default all topics are subscribed to the worker service's default queue. | ||
|
||
```yaml | ||
subscribe: | ||
topics: | ||
- name: events | ||
service: api | ||
queue: # Define a topic-specific queue for the api-events topic. | ||
timeout: 20s | ||
- name: events | ||
service: fe | ||
queue: # By default, messages from all topics will go to a shared queue. | ||
timeout: 45s | ||
retention: 96h | ||
delay: 30s | ||
``` | ||
<span class="parent-field">subscribe.</span><a id="subscribe-queue" href="#subscribe-queue" class="field">`queue`</a> <span class="type">Map</span> | ||
By default, a service level queue is always created. `queue` allows customization of certain attributes of that default queue. | ||
|
||
<span class="parent-field">subscribe.queue.</span><a id="subscribe-queue-delay" href="#subscribe-queue-delay" class="field">`delay`</a> <span class="type">Duration</span> | ||
The time in seconds for which the delivery of all messages in the queue is delayed. Default 0s. Range 0s-15m. | ||
|
||
<span class="parent-field">subscribe.queue.</span><a id="subscribe-queue-retention" href="#subscribe-queue-retention" class="field">`retention`</a> <span class="type">Duration</span> | ||
Retention specifies the time a message will remain in the queue before being deleted. Default 4d. Range 60s-336h. | ||
|
||
<span class="parent-field">subscribe.queue.</span><a id="subscribe-queue-timeout" href="#subscribe-queue-timeout" class="field">`timeout`</a> <span class="type">Duration</span> | ||
Timeout defines the length of time a message is unavailable after being delivered. Default 30s. Range 0s-12h. | ||
|
||
<span class="parent-field">subscribe.queue.dead_letter.</span><a id="subscribe-queue-dead-letter-tries" href="#subscribe-queue-dead-letter-tries" class="field">`tries`</a> <span class="type">Integer</span> | ||
If specified, creates a dead letter queue and a redrive policy which routes messages to the DLQ after `tries` attempts. That is, if a worker service fails to process a message successfully `tries` times, it will be routed to the DLQ for examination instead of redriven. | ||
|
||
<span class="parent-field">subscribe.</span><a id="subscribe-topics" href="#subscribe-topics" class="field">`topics`</a> <span class="type">Array of `topic`s</span> | ||
Contains information about which SNS topics the worker service should subscribe to. | ||
|
||
<span class="parent-field">topic.</span><a id="topic-name" href="#topic-name" class="field">`name`</a> <span class="type">String</span> | ||
Required. The name of the SNS topic to subscribe to. | ||
|
||
<span class="parent-field">topic.</span><a id="topic-service" href="#topic-service" class="field">`service`</a> <span class="type">String</span> | ||
Required. The service this SNS topic is exposed by. Together with the topic name, this uniquely identifies an SNS topic in the copilot environment. | ||
|
||
{% include 'image-config.en.md' %} | ||
|
||
{% include 'image-healthcheck.en.md' %} | ||
|
||
{% include 'common-svc-fields.en.md' %} |