[JAVA] Essayez d'implémenter le traitement asynchrone dans Azure

ALH Advent Calender Voici le calendrier de l'Avent ALH! J'ai participé au Nori. Présentation secrète

Cette fois, je présenterai l'architecture dans Azure dans un format pratique.

C'est basé sur des connaissances rudimentaires dans Azure, donc je suis désolé pour Hatsumi-san, mais je suis désolé: pleurez:

Architecture asynchrone sur Azure

Je souhaite utiliser Azure Service Bus, qui est un service de messagerie géré. ..

Pourquoi asynchrone? sur,

Il y a des mérites tels que.

Les options d'architecture de délai en ligne incluent un modèle qui utilise Azure Queue Storage et l'interrogation de base de données, mais j'ai choisi Service Bus car il semble facile à implémenter. (Plutôt, je veux l'utiliser)

La messagerie telle que MQ est un domaine de niche, mais je pense que c'est une architecture indispensable pour les applications cloud natives.

Bien qu'il soit en anglais, nous vous recommandons de regarder ci-dessous. Enterprise Integration Patterns

Entrée à l'étape précédente

Les meilleures pratiques d'architecture sont détaillées dans la documentation officielle d'Azure.

D'autres chapitres sont également recommandés car vous pouvez les étudier simplement en les lisant personnellement!

[Azure] Amélioration de l'évolutivité des applications Web Azure [Azure] Modèle de nivellement de charge basé sur la file d'attente

L'opportunité d'écrire

La documentation et les exemples Azure Java sont difficiles

Le matériel pratique est assez substantiel, mais si vous essayez de l'implémenter avec un contenu un peu détaillé, il existe de nombreux documents C # et Node.js, et l'implémentation Java est difficile. Il est nécessaire de sélectionner une langue qui convient à votre environnement.

Cependant, à partir de maintenant (au 12/07/2019), Pivotal semble travailler dur.

https://pivotal.io/azure-spring-cloud

En outre, le SDK pour le stockage Azure présente les problèmes suivants et la version 12 a une préversion: innocent: Il y a un mythe GA, mais lorsque vous l'utilisez dans un projet réel, l'aperçu est vraiment effrayant, n'est-ce pas?

Microsoft Azure Storage SDK for Java N'utilisez pas la v10,11

J'espère que cet article sera utile à tout le monde!

Diagramme

Il a la configuration suivante.

async-architecture2.png

ServiceBus peut être grossièrement divisé en files d'attente et rubriques, ainsi qu'en JMS et MQ, mais cette fois, nous les créerons dans des files d'attente.

https://www.draw.io/ J'ai utilisé ceci pour créer la figure. Pratique!

Préparation des ressources ServiceBus

Vous pouvez le créer sur le portail, mais cette fois je vais le créer avec CLI.

Environnement d'exécution

#Connexion Azure
az login

#Créer un groupe de ressources
az group create --name async-test --location japaneast

#Création de l'espace de noms ServiceBus (allocation de ressources) environ 1 minute
az servicebus namespace create --resource-group async-test --name serbicebusqueue --location japaneast --sku Basic

#Créer une file d'attente
az servicebus queue create --resource-group async-test --namespace-name serbicebusqueue --name funcqueue

Concernant --name au moment de la création, il est nécessaire d'être unique sur Azure, donc si l'erreur suivante se produit, changez-le en un autre nom.

#Si le nom défini ne peut pas être utilisé
BadRequest - The specified name is not available. CorrelationId: XXXXXXXXXXXXXXXXXXXXXXX

Le portail définit «$ RANDOM». https://docs.microsoft.com/ja-jp/azure/service-bus-messaging/service-bus-quickstart-cli

Exécutez la commande suivante et si la chaîne de connexion s'affiche normalement, la création est terminée.

az servicebus namespace authorization-rule keys list --resource-group async-test --namespace-name serbicebusqueue --name RootManageSharedAccessKey --query primaryConnectionString --output tsv

Endpoint=sb://serbicebusqueue.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=[Chaîne aléatoire]

Bien qu'il s'agisse des bases du cloud, soyez prudent lorsque vous manipulez les clés d'accès.

Création d'applications Web

Obtenez immédiatement un échantillon de montage. Le premier est l'implémentation de l'expéditeur vers ServiceBus.

Créer un projet vide avec Spring Boot Initializr

https://start.spring.io/

Ajouter une dépendance

