Test de vitesse HTTP pour les services SMS REST

Besoin de mesurer les performances de votre service SMS basé sur HTTP ? Le Test de vitesse HTTP pour les services SMS REST est un outil puissant conçu pour évaluer la vitesse et la fiabilité de vos points de terminaison d'API JSON/REST. Cette utilitaire téléchargeable vous permet de simuler des requêtes SMS à haut volume, de suivre les taux de réussite et de calculer les requêtes par seconde, vous aidant ainsi à optimiser les performances du serveur sous charge. Que vous testiez un environnement de développement local ou que vous évaluiez une passerelle SMS en production, cet outil fournit des métriques claires pour les requêtes totales, les connexions concurrentes et l'efficacité du HTTP Keep-Alive. Téléchargez la solution C# prête à l'emploi ou intégrez le code source fourni dans votre flux de travail de test pour une analyse précise des performances de l'API.

Téléchargement

HttpSpeedTest.zip

Exemple d'utilisation

Figure 1 - Comment utiliser l'outil de test de vitesse

Code source

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

class Program
{
    static readonly Random random = new Random();
    static readonly string[] sampleMessages = {
        "Hello, this is a test message.",
        "Performance testing HTTP server capabilities.",
        "Measuring requests per second for JSON API.",
        "Random message content for load testing.",
        "Another test message with different content.",
        "Checking server capacity under load.",
        "How many requests can the server handle?",
        "Stress testing the SMS API endpoint.",
        "This message is automatically generated.",
        "Final test message in the sample set."
    };

    static async Task Main(string[] args)
    {
        Console.WriteLine("HTTP Server JSON API Performance Tester");
        Console.WriteLine("---------------------------------------");

        if (args.Length < 3)
        {
            Console.WriteLine("Usage: Program    [useKeepAlive]");
            Console.WriteLine("Example: Program http://198.50.122.178:8080 1000 50 true");
            Console.WriteLine("Example: Program https://api.example.com/sms 5000 100 false");
            Console.WriteLine("Example: Program http://localhost/innotest/innotest.php 50 10 false");
        
            return;
        }

        string baseUrl = args[0];
        if (!Uri.TryCreate(baseUrl, UriKind.Absolute, out Uri uriResult) ||
            (uriResult.Scheme != Uri.UriSchemeHttp && uriResult.Scheme != Uri.UriSchemeHttps))
        {
            Console.WriteLine("Invalid base URL. Must be a valid HTTP or HTTPS URL.");
            return;
        }

        if (!int.TryParse(args[1], out int totalRequests) || totalRequests <= 0)
        {
            Console.WriteLine("Invalid totalRequests value. Must be a positive integer.");
            return;
        }

        if (!int.TryParse(args[2], out int concurrentRequests) || concurrentRequests <= 0)
        {
            Console.WriteLine("Invalid concurrentRequests value. Must be a positive integer.");
            return;
        }

        bool useKeepAlive = args.Length > 3 && bool.TryParse(args[3], out bool keepAlive) && keepAlive;

        Console.WriteLine($"Test Parameters:");
        Console.WriteLine($"- Base URL: {baseUrl}");
        Console.WriteLine($"- Total Requests: {totalRequests}");
        Console.WriteLine($"- Concurrent Requests: {concurrentRequests}");
        Console.WriteLine($"- HTTP Keep-Alive: {(useKeepAlive ? "Enabled" : "Disabled")}");
        Console.WriteLine();

        var httpClientHandler = new HttpClientHandler
        {
            UseProxy = false,
            MaxConnectionsPerServer = concurrentRequests
        };

        var httpClient = new HttpClient(httpClientHandler)
        {
            Timeout = TimeSpan.FromSeconds(30),
            BaseAddress = new Uri(baseUrl)
        };

        if (useKeepAlive)
        {
            httpClient.DefaultRequestHeaders.ConnectionClose = false;
            httpClient.DefaultRequestHeaders.Connection.Add("keep-alive");
        }
        else
        {
            httpClient.DefaultRequestHeaders.ConnectionClose = true;
        }

        httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(
         "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "+
         "(KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36");
        httpClient.DefaultRequestHeaders.Accept.ParseAdd("application/json");

        var stopwatch = Stopwatch.StartNew();
        var tasks = new List(concurrentRequests);
        var completedRequests = 0;
        var successfulRequests = 0;
        var failedRequests = 0;

        Console.WriteLine("Starting test...");

        var semaphore = new System.Threading.SemaphoreSlim(concurrentRequests, concurrentRequests);
        var jsonOptions = new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
            WriteIndented = false
        };

        for (int i = 0; i < totalRequests; i++)
        {
            await semaphore.WaitAsync();

            tasks.Add(Task.Run(async () =>
            {
                try
                {
                    var requestData = new
                    {
                        sender = "+0000000",
                        gsm = GenerateRandomPhoneNumber(),
                        text = GetRandomMessage(),
                        usrClient = "Pruebas",
                        pasClient = "Pruebas"
                    };

                    var json = JsonSerializer.Serialize(requestData, jsonOptions);
                    var content = new StringContent(json, Encoding.UTF8, "application/json");

                    var response = await httpClient.PostAsync(baseUrl, content);

                    System.Threading.Interlocked.Increment(ref completedRequests);

                    if (response.IsSuccessStatusCode)
                    {
                        System.Threading.Interlocked.Increment(ref successfulRequests);
                    }
                    else
                    {
                        System.Threading.Interlocked.Increment(ref failedRequests);
                        Console.WriteLine($"Request failed with status: {response.StatusCode}");
                    }
                }
                catch (Exception ex)
                {
                    System.Threading.Interlocked.Increment(ref completedRequests);
                    System.Threading.Interlocked.Increment(ref failedRequests);
                    Console.WriteLine($"Request failed: {ex.Message}");
                }
                finally
                {
                    semaphore.Release();
                }
            }));
        }

