IoT où vous n'avez pas attendu (partie 3). Construire un modèle de simulation

Comme je l'ai déjà dit dans la dernière partie , lors du développement d'un projet IoT, les protocoles d'interaction avec les appareils sont plutôt instables et les chances de perdre le contact avec les appareils de test après la mise à jour du firmware étaient assez importantes. Plusieurs équipes ont été impliquées dans le développement, et il y avait une exigence stricte - ne pas perdre la capacité de tester la couche métier de l'application, même si le flashage des appareils interrompt l'ensemble du flux de travail avec les capteurs.

image

Afin de permettre aux analystes métier de tester leurs hypothèses sur des données plus ou moins proches de la réalité, nous avons construit un modèle de simulation de l'appareil. Ainsi, si l'appareil tombait en panne en raison d'un nouveau micrologiciel et que les données devaient être reçues de toute urgence, nous avons lancé un modèle de simulation au lieu d'un véritable appareil sur le réseau, qui, selon l'ancien format, a généré les données et produit le résultat.

De plus, l'avantage du modèle était que l'entreprise n'achèterait jamais un grand nombre d'appareils uniquement pour tester une hypothèse. Par exemple, l'équipe d'analyse commerciale a décidé que la prévision du temps de remplissage des conteneurs devrait fonctionner différemment. Et pour tester leur hypothèse, personne ne courra pour acheter 10 000 capteurs.

Développement d'un modèle de simulation


Le modèle de simulation lui-même était le suivant: L'

image

état et le comportement de la poubelle sont décrits par une machine d'état régulière. Tout d'abord, nous initialisons la machine d'état avec l'état `EMPTY (level = 0)` et nous pouvons effectuer certaines actions dessus, c'est-à-dire jeter des ordures dans le conteneur. Nous devons maintenant déterminer si le conteneur reste vide `(niveau? MAX_LEVEL)` ou s'il est plein` (niveau> = MAX_LEVEL) `. Si c'est le deuxième, alors l'état passe à `FULL`.

Quelqu'un peut décharger les ordures d'un conteneur plein, ou le concierge est venu nettoyer son désordre, et nous devons décider dans quel état passer. L'état `CHOICE` est responsable du choix d'une action - dans la terminologie d'une machine d'état, quelque chose de similaire à un bloc if.

