Prueba de Velocidad HTTP para servicios REST de SMS

¿Necesitas medir el rendimiento de tu servicio de SMS basado en HTTP? La Prueba de Velocidad HTTP para Servicios REST de SMS es una herramienta poderosa diseñada para evaluar la velocidad y confiabilidad de tus endpoints de API JSON/REST. Esta utilidad descargable te permite simular solicitudes de SMS de alto volumen, rastrear tasas de éxito y calcular solicitudes por segundo, ayudándote a optimizar el rendimiento del servidor bajo carga. Ya sea que estés probando un entorno de desarrollo local o evaluando una pasarela de SMS en producción, esta herramienta proporciona métricas claras para solicitudes totales, conexiones concurrentes y eficiencia de HTTP Keep-Alive. Descarga la solución en C# lista para usar o integra el código fuente proporcionado en tu flujo de trabajo de pruebas para un análisis preciso del rendimiento de la API.

Descargar

HttpSpeedTest.zip

Ejemplo de uso

Figura 1 - Cómo usar la herramienta de prueba de velocidad

Código fuente

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 = {
        "Hola, este es un mensaje de prueba.",
        "Probando las capacidades del servidor HTTP.",
        "Midiendo solicitudes por segundo para API JSON.",
        "Contenido aleatorio para pruebas de carga.",
        "Otro mensaje de prueba con contenido diferente.",
        "Verificando capacidad del servidor bajo carga.",
        "¿Cuántas solicitudes puede manejar el servidor?",
        "Prueba de estrés para el endpoint de API de SMS.",
        "Este mensaje se genera automáticamente.",
        "Mensaje de prueba final en el conjunto de ejemplos."
    };

    static async Task Main(string[] args)
    {
        Console.WriteLine("Probador de Rendimiento de API JSON para Servidor HTTP");
        Console.WriteLine("----------------------------------------------------");

        if (args.Length < 3)
        {
            Console.WriteLine("Uso: Programa    [useKeepAlive]");
            Console.WriteLine("Ejemplo: Programa http://198.50.122.178:8080 1000 50 true");
            Console.WriteLine("Ejemplo: Programa https://api.example.com/sms 5000 100 false");
            Console.WriteLine("Ejemplo: Programa 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("URL base inválida. Debe ser una URL HTTP o HTTPS válida.");
            return;
        }

        if (!int.TryParse(args[1], out int totalRequests) || totalRequests <= 0)
        {
            Console.WriteLine("Valor inválido para totalRequests. Debe ser un entero positivo.");
            return;
        }

        if (!int.TryParse(args[2], out int concurrentRequests) || concurrentRequests <= 0)
        {
            Console.WriteLine("Valor inválido para concurrentRequests. Debe ser un entero positivo.");
            return;
        }

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

        Console.WriteLine($"Parámetros de prueba:");
        Console.WriteLine($"- URL base: {baseUrl}");
        Console.WriteLine($"- Solicitudes totales: {totalRequests}");
        Console.WriteLine($"- Solicitudes concurrentes: {concurrentRequests}");
        Console.WriteLine($"- HTTP Keep-Alive: {(useKeepAlive ? "Activado" : "Desactivado")}");
        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("Iniciando prueba...");

        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 = GenerarNumeroTelefonicoAleatorio(),
                        text = ObtenerMensajeAleatorio(),
                        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($"Solicitud fallida con estado: {response.StatusCode}");
                    }
                }
                catch (Exception ex)
                {
                    System.Threading.Interlocked.Increment(ref completedRequests);
                    System.Threading.Interlocked.Increment(ref failedRequests);
                    Console.WriteLine($"Solicitud fallida: {ex.Message}");
                }
                finally
                {
                    semaphore.Release();
                }
            }));
        }

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

        Console.WriteLine("\n¡Prueba completada!");
        Console.WriteLine($"Tiempo total: {stopwatch.Elapsed.TotalSeconds:F2} segundos");
        Console.WriteLine($"Solicitudes completadas: {completedRequests}");
        Console.WriteLine($"Solicitudes exitosas: {successfulRequests}");
        Console.WriteLine($"Solicitudes fallidas: {failedRequests}");
        Console.WriteLine($"Solicitudes por segundo: {totalRequests / stopwatch.Elapsed.TotalSeconds:F2}");
    }

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

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

Explicación del código

1. Resumen

Esta aplicación de consola en C# prueba de carga un endpoint de API de SMS HTTP(S) enviando solicitudes JSON concurrentes, midiendo métricas de rendimiento como:

  • Solicitudes por segundo (RPS)
  • Tasas de éxito/fracaso
  • Tiempo total de ejecución