        await Task.WhenAll(tasks);
        stopwatch.Stop();

        Console.WriteLine("\nTest completed!");
        Console.WriteLine($"Total time: {stopwatch.Elapsed.TotalSeconds:F2} seconds");
        Console.WriteLine($"Completed requests: {completedRequests}");
        Console.WriteLine($"Successful requests: {successfulRequests}");
        Console.WriteLine($"Failed requests: {failedRequests}");
        Console.WriteLine($"Requests per second: {totalRequests / stopwatch.Elapsed.TotalSeconds:F2}");
    }

    static string GenerateRandomPhoneNumber()
    {
        return $"+{random.Next(100, 999)}{random.Next(1000000, 9999999)}";
    }

    static string GetRandomMessage()
    {
        return sampleMessages[random.Next(sampleMessages.Length)];
    }
}

Explication du code

1. Aperçu

Cette application console C# teste la charge d'un point de terminaison d'API SMS HTTP(S) en envoyant des requêtes JSON concurrentes, mesurant des métriques de performance comme :

  • Requêtes par seconde (RPS)
  • Taux de réussite/échec
  • Temps d'exécution total

2. Composants clés

A. Configuration et paramétrage

Génération de données aléatoires :

  • sampleMessages : Ensemble prédéfini d'échantillons de texte SMS pour des tests réalistes.
  • GenerateRandomPhoneNumber() : Crée des numéros de téléphone fictifs (par exemple, +1234567890).
  • GetRandomMessage() : Sélectionne un message aléatoire dans sampleMessages.

Arguments en ligne de commande :

Program <baseUrl> <totalRequests> <concurrentRequests> [useKeepAlive]
  • Valide les entrées (format URL, entiers positifs pour les comptes de requêtes).
  • Configure les paramètres du client HTTP (timeout, keep-alive, user-agent).

B. Configuration du client HTTP

Personnalisation de HttpClient :

  • MaxConnectionsPerServer : Limite les connexions parallèles au serveur.
  • ConnectionClose/keep-alive : Active/désactive les connexions persistantes HTTP.
  • Timeout : 30 secondes par requête.
  • En-têtes : Définit User-Agent et Accept: application/json.

C. Exécution du test de charge

Contrôle de la concurrence :

  • Utilise SemaphoreSlim pour limiter les requêtes concurrentes (par exemple, 50 à la fois).
  • Async/await (Task.Run) pour des opérations I/O non bloquantes.

Flux de requête :

  1. Sérialise une charge utile JSON avec des numéros de téléphone/messages aléatoires :
    {
        "sender": "+0000000",
        "gsm": "+1234567890",
        "text": "Hello, this is a test message.",
        "usrClient": "Pruebas",
        "pasClient": "Pruebas"
    }
  2. Envoie une requête POST au point de terminaison spécifié.
  3. Suivi des réussites/échecs avec Interlocked pour des compteurs thread-safe.

D. Métriques et rapports

  • Stopwatch : Mesure la durée totale du test.
  • Métriques de sortie :
    • Temps total écoulé.
    • Requêtes terminées/réussies/échouées.
    • Requêtes par seconde (RPS) : totalRequests / elapsedTime.

3. Points techniques marquants

  • Sécurité des threads :
    • Interlocked.Increment garantit des mises à jour atomiques des compteurs entre les threads.
    • SemaphoreSlim empêche la surcharge du serveur ou du client.
  • Gestion des erreurs :
    • Capture les exceptions (par exemple, timeouts, erreurs réseau) et enregistre les échecs.
    • Valide les codes de statut HTTP (IsSuccessStatusCode).
  • Optimisations de performance :
    • Réutilise HttpClient (meilleure pratique pour éviter l'épuisement des ports TCP).
    • Keep-alive configurable pour simuler des scénarios réels.

4. Exemple d'utilisation

Pour tester une API SMS à http://localhost:8080/sms avec 1 000 requêtes totales (50 concurrentes, keep-alive activé) :

Program http://localhost:8080/sms 1000 50 true

Sortie :

Test completed!
Total time: 12.34 seconds
Completed requests: 1000
Successful requests: 980
Failed requests: 20
Requests per second: 81.04

5. Pourquoi c'est important

  • Benchmarking : Identifie les goulots d'étranglement de l'API (par exemple, limites du serveur, latence réseau).
  • Tests de régression : Garantit que les performances ne se dégradent pas après les mises à jour.
  • Planification de capacité : Détermine la charge maximale que le service peut gérer.

6. Améliorations potentielles

  • Ajouter une logique de réessai pour les échecs transitoires.
  • Prise en charge de l'authentification (OAuth/clés API).
  • Export des résultats en CSV/JSON pour analyse.

Cet outil est idéal pour les développeurs et les équipes DevOps qui valident les performances des passerelles SMS avant le déploiement.

Conclusion

Le Test de vitesse HTTP pour les services SMS REST offre une solution robuste et facile à utiliser pour évaluer les performances et la fiabilité des points de terminaison d'API SMS. En simulant un trafic réel avec une concurrence configurable, une génération de messages aléatoires et des métriques de performance détaillées, cet outil aide les développeurs et les équipes QA à identifier les goulots d'étranglement, valider l'évolutivité et optimiser la réactivité de l'API. Que vous testiez un nouveau déploiement ou auditez une passerelle SMS existante, le code source C# inclus offre une flexibilité pour la personnalisation, tandis que l'exécutable pré-construit fournit des insights actionnables rapidement. Téléchargez l'outil dès aujourd'hui pour vous assurer que votre service SMS répond aux attentes de performance sous charge et offrir une expérience transparente aux utilisateurs finaux.

More information