pom.xml



		<!-- for Azure Service Bus -->
		<dependency>
			<groupId>com.microsoft.azure</groupId>
			<artifactId>azure-servicebus-spring-boot-starter</artifactId>
		</dependency>

Définition de application.properties

Le paramètre de connexion à ServiceBus est défini par la classe Configuration dans starter, définissez donc la chaîne de caractères de connexion et la file d'attente de ServiceBus créées précédemment.

application.properties


#Paramètres du bus de service
azure.servicebus.connection-string=Endpoint=sb://serbicebusqueue.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=[Chaîne aléatoire]
azure.servicebus.queue-name=funcqueue
azure.servicebus.queue-receive-mode=peeklock

Créer une classe de service

En suivant le modèle MVC, implémentez-le en tant que classe de service appelée depuis Controller.

EnqueueService.java


package com.example.async.domain;

import com.microsoft.azure.servicebus.Message;
import com.microsoft.azure.servicebus.QueueClient;
import com.microsoft.azure.servicebus.primitives.ServiceBusException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;

@Service
public class EnqueueService {

    private static final Logger logger = LoggerFactory.getLogger(EnqueueService.class);

    /**
     *AutoConfigure masque les paramètres de connexion à ServiceBus.
     */
    @Autowired
    QueueClient queueClient;