Un autre conteneur peut brûler, puis l'état de la machine d'état passe à «FEU». En outre, le conteneur peut tomber et son état devient "FALL" (dans le rapport, j'ai parlé des raisons inattendues que peuvent provoquer des chutes de conteneur). Mais il existe un autre état `LOST`, qui est valable à partir de tout autre état - il est défini lorsque la connexion est perdue.

Une telle machine d'état décrit presque tout le comportement du conteneur et du capteur sur celui-ci. Mais cela ne suffit pas pour faire un modèle de simulation, car nous connaissons les états et les transitions possibles de ceux-ci, mais nous ne savons pas quelle est la probabilité de ces événements et quand ils se produiront.

En fait, il s'est avéré que la probabilité d'événements dépendait de l'heure de la journée, car:

  • les transporteurs ne travaillent pas la nuit;
  • les gens jettent plus de déchets à certaines heures (le matin avant le travail et le soir).

Par conséquent, nous avons permis à l'équipe d'analyse commerciale de personnaliser le comportement de simulation. Il était possible de définir la probabilité d'un événement à une certaine heure de la journée.

Test de stress simple et intuitif


L'imitation elle-même présente de nombreux avantages, dont l'un est le test de charge bon marché. C'est bon marché parce que l'imitation est, en fait, un thread séparé qui démarre la machine d'état, lui applique des événements et les événements eux-mêmes sont envoyés au vrai serveur.

Par conséquent, la simulation pour le backend n'est pas différente du vrai capteur. Et si nous devons exécuter 1000 capteurs, exécutez 1000 threads et travaillez. De plus, la simulation évolue parfaitement.

image

D'une part, il est plutôt grossier de tester la charge, mais d'autre part, la simulation a permis de piloter beaucoup de données au plus près de la réalité pour l'ensemble du projet. Et n'oubliez pas les développeurs chinois talentueux qui ont ignoré les protocoles standard comme MQTT et scié leur protocole au-dessus des sockets. Par conséquent, nous avons dû faire notre propre implémentation d'un serveur qui accepte les données sur les sockets pour ce protocole propriétaire.

Un tel serveur devait être multi-thread, car il existe de nombreux capteurs d'entrée. et cette partie doit également être testée séparément à l'aide de tests de performances. Vous pouvez prendre JMeter (écrire un script de test typique), JMH / JCStress (tester des parties isolées et faire un benchmark plus fin), ou quelque chose d'autre. Lorsque vous prenez une décision dans une situation similaire, je vous conseille d'écouter les professionnels, par exemple Alexei Shipilev. À JPoint 2017, il froidement parlé de la façon de référence différentes choses et ce que vous devez penser à faire lors des tests de performance.


Nous avons choisi l'option de faire quelque chose de notre choix, car le projet avait une approche atypique de l'assurance qualité - nous n'avons pas d'équipe de testeurs distincte et l'équipe de backend elle-même a testé la fonctionnalité. Autrement dit, la personne qui a écrit le serveur de socket devait couvrir le code avec des unités ordinaires, des tests d'intégration et de performance.

Nous avions un petit outil qui nous a permis de décrire rapidement le scénario de charge et de l'exécuter dans la bonne quantité de threads parallèles:

StressTestRunner.test()
                .mode(ExecutionMode.EXECUTOR_MODE)
                .threads(THREADS_COUNT)
                .iterations(MESSAGES_COUNT)
                .timeout(5, TimeUnit.SECONDS)
                .run(() -> sensor.send(MESSAGE));

Awaitility.await()
          .atMost(5, TimeUnit.SECONDS)
          .untilAsserted(() ->
            verifyReceived(MESSAGES_COUNT)
          );

Nous disons combien de threads vous devez exécuter, combien de messages envoyer, combien de temps cela devrait prendre et envoyer des données au socket dans chaque thread. Il ne reste plus qu'à attendre que notre serveur traite correctement toutes ces données. Seules quelques lignes de code ont été publiées et peuvent être écrites par un développeur principal.

Émulation de problèmes de réseau


À l'aide de l'imitation, nous avons pu simuler un travail de mauvaise qualité et spécifique avec des prises. Les cartes SIM GSM dans les capteurs n'ont pas d'adresse IP «blanche», et nous pourrions recevoir des données de différentes adresses IP 50 fois par jour. Et il arrivait souvent que la connexion soit ouverte, nous commencions à transférer des données, puis l'adresse IP change, et le serveur ouvre une nouvelle connexion sans fermer l'ancienne. Si nous ne prenions pas cela en compte, dans quelques jours, nous manquerions de ports libres sur le serveur.

image

Il y avait également un problème avec différents capteurs de vitesse. Un appareil lent peut ouvrir la connexion et se bloquer pendant un certain temps, tandis qu'un appareil rapide enverra quelque chose. Et tout cela doit être traité correctement. En imitation, il est facile de simuler une situation similaire en utilisant des pauses.

image

Ce n'est qu'une partie des scénarios qui peuvent être incorporés dans le modèle.

résultats


Il me semble que c'est précisément la possibilité de simulation qui distingue fortement l'IoT des autres projets. La simulation du comportement d'un appareil est plus facile que le comportement humain. En entrée, nous obtenons des valeurs déterministes qui correspondent bien à notre modèle, et non des actions humaines aléatoires. Parce que le comportement des appareils est logiquement plus facile à décrire que le comportement des personnes, et tester le système devient plus facile.

Nous avons examiné plusieurs aspects différents du développement de l'IoT.

image

Si vous avez ignoré les deux parties précédentes de cet article, vous pouvez les trouver ici:

IoT où vous n'avez pas attendu (Partie 1) - Le sujet et les problèmes de l'
IoT où vous n'avez pas attendu (Partie 2) - Architecture d'application et test IoT de choses spécifiques

Github avec les outils de test en question.

. , Heisenbug , IoT. , ! JPoint, . Heisenbug JPoint 6 . !

All Articles