Amazon Simple Notification Service (SNS) Γ¨ un servizio di messaggistica basato su pubblicazione/sottoscrizione. Permette di inviare notifiche a una vasta gamma di destinatari, inclusi email, SQS, SMS, e funzioni Lambda. SNS Γ¨ altamente scalabile e supporta casi dβuso come notifiche push per dispositivi mobili, avvisi di sistema e aggiornamenti in tempo reale. Il servizio Γ¨ gratis fino a 1 milione di publisher.
Lβidea di base di SNS Γ¨ estendere il concetto di SQS creando n code invece che una sola in modo che ogni consumer
utilizzi solo la coda sui messaggi che lo riguardano.
Il producer
invierΓ i messaggi ad un unico punto chiamato topic
il quale funge da hub centralizzato per inoltrare messaggi a piΓΉ sottoscrittori in modo asincrono, per esempio a piΓΉ SQS.
Ogni topic sarΓ associato a n subscriptions
che saranno i servizi (esempio SQS) a cui inviare i messaggi.
I consumer
utilizzeranno una SQS esattamente come lβesempio sopra senza sapere che dietro cβΓ¨ questo ulteriore layer di disaccoppiamento.
Vantaggi:
- Ogni consumer processerΓ tutti i messaggi della coda, senza implementare filtri per capire se Γ¨ un messaggio inviato a lui o meno.
- Posso inviare lo stesso messaggio anche a piΓΉ code insieme, se la mia applicazione lo necessita
- Ogni singola coda avrΓ la sua dead letter queue separata dalle altre: per esempio se ho un bug nellβapplicativo che invia le mail non voglio che tali messaggi, che andranno nella DLQ, siano mescolati ad altri messaggi di altri bug di altri applicativi.
AWS
Creare Topic e Subscription
Per prima cosa Γ¨ necessario creare un topic
che Γ¨ lβhub dove verranno inviati i messaggi. Poi si dovrΓ scegliere tra Standard
e FIFO
e, come per le SQS, Γ¨ meglio scegliere Standard
e gestire lato applicativo lβidempotenza.
Una volta creato il topic
Γ¨ necessario creare almeno una subscription
in modo che sappia dove inviare il messaggio.
Nellβinterfaccia di creazione della subscription
dovrΓ² fornire il topic
, il protocollo (esempio Amazon SQS) e la coda di destinazione che devo aver giΓ creato in precedenza.
Raw Message Delivery
SNS di default wrappa il messaggio originale in un suo formato stile Notification, cosa che tipicamente non voglio in quanto voglio che il mio messaggio sia inoltrato così come è alle varie subscriptions
senza essere modificato in alcun modo.
Questo puΓ² essere indicando selezionando la checkbox Raw Message Delivery
.
Permessi
Per ultima cosa devo indicare alla coda che esiste un topic SNS che puΓ² scriverci dentro, altrimenti questβultimo, non avendo i permessi per farlo, non funzionerΓ .
Per farlo devo andare nella Queue Policies
e aggiungere un nuovo Statement
.
{
"Version": "2012-10-17",
"Id": "__default_policy_ID",
"Statement": [
{
"Sid": "__owner_statement",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::412381757397:root"
},
"Action": "[[SQS]]:*",
"Resource": "arn:aws:[[SQS]]:eu-west-3:412381757397:customers"
},
// Da qui in poi Γ¨ lo statement che permette al topic di scriverci dentro
{
"Effect": "Allow",
"Principal": {
"Service": "sns.amazonaws.com"
},
"Action": "[[SQS]]:SendMessage",
"Resource": "arn:aws:[[SQS]]:eu-west-3:412381757397:customers", //ARN della coda in questione
"Condition": {
"ArnEquals": {
"aws:SourceArn": "arn:aws:sns:eu-west-3:412381757397:customers" // ARN del topic SNS
}
}
}
]
}
In-app filter
Una delle feature principali di SNS Γ¨ permettere automaticamente di inoltrare i messaggi alle code in base a dei criteri in modo che ogni coda riceva solo i messaggi che la riguardano e non tutti i messaggi.
Per farlo bisogna andare nella subscription
, sezione Subscription filter policy
dove posso specificare una policy basata sullβattributo del messaggio oppure anche su alcune caratteristiche del body, il tutto tramite un json.
Per esempio questo json filtra solo i messaggi che hanno come attributo MessageType
il valore CustomerCreated
.
{
"MessageType": [
"CustomerCreated"
]
}
Esempio
Il pacchetto nuget per lavorare con SNS Γ¨ Amazon.SimpleNotificationService
, una volta aggiunto i metodi sono molto simili a quelli di SQS con la differenza nella terminologia.
Publisher
var customer = new CustomerCreated
{
Id = Guid.NewGuid(),
Email = "nick@nickchapsas.com",
FullName = "Nick Chapsas",
DateOfBirth = new DateTime(1993, 1, 1),
GitHubUsername = "nickchapsas"
};
var snsClient = new AmazonSimpleNotificationServiceClient();
var topicArnResponse = await snsClient.FindTopicAsync("customers");
var publishRequest = new PublishRequest
{
TopicArn = topicArnResponse.TopicArn,
Message = JsonSerializer.Serialize(customer),
MessageAttributes = new Dictionary<string, MessageAttributeValue>
{ { "MessageType", new MessageAttributeValue
{
DataType = "String",
StringValue = nameof(CustomerCreated)
} } }};
var response = await snsClient.PublishAsync(publishRequest);
Consumer
Il consumer Γ¨ identico a quello implementato per la SQS in quanto per lui Γ¨ una normale coda, non sa che dietro cβΓ¨ un sistema SNS.