    public boolean sendQueueMessage() {
        String messageBody = "queue Message";
        logger.info("message body:{}", messageBody);
        //Générer un message à envoyer
        Message message = new Message(messageBody.getBytes(StandardCharsets.UTF_8));
        try {
            //Envoyer à Service Bus
            queueClient.send(message);
            queueClient.close();
        } catch (ServiceBusException e) {
            e.printStackTrace();
            return false;
        } catch (InterruptedException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
}

Créer un contrôleur

Préparez un point de terminaison à partir du client et appelez la classe Service à envoyer à ServiceBus.

AsyncController.java


package com.example.async.controller;

import com.example.async.domain.EnqueueService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("async")
public class AsyncController {

    @Autowired
    EnqueueService enqueueService;

    @PostMapping
    public String sendMessage() {
        boolean result = enqueueService.sendQueueMessage();
        if(!result) {
            return "Fail.";
        }
        return "Complete.";
    }
}

Exécution locale

À ce stade, assurez-vous qu'il est envoyé localement à ServiceBus.

mvn spring-boot:run

Essayez de frapper curl depuis une autre console.

curl -X POST localhost:8080/async

S'il fonctionne correctement, vous pouvez le vérifier sur le portail.

service_bus_portal.png

Créer des fonctions

Maintenant que nous avons créé l'expéditeur, nous allons implémenter le récepteur. Utilisez la fonction de déclenchement de Functions.

J'ai essayé de l'implémenter avec Spring Cloud Function, mais je ne peux pas bien utiliser l'extension Functions et je l'implémente avec Java pur. Je voudrais le revérifier à une date ultérieure: sanglot:

Créer un projet à partir de l'archétype maven

Créez un projet vierge à partir de l'archétype Maven selon la documentation officielle. Puisqu'il sera en mode interactif, je le règle comme suit.

mvn archetype:generate \
    -DarchetypeGroupId=com.microsoft.azure \
    -DarchetypeArtifactId=azure-functions-archetype 

[réduction]

Define value for property 'groupId' (should match expression '[A-Za-z0-9_\-\.]+'): com.example.function
[INFO] Using property: groupId = com.example.function
Define value for property 'artifactId' (should match expression '[A-Za-z0-9_\-\.]+'): functions
[INFO] Using property: artifactId = functions
Define value for property 'version' 1.0-SNAPSHOT: : 0.0.1-SNAPSHOT
Define value for property 'package' com.example.function: : 
Define value for property 'appName' functions-20191208134240755: : async-functions
Define value for property 'appRegion' westus: : japaneast
Define value for property 'resourceGroup' java-functions-group: : async-test
Confirm properties configuration:
groupId: com.example.function
groupId: com.example.function
artifactId: functions
artifactId: functions
version: 0.0.1-SNAPSHOT
package: com.example.function
appName: async-functions
appRegion: japaneast
resourceGroup: async-test
 Y: : y

Créer une fonction qui déclenche ServiceBus

Mettez en œuvre comme suit.

ServiceBusFunctions.java


package com.example.function;

import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.ServiceBusQueueTrigger;

/**
 * Azure Functions with ServiceBus Trigger.
 */
public class ServiceBusFunction {

    /**
     *Trigger Service Bus
     * @param message
     * @param context
     */
    @FunctionName("servicebus-trigger")
    public void run(
            @ServiceBusQueueTrigger(name = "message",queueName = "funcqueue", connection="SERVICE_BUS_CONNECTIONSTRING") String message,
            final ExecutionContext context) {
        context.getLogger().info("ServiceBusTrigger start.");
        context.getLogger().info(message);
    }
}

Valeur de réglage de @ ServiceBusQueueTrigger

attribute La description
name Spécifiez n'importe quel nom.
queueName Spécifiez le nom de file d'attente de ServiceBus.
connection Spécifiez la chaîne de connexion pour ServiceBus.
Cette fois dans l'environnement localhost.settings.json, Une chaîne de caractères à utiliser comme variable d'environnement est spécifiée au moment du déploiement.

Paramètres de Local.settings.json

Par défaut, un fichier de configuration pour l'environnement local est créé.

json:local.settings.json


{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "java",
    "SERVICE_BUS_CONNECTIONSTRING": "Endpoint=sb://serbicebusqueue.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=[Valeur clé]"
  }
}

--Il n'est pas requis par le paramètre par défaut qui utilise des déclencheurs HTTP, mais si vous souhaitez utiliser d'autres déclencheurs, vous devez définir ʻAzureWebJobsStorage. Définissez ʻUseDevelopmentStorage = true pour local. --Définissez la chaîne de connexion ServiceBus dans SERVICE_BUS_CONNECTIONSTRING défini dans la classe.

Exécuter dans un environnement local

Exécutons les fonctions localement et récupérons le message envoyé à ServiceBus par une exécution locale plus tôt.

mvn clean package
mvn azure-functions:run

Espérons que le journal suivant devrait être produit.

[Omettre le journal pour le déclencheur HTTP]

[2019/12/08 5:15:56] Executed 'Functions.servicebus-trigger' (Succeeded, Id=e1c75286-c80f-45d9-88ae-d5e8dfb2cd8a)
[2019/12/08 5:18:52] Executing 'Functions.servicebus-trigger' (Reason='New ServiceBus message detected on 'funcqueue'.', Id=07b50ad5-256e-45ee-8bfa-0fb5ddfb7172)
[2019/12/08 5:18:52] Trigger Details: MessageId: 3c3bffa6-c533-41f3-9bf4-7664e16e44bc, DeliveryCount: 1, EnqueuedTime: 2019/12/08 5:18:52, LockedUntil: 2019/12/08 5:19:52, SessionId: (null)
[2019/12/08 5:18:52] ServiceBusTrigger start.
[2019/12/08 5:18:52] queue Message
[2019/12/08 5:18:52] Function "servicebus-trigger" (Id: 07b50ad5-256e-45ee-8bfa-0fb5ddfb7172) invoked by Java Worker
[2019/12/08 5:18:52] Executed 'Functions.servicebus-trigger' (Succeeded, Id=07b50ad5-256e-45ee-8bfa-0fb5ddfb7172)

Vous avez maintenant confirmé que Application Web locale-> Bus serbe-> Fonctions locales peut être exécuté avec succès.

Déployer dans l'environnement Azure

Déployez l'application créée sur Azure.

Vous pouvez également créer des ressources avec l'interface de ligne de commande, mais les exemples Azure sont souvent créés automatiquement au moment du déploiement et contiennent des chaînes aléatoires, créez donc un AppService dans le portail.

Créer un service d'application

AppService alloue des ressources aux applications Web. Vous pouvez économiser des ressources en déployant plusieurs applications sur le même App Service. Cependant, étant donné que les ressources telles que le processeur sont partagées, il est plus sûr de diviser les fonctions en un plan de paiement à l'utilisation pour le fonctionnement réel.

J'ai créé un groupe de ressources pour ʻasync-test` lorsque j'ai créé le Service Bus, donc je vais l'utiliser.

portal_appservice.png

Depuis le 7 décembre 2019, lors de l'implémentation de Java avec des fonctions, le système d'exploitation d'App Service est uniquement Windows, alors sélectionnez Windows.

Déployer des applications Web

Ajoutez le plugin Maven à pom.xml.

pom.xml


