Cet article est le deuxième jour de NTT Technocross Calendrier de l'Avent 2019.
Bonjour. Je m'appelle Yasuda. Je suis en charge du développement de nouveaux produits liés à l'IA chez NTT Techno Cross. Bien qu'il s'écarte immédiatement du sujet principal, dessiner un manga est une rupture récente, et je dessine le manga suivant.
Liaison de données comprise par manga Architecture d'entreprise à l'ère de l'IA comprise par les mangas Stratégie informatique comprise par manga
... Eh bien, dans cet article, je voudrais voir comment faire "Web Socket" sans serveur AWS. Il semble qu'AWS API Gateway ait pu configurer la communication WebSocket depuis décembre 2018, et je voulais l'essayer un jour, alors je l'ai essayé. Quand j'ai recherché, j'ai trouvé de nombreux exemples de programmes qui utilisent node.js dans AWS Lambda, mais je n'ai pas trouvé d'exemples Python ... Je suis bon en Python, donc j'aimerais écrire du code Python.
Faites un chat WEB. Lorsque vous vous connectez à la page Web et rédigez un message, le message sera livré en temps réel à tous les terminaux connectés à cette page (ayant une session WebSocket).
Il est créé en combinant API Gateway, Lambda et DynamoDB, qui sont des éléments typiques d'AWS sans serveur. La page Web à publier fonctionnera simplement en plaçant le fichier HTML sur le PC local, ou elle fonctionnera même si elle est facilement publiée en le plaçant sur l'hébergement statique de S3.
Sélectionnez WebSocket pour créer une nouvelle passerelle API.
La formule de sélection d'itinéraire est définie ici sur "$ request.body.action". Vous pouvez changer cela plus tard.
Créez la route lors de la connexion (connexion), la route lors de la déconnexion (déconnexion) et la route lors de l'envoi d'un message (sendMessage) un par un.
Mais avant cela, je dois créer un rôle DynamoDB et IAM.
Je n'ai encore créé aucune route, mais je vais la déployer et créer une étape.
Là où il est effacé en bleu, une chaîne de caractères unique est saisie. Cette chaîne unique sera utilisée la prochaine fois que vous créerez un rôle IAM.
Tout d'abord, ajoutez "AWSLambdaBasicExecutionRole" pour exécuter Lambda et "AmazonDynamoDBFullAccess" pour exécuter DynamoDB. * Il n'est pas nécessaire que ce soit un accès complet, mais c'est facile.
Après cela, définissez la stratégie en ligne suivante. Vous pouvez désormais accéder à l'API Gatteway depuis Lambda.
Politique en ligne
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"execute-api:ManageConnections"
],
"Resource": [
"arn:aws:execute-api:ap-northeast-1:<ID de locataire ici>:<Écrivez ici la chaîne de caractères unique d'API Gateway que vous avez définie précédemment.>/*"
],
"Effect": "Allow"
}
]
}
Dans l'image du rôle ci-dessus qui est effacée en bleu, essayez de définir la chaîne de caractères unique qui est apparue lors du premier déploiement d'API Gateway.
La clé primaire doit-elle être la chaîne "id"?
Créez un nouveau Lambda / Python 3.8. Définissez le rôle IAM que vous avez utilisé précédemment. Le programme est simple car il n'y a que deux lignes en vigueur, sans considérer le système anormal. (En fait, cela devrait être fait en tenant compte du système anormal.) Tout ce que vous avez à faire est d'obtenir l'identifiant de connexion connecté et de l'enregistrer auprès de DynamoDB.
ac19_onConnect/lambda_function.py
import json
import os
import boto3
dynamodb = boto3.resource('dynamodb')
connections = dynamodb.Table(os.environ['CONNECTION_TABLE'])
def lambda_handler(event, context):
connection_id = event.get('requestContext',{}).get('connectionId')
result = connections.put_item(Item={ 'id': connection_id })
return { 'statusCode': 200,'body': 'ok' }
Définissez le nom du DynamoDB créé précédemment dans la variable d'environnement Lambda "CONNECTION_TABLE". Le délai d'expiration devrait être de 3 secondes, mais je l'ai réglé à environ 1 minute.
Intégrez le Lambda "ac19_onConnect" ci-dessus avec la racine de connexion API Gateway créée précédemment.
La procédure est la même lors de l'intégration des racines de déconnexion et de sendMessage décrites ci-dessous avec Lambda. N'oubliez pas de déployer la scène une fois qu'elle est intégrée.
Suivez la même procédure que la route de connexion, créez d'abord un programme Lambda et intégrez-le à la route de déconnexion API Gateway. Si vous ne pensez pas aux systèmes anormaux, le programme est simple, récupérez simplement l'identifiant de connexion déconnecté et supprimez-le de DynamoDB. Les autres paramètres de Lambda (rôle, délai d'expiration, variables d'environnement) sont identiques à ceux du programme onConnect précédent.
ac19_onDisconnect/lambda_function.py
import json
import os
import logging
import boto3
dynamodb = boto3.resource('dynamodb')
connections = dynamodb.Table(os.environ['CONNECTION_TABLE'])
def lambda_handler(event, context):
connection_id = event.get('requestContext',{}).get('connectionId')
result = connections.delete_item(Key={ 'id': connection_id })
return { 'statusCode': 200, 'body': 'ok' }
Seul sendMessage a quelques lignes, mais c'est facile à faire. Lorsqu'il reçoit un sendMessage, il remet simplement le message à chaque connexion enregistrée dans DynamoDB. Suivez les mêmes étapes que précédemment, créez d'abord un programme Lambda, créez une route sendMessage dans API Gateway et intégrez-la à cette route. N'oubliez pas de déployer API Geteway sur scène. Les autres paramètres de Lambda (rôle, délai d'expiration, variables d'environnement) sont les mêmes que les deux précédents Lambda.
ac19_sendMessage/lambda_function.py
import json
import os
import sys
import logging
import boto3
import botocore
dynamodb = boto3.resource('dynamodb')
connections = dynamodb.Table(os.environ['CONNECTION_TABLE'])
def lambda_handler(event, context):
post_data = json.loads(event.get('body', '{}')).get('data')
print(post_data)
domain_name = event.get('requestContext',{}).get('domainName')
stage = event.get('requestContext',{}).get('stage')
items = connections.scan(ProjectionExpression='id').get('Items')
if items is None:
return { 'statusCode': 500,'body': 'something went wrong' }
apigw_management = boto3.client('apigatewaymanagementapi',
endpoint_url=F"https://{domain_name}/{stage}")
for item in items:
try:
print(item)
_ = apigw_management.post_to_connection(ConnectionId=item['id'],
Data=post_data)
except:
pass
return { 'statusCode': 200,'body': 'ok' }
À la place de "wss: //" dans le programme, écrivez la chaîne de caractères unique d'API Gateway que vous avez définie précédemment. Ce HTML peut être exécuté même s'il est placé localement sur le PC, ou même s'il est publié sur l'hébergement statique d'AWS S3.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Tchat d'essai "Web Socket"!</title>
</head>
<body>
<H3>Tchat d'essai "Web Socket"!</H3>
<input id="input" type="text" />
<button onclick="send()">Envoyer</button>
<pre id="output"></pre>
<script>
var input = document.getElementById('input');
var output = document.getElementById('output');
var socket = new WebSocket("wss://<Écrivez ici la chaîne de caractères unique d'API Gateway que vous avez définie précédemment.>.execute-api.ap-northeast-1.amazonaws.com/v01");
socket.onopen = function() {
output.innerHTML += "J'ai pu me connecter!\n";
};
socket.onmessage = function(e) {
output.innerHTML += "Reçu:" + e.data + "\n";
};
function send() {
socket.send(JSON.stringify(
{
"action":"sendMessage",
"data": input.value
}
));
input.value = "";
};
</script>
</body>
</html>
Bien! C'est tout ce qu'on peut en dire! Essayons!
Je l'ai fait principalement en regardant la page AWS. https://aws.amazon.com/jp/blogs/news/announcing-websocket-apis-in-amazon-api-gateway/
Maintenant que je peux configurer un WebSocket sans serveur AWS, je suis ravi de pouvoir faire diverses choses. Puis, Jour 3 de NTT Technocross Calendrier de l'Avent 2019 Merci de continuer à profiter de 5bc108bdf5068ef7be2f)!