Faisons une discussion WEB en utilisant WebSocket avec AWS sans serveur (Python)!

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 240_news012.jpg

... 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.

Quoi faire

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). qiita作るもの.png

Configuration du système

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.

qiita作るもの.png

codage

1. Tout d'abord, préparez API Gateway!

1-1. Créez une nouvelle passerelle API pour "Web Socket"

Sélectionnez WebSocket pour créer une nouvelle passerelle API. キャプチャ.PNG

La formule de sélection d'itinéraire est définie ici sur "$ request.body.action". Vous pouvez changer cela plus tard.

1-2. Je fais des itinéraires un par un d'ici

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. キャプチャ.PNG

Mais avant cela, je dois créer un rôle DynamoDB et IAM.

1-3. Déployer et créer une scène

Je n'ai encore créé aucune route, mais je vais la déployer et créer une étape. キャプチャ.PNG

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.

2. Créer un rôle IAM pour Lambda

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. キャプチャ.PNG

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.

3. Créez une table (DynamoDB) qui gère les informations de connexion

La clé primaire doit-elle être la chaîne "id"? キャプチャ.PNG

4. Créez une connexion lors de la connexion

4-1. Faire Lambda

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.

4-2. Intégrer API Gateway et Lambda

Intégrez le Lambda "ac19_onConnect" ci-dessus avec la racine de connexion API Gateway créée précédemment. キャプチャ.PNG

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.

5. Créez une racine (déconnexion) lors de la déconnexion

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' }

6. Créez une route (sendMessage) lorsqu'un sendMessage est reçu

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' }

7. Créez une page Web HTML

À 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! qiita作るもの.png

référence

Je l'ai fait principalement en regardant la page AWS. https://aws.amazon.com/jp/blogs/news/announcing-websocket-apis-in-amazon-api-gateway/

en conclusion

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)!

Recommended Posts

Faisons une discussion WEB en utilisant WebSocket avec AWS sans serveur (Python)!
Créez un framework Web avec Python! (2)
[Chat De Tornado] Créez un chat en utilisant WebSocket dans Tornado
Faisons une interface graphique avec python.
Faisons un graphe avec python! !!
Créons un client de socket Web avec Python. (Authentification par jeton d'accès)
Faisons un jeu de shiritori avec Python
Faisons la voix lentement avec Python
Faisons un bot Twitter avec Python!
Remplaçons UWSC par Python (5) Faisons un robot
Faisons un module pour Python en utilisant SWIG
[Jouons avec Python] Créer un livre de comptes de ménage
Essayez de créer un jeu simple avec Python 3 et iPhone
Faites une loterie avec Python
[Super facile] Faisons un LINE BOT avec Python.
Faisons une rupture de bloc avec wxPython
Créer un système de recommandation avec python
Faisons un spacon avec xCAT
[AWS Hands-on] Créons un service d'identification des célébrités avec une architecture sans serveur!
Faisons une application WEB pour l'annuaire téléphonique avec flacon Partie 2
Faisons une application WEB pour l'annuaire téléphonique avec flacon Partie 3
Créez une application de scraping avec Python + Django + AWS et modifiez les tâches
J'ai créé un chat-holdem de serveur de jeu de poker en utilisant websocket avec python
[AWS] Utilisation de fichiers ini avec Lambda [Python]
Créons un groupe gratuit avec Python
Démonisez une application Web Python avec Supervisor
Faisons un langage simple avec PLY 1
[Python] Une application web rapide avec Bottle!
[Python] Rendons matplotlib compatible avec le japonais
Faisons un site multilingue en utilisant flask-babel
Exécutez une application Web Python avec Docker
Faisons une IA à trois yeux avec Pylearn 2
Faisons un calcul de combinaison avec Python
Créez une application de bureau avec Python avec Electron
Touchez AWS avec Serverless Framework et Python
Créons une fonction de chat avec Vue.js + AWS Lambda + dynamo DB [Paramètres AWS]
[Ev3dev] Faisons un programme de contrôle à distance par Python avec le protocole RPyC
[Streamlit] Je déteste JavaScript, donc je crée une application Web uniquement avec Python
Faisons une animation 3D uniquement avec Python sans utiliser Blender! [FBX SDK Python]
J'ai essayé de créer un service de raccourcissement d'url sans serveur avec AWS CDK
Je souhaite créer une application Web en utilisant React et Python flask
Implémentez une application simple avec Python full scratch sans utiliser de framework web.
Créer un bot Twitter Trend avec heroku + Python
Je veux faire un jeu avec Python
Démarrez un serveur Web Python simple avec Docker
Créer une carte Web en utilisant Python et GDAL
Lancer un serveur Web avec Python et Flask
Web scraping avec Python (prévisions météo)
Web scraping avec Python (cours de l'action)
Extraire des données d'une page Web avec Python
Créons une application Web de conversion A vers B avec Flask! De zéro ...
WEB grattage avec python et essayez de créer un nuage de mots à partir des critiques
Si vous voulez créer un bot discord avec python, utilisons un framework
Combinez des chaînes répétitives en une seule avec des expressions régulières Python.
Faisons un outil de veille de commande avec python
(Python) Essayez de développer une application Web en utilisant Django
[Pratique] Créez une application Watson avec Python! # 2 [Fonction de traduction]