      <plugin>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>azure-webapp-maven-plugin</artifactId>
        <version>1.8.0</version>
        <configuration>
          <schemaVersion>V2</schemaVersion>
          <resourceGroup>async-test</resourceGroup>
          <appName>async-app</appName>
          <appServicePlanName>appservice-async-test</appServicePlanName>
          <region>japaneast</region>
          <!--Plan AppServicePlan-->
          <pricingTier>S1</pricingTier>
          <runtime>
            <os>windows</os>
            <javaVersion>1.8</javaVersion>
            <webContainer>java 8</webContainer>
          </runtime>
          <deployment>
            <resources>
              <resource>
                <directory>${project.basedir}/target</directory>
                <includes>
                  <include>*.jar</include>
                </includes>
              </resource>
            </resources>
          </deployment>
        </configuration>
      </plugin>

Déployez avec ʻazure-webapp-maven-plugin` de maven.

mvn clean package
mvn azure-webapp:deploy

commande curl

curl -H 'Content-Length:0' -X POST https://async-app.azurewebsites.net/async

Nécessite l'en-tête Content-Length.

Déployer des fonctions

Étant donné que le modèle est généré lors de la création d'un projet vide, définissez AppServiePlan.

pom.xml


      <plugin>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>azure-functions-maven-plugin</artifactId>
        <configuration>
          <resourceGroup>${functionResourceGroup}</resourceGroup>
          <appName>${functionAppName}</appName>
          <region>${functionAppRegion}</region>
          <!--Paramètres AppServicePlan-->
          <appServicePlanName>appservice-async-test</appServicePlanName>

          <appSettings>
            <!-- Run Azure Function from package file by default -->
            <property>
              <name>WEBSITE_RUN_FROM_PACKAGE</name>
              <value>1</value>
            </property>
            <property>
              <name>FUNCTIONS_EXTENSION_VERSION</name>
              <value>~2</value>
            </property>
          </appSettings>
        </configuration>
        <executions>
          <execution>
            <id>package-functions</id>
            <goals>
              <goal>package</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

Déployez avec ʻazure-functions-maven-plugin` de maven.

mvn clean package
mvn azure-functions:deploy

Une fois déployée, la fonction a été créée, définissez donc la chaîne de connexion ServiceBus dans les paramètres de l'application.

portal_functions.png

Source de l'échantillon

https://github.com/bokuwakuma/azure-spring-boot-servicebus

Résumé

J'ai fini par me familiariser avec la documentation Azure, mais je suis accro aux fonctions Azure à bien des égards. Il y a quelques points addictifs si vous n'essayez pas de créer un peu plus d'application.

De plus, je ne pense pas que je ferai un déploiement direct à partir de local, donc j'aimerais essayer de déployer dans un pipeline en utilisant GitHub Actions. La prochaine fois, j'aimerais en faire plus à ce sujet.

Recommended Posts

Essayez d'implémenter le traitement asynchrone dans Azure
Essayez d'implémenter Yuma dans Kinx
Essayez d'implémenter Android Hilt en Java
Implémentation du traitement asynchrone dans Tomcat
Implémentation du traitement asynchrone compatible multi-tenant dans Tomcat
Traitement des threads de l'interface utilisateur asynchrone Android
Comment implémenter le traitement asynchrone dans Outsystems
Implémentation du traitement asynchrone pour un seul locataire dans Tomcat
Il est tard! Essayez d'implémenter la notification Android en Java (débutant)
Fonctions Azure en Java
Essayez LetCode dans Ruby-TwoSum
Traitement asynchrone et intégration d'API Web dans Android Studio
Utiliser MouseListener avec le traitement
Il est tard! Essayez d'implémenter Android Work Manager en Java (débutant)
Implémentons la vérification de signature du code de courbe elliptique en Java
Essayez de passer au traitement asynchrone via MQ sans changer le code
Essayez d'utiliser RocksDB avec Java
API (lors de la mise en œuvre d'une communication asynchrone)
Essayez d'appeler JavaScript en Java
Essayez de développer Spresense avec Java (1)
Essayez le type fonctionnel en Java! ①
Traitement d'écriture dans IntelliJ IDEA
Spring avec Kotorin --6 Traitement asynchrone
Créer des fonctions Azure en Java
Essayez d'implémenter une session WebFlux
Traitement parallèle mesuré avec Java
Traitement du jugement Mazume dans la pêche
Essayez d'implémenter un filtre WebFlux
[Swift] Traitement asynchrone à l'aide de PromiseKit
[Traitement] Essayez d'utiliser GT Force.
Appui simultané sur une touche en traitement