2. Componentes Clave

A. Configuración

Generación de Datos Aleatorios:

  • sampleMessages: Conjunto predefinido de mensajes SMS para pruebas realistas.
  • GenerarNumeroTelefonicoAleatorio(): Crea números de teléfono falsos (ej. +1234567890).
  • ObtenerMensajeAleatorio(): Selecciona un mensaje aleatorio de sampleMessages.

Argumentos de Línea de Comandos:

Programa <baseUrl> <totalRequests> <concurrentRequests> [useKeepAlive]
  • Valida entradas (formato de URL, enteros positivos para conteos de solicitudes).
  • Configura ajustes del cliente HTTP (tiempo de espera, keep-alive, user-agent).

B. Configuración del Cliente HTTP

Personalización de HttpClient:

  • MaxConnectionsPerServer: Limita conexiones paralelas al servidor.
  • ConnectionClose/keep-alive: Alterna conexiones persistentes HTTP.
  • Tiempo de espera: 30 segundos por solicitud.
  • Encabezados: Establece User-Agent y Accept: application/json.

C. Ejecución de Prueba de Carga

Control de Concurrencia:

  • Usa SemaphoreSlim para limitar solicitudes concurrentes (ej. 50 a la vez).
  • Async/await (Task.Run) para operaciones de E/S no bloqueantes.

Flujo de Solicitud:

  1. Serializa un payload JSON con números/mensajes aleatorios:
    {
        "sender": "+0000000",
        "gsm": "+1234567890",
        "text": "Hola, este es un mensaje de prueba.",
        "usrClient": "Pruebas",
        "pasClient": "Pruebas"
    }
  2. Envía una solicitud POST al endpoint especificado.
  3. Rastrea éxitos/fracasos usando Interlocked para contadores seguros en hilos.

D. Métricas y Reporte

  • Cronómetro: Mide la duración total de la prueba.
  • Métricas de Salida:
    • Tiempo total transcurrido.
    • Solicitudes completadas/exitosas/fallidas.
    • Solicitudes por segundo (RPS): totalRequests / elapsedTime.

3. Aspectos Técnicos Destacados

  • Seguridad en Hilos:
    • Interlocked.Increment asegura actualizaciones atómicas de contadores entre hilos.
    • SemaphoreSlim evita sobrecargar el servidor o cliente.
  • Manejo de Errores:
    • Captura excepciones (ej. tiempos de espera, errores de red) y registra fallos.
    • Valida códigos de estado HTTP (IsSuccessStatusCode).
  • Optimizaciones de Rendimiento:
    • Reutiliza HttpClient (mejor práctica para evitar agotamiento de puertos TCP).
    • Keep-alive configurable para simular escenarios reales.

4. Caso de Uso Ejemplo

Para probar una API de SMS en http://localhost:8080/sms con 1,000 solicitudes totales (50 concurrentes, keep-alive activado):

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

Salida:

¡Prueba completada!
Tiempo total: 12.34 segundos
Solicitudes completadas: 1000
Solicitudes exitosas: 980
Solicitudes fallidas: 20
Solicitudes por segundo: 81.04

5. Por Qué Esto Importa

  • Evaluación Comparativa: Identifica cuellos de botella en la API (ej. límites del servidor, latencia de red).
  • Pruebas de Regresión: Asegura que el rendimiento no se degrade después de actualizaciones.
  • Planificación de Capacidad: Determina la carga máxima que el servicio puede manejar.

6. Mejoras Potenciales

  • Añadir lógica de reintento para fallos transitorios.
  • Soporte para autenticación (OAuth/claves de API).
  • Exportar resultados a CSV/JSON para análisis.

Esta herramienta es ideal para desarrolladores y equipos DevOps que validan el rendimiento de pasarelas SMS antes de su implementación.

Conclusión

La Prueba de Velocidad HTTP para Servicios REST de SMS proporciona una solución robusta y fácil de usar para evaluar el rendimiento y confiabilidad de endpoints de API de SMS. Al simular tráfico del mundo real con concurrencia configurable, generación de mensajes aleatorios y métricas detalladas de rendimiento, esta herramienta ayuda a desarrolladores y equipos de QA a identificar cuellos de botella, validar escalabilidad y optimizar la capacidad de respuesta de la API. Ya sea que estés probando una nueva implementación o auditando una pasarela de SMS existente, el código fuente en C# incluido ofrece flexibilidad para personalización, mientras que el ejecutable precompilado proporciona información rápida y accionable. Descarga la herramienta hoy para asegurar que tu servicio de SMS cumple con las expectativas de rendimiento bajo carga—y ofrece una experiencia perfecta a los usuarios finales.

More information