Acerca de Jose Antonio

Yo soy el que manda aqui... ¿Que pasa?

Varias formas de hacer pruebas de stress a una url

Una vez que hemos programado algo, una web, un api o cualquier otra cosa que van a utilizar muchas personas a la vez nos entra la necesidad inmediata de, después de las pruebas unitarias, poder pasarle unas pruebas de stress para ver cuanta gente puede entrar a la vez antes de que el sistema reviente o, en el peor de los casos, ver si hay algún problema de programación que nos impide tener peticiones concurrentes con seguridad.

Servidor bajo asedio... Imagen generada por AI

Solo os voy a presentar los más sencillos, aunque luego hay herramientas mucho más completas que ya se deben usar en el momento de QA para comprobar si los requisitos del sistema se cumplen (máximo número de peticiones por minuto / curva de carga / evolución del tiempo de respuesta, etc.).. Pero vamos, que ahora mismo solo queremos ver si se puede llamar a nuestro api o web concurrentemente…

siege

Este es el comando más sencillo que he encontrado, pero a la vez es muy eficiente en lo que se puede hacer con él.

siege -c10 -r1 https://blaba.com

Tras un tiempo de ejecución (depende de los parámetros c: concurrencia y r: repeticiones) se recibirá una salida como esta:

{ "transactions": 140,
"availability": 100.00,
"elapsed_time": 3.12,
"data_transferred": 3.48,
"response_time": 0.22,
"transaction_rate": 44.87,
"throughput": 1.11,
"concurrency": 9.68,
"successful_transactions": 140,
"failed_transactions": 0,
"longest_transaction": 0.33,
"shortest_transaction": 0.04
}

Ahí ya podemos ver cual es el ratio de fallo para esa concurrencia y los tiempos máximos y mínimos para cada transacción. Guay…

Ahora bien, el problema viene de que solo podemos hacer peticiones GET (podemos poner las cabeceras que queramos, pero no hay manera de hacer una petición POST, por ejemplo). Así pues si tenemos que probar un API que tiene algo más que peticiones GET tendremos que usar otra cosa…

Sigue habiendo una infinidad de herramientas muy buenas para hacer estas cosas, como Jmeter y otras, pero para unas pruebas de carga básicas vamos a continuar con el camino «barato»

curl + bash

Si estamos en linux, tenemos suerte (el siege también es de linux, pero seguro que hay un port para tu sistema operativo). Apuntad esto:

Primero hay que instalar paralell que no está en la distribución por defecto:

sudo apt install parallel

Luego podremos escribir algo como esto:

seq 100 | parallel --max-args 0 --jobs 10 "./curl_to.sh"

Y en curl_to.sh poned el comando curl con el que vais a probar, por ejemplo este:

curl --location 'https://blabla.com/api/v1/micomando' --header 'Content-Type: application/json' --header 'Accept: application/json' --header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIU...CvuTuF30k8XEFg_XL-gJyK-8rT4htC7HTHxbtDSGN8' --data '{ "userid": "418043893","message": "Hola payo…..", "uuid": "kk"}'

Este comando de antes lo que hace, básicamente, es lanzar una petición POST con un cuerpo JSON y una cabecera de autenticación (con un token JWT por ejemplo). Este código lo podemos sacar de postman, por ejemplo diciendole que queremos generar código para curl.

Si lanzamos el comando seq, lo que hace es generar una secuencia de números (en este caso de 1 a 100, y paralell lo que hace es lanzarnos de manera paralela (10 cada vez) el comando que hemos especificado… Con esto conseguiremos lanzar 100 veces 10 peticiones paralelas.

Obviamente no es perfecto, pero habremos podido simular una carga paralela sin tener que instalar nada en nuestro ordenador. Si eso lo combinamos con el comando time (os lo dejo como ejercicio) también podríamos sacar estadísticas de las ejecuciones.

En próximas entradas veremos como usar algunas herramientas muy potentes para pruebas de carga, pero por ahora, ya podéis empezar a estresar a vuestro servidor.

La pinza

Uno de los grandes logros en la estrategia militar de los alemanes en la segunda guerra mundial fue utilizar el movimiento de pinza con embolsamiento (no había forma de salir de la misma) para acabar de manera rápida con un enemigo que se creía muy bien guarnecido en su territorio.

Este es un movimiento que ya se describe desde tiempos inmemoriales, Tsun Zu ya lo recomienda, pero sin embolsamiento, dejando una salida al enemigo para que no se sienta acorralado y se vea forzado a una lucha más feroz. Y, diréis vosotros, ¿porque nos habla este ahora de un movimiento militar? Bien, porque este movimiento se utiliza en muchos otros campos, uno de ellos, y de actualidad tras las últimas elecciones municipales, es el campo político.

Yo ya os he dicho que soy más progresista que otra cosa, no me importa decirlo aunque no creo en eso de que haya que odiar al que piensa distinto y odio la polarización en la política y en cualquier otro aspecto de la vida. Estamos asistiendo, no obstante, a un espectáculo vergonzoso de prostitución de la democracia en la que los ciudadanos, por el momento, no podemos más que escandalizarnos y desanimarnos. Perdonadme por poner un post de corte político en medio de mi blog, pero es que es mi blog y es el sitio donde dejo lo que me pasa por la cabeza (sea técnico o no).

Estas elecciones municipales han servido para varias cosas, que se han visto desde la campaña y desde antes, a saber:

  • Los medios de comunicación ya no tienen ningún pudor en mostrar a quién apoyan y a quien quieren silenciar. Eso es bastante normal cuando hablamos de una tertulia política, pero es vergonzoso cuando convierten los programas de entretenimiento en adoctrinamiento. Solo hay que ver el programa de Pablo Motos y sus invitados a quién menos gracioso o el hecho de que el horario de la telebasura del corazón la hayan sustituido por telebasura política con Ana Rosa, por poner dos ejemplos del lavado sistemático de cerebros débiles.
  • No existen medios de izquierda ni que se le parezcan. La falsa sensación de que la sexta, por ejemplo, era una televisión «friendly» con la izquierda se ha tornado, como no podía ser de otra manera, en la constatación de que tienen patrones a los que contentar y sus directivos no tienen ningún escrúpulo en participar de las cloacas o de invitar a «hostiles» y silenciar a los «amigos» de la izquierda más irreductible.
  • La derecha no tiene escrúpulos y no hace prisioneros. Lo hemos visto en la defenestración de casado, en el uso de «medios» mentirosos y difunde bulos (okdiario, EDA, etc.) siendo pagados sin rubor con dinero público y compitiendo en quien decía la mentira más gorda (ya sabes, si alguien dice que es mentira es que es un zurdo intentando coartar mi libertad de expresión) y siempre es un buen momento para reirse de los progres.
  • No hay aliados entre los que piensan igual que tu. Sumar, que podría parecer una buena idea a priori, se ha esforzado muy mucho en desligarse de Podemos desde el primer momento. Yolanda Díaz, que está en el gobierno gracias a Podemos, que ha disfrutado de libertad y apoyo constante para su labor de gobierno ha decidido que no quiere cargar con el peso de un partido ya formado, que prefiere alimentarse de estructuras más tradicionales, desmembrarlas y someterlas a un único objetivo: volver a sentarse en un gobierno.
  • Nadie se lee los programas… Votan lo mismo al defensor de los toros y azote de los menas que a la que va de bar en bar sirviendo cervezas y sin encontrarse con el ex-novio. ¿Programa? ¿Para qué? Ya se que me roban, pero yo nunca permitiría que me robase un comunista (Álvaro Ojeda dixit)

Esto ha generado una terrible pinza donde, si te unes a Sumar renuncias a cualquier posibilidad de apoyar políticas más sociales (nada que no haría el PSOE) y, además, sabes que te van a mirar mal como el radical que ya no sabe donde meterse. Si no te unes eres un traidor a la izquierda y solo piensas en tu orgullo y les vas a hacer perder votos. Por otro lado tienes a la derecha lobotomizadora que te está diciendo que no merece seguir votando, total, ellos ya han ganado y «la resistencia es futil», mejor dejar de resistirse y, en todo caso, votar al PSOE (que es lo que Pedro Sanchez ha dado por descontado que hará la mayor parte de la gente como voto útil visto lo que provoca la fragmentación del voto).

Lo que más me duele es que gente aparentemente culta e inteligente como Pedro Vallin van por ahí insultado, ninguneando y mofándose de los que han construido el modo de política que ahora pretenden aprovechar para hacerse un Carmena. Lo que ellos no saben es que, al igual que matar la sanidad pública hará que la privada lo pase muy mal (no está preparada para tener que hacerse caso de las cosas costosas), matar a Podemos hará que la izquierda vuelva a lo de siempre, pero de mal humor. Sumar será la nueva Izquierda Unida (¿Similitudes en la intención del nombre?) y PSOE volverá a aglutinar el voto no de derechas.

Internacionalizando javascript en symfony

En este nuevo desafío que he asumido recientemente me encuentro con tener que mantener y mejorar aplicaciones web que están desarrolladas sobre symfony 5. Este es un framework PHP (si, php, no me matéis) que tiene sus cosas buenas y sus cosas malas. Una de las buenas es que permite internacionalizar las aplicaciones sin demasiados problemas… Al menos la parte de html.

Symfony utiliza un sistema de plantillas twig que es donde se pueden realizar las traducciones poniendo {%trans%}cadena{%endtrans%} y luego simplemente tenemos que mantener los archivos de traducción de cada lenguaje y ya toda la magia sucede internamente y sin problemas.

Imagen generada por AI cuando le pedí que me hiciese una imagen para un post de programación

Pero, ¿Qué pasa con las cadenas que generamos en javascript? Los archivos .js se sirven estáticamente sin que pasen por el proceso de sustitución que se hace en los twig, no nos vale poner {%trans%}cadena{%endtrans%} en el js porque ese archivo nunca va a ser tratado por symfony ni por php ya puestos.

La solución que he terminado por implementar se basa en generar un archivo .js con las traducciones en base a una plantilla twig y cargarla cada vez que necesite traducir algo en un js. Para ello solo tenemos que dar estos pasos:

  1. Crear la ruta en routes.yml (o usar un decorador) para /jstrans.js o similar
  2. Crear un controlador para servir ese archivo, por ejemplo JavascriptController.php
  3. Crear un twig para el javascript, por ejemplo jstrans.js.twig
  4. Meter en el twig todas las cadenas y sus traducciones correspondientes
  5. Hacer que jstrans.js se cargue en todas las páginas que necesiten traducciones
  6. usar la función que traduce en los js que lo necesiten.

Aquí os dejo un ejemplo de cada uno de los archivos:

JavascriptController.php

class JavascriptController extends AbstractController
{
    public function __construct()
    {
        $this->config = new Config();
    }

    public function index(): Response
    {
        $response =  $this->render('javascript/jstrans.js.twig', [
            'controller_name' => 'JavascriptController',
        ])->setSharedMaxAge(3600)->setPublic();
        $response->headers->set('Content-Type','text/javascript');
        return $response;
    }
}

jstrans.js.twig

if (typeof jstrans == 'undefined') {

    var jstrans = {
        traducciones: {
            'Seleccionar': '{%trans%}Seleccionar{%endtrans%}',
            'Registros': '{%trans%}Registros{%endtrans%}',
            'No se han encontrado resultados': '{%trans%}No se han encontrado resultados{%endtrans%}',
        },
        // Función que traduce un texto
        translate: function (text) {
            if (jstrans.traducciones[text] != undefined) {
                return jstrans.traducciones[text];
            } else {
                return text;
            }
        }
    };
} else {
    console.log ('jstrans ya está definida');
}

Luego ya se meten las cadenas en, messages.en.yaml,, por ejemplo

Seleccionar: Select
Registros: Registers
No se han encontrado resultados: No results found

Y luego solo hay que usarlo en los archivos js de esta manera:

jstrans.translate("Seleccionar")

Y eso te dará la cadena traducida al idioma en el que se esté navegando.

¿Conoces algún método mejor para conseguir traducciones en los js de un proyecto symfony? déjame un comentario si es así…

Buscar talento en linkedin

Durante mi periodo de CEO en biblioeteca he tenido la necesidad de contratar personas que pudiesen ayudarnos con los proyectos que nuestros clientes nos proponían. En este mercado la rotación es muy alta y el talento (aunque cueste admitirlo) bastante escaso. Tampoco es que nosotros tengamos necesidades extraordinarias, y la mayor parte de nuestras contrataciones venían recomendadas de antes (eso siempre es lo mejor), pero cuando hay que cubrir puestos rápidamente es cuando nos encontramos en problemas.

Uno de los sitios a los que he acudido a ofrecer puestos de trabajo ha sido a LinkedIn, en concreto creo que conseguí un total de 4 personas (en un periodo largo), pero cada vez ha estado funcionando peor, os comento el ejemplo de la última campaña donde buscaba alguien con Java y Linux (y tampoco pedía años de experiencia). El anuncio en concreto está en este enlace:

https://www.linkedin.com/jobs/view/3517177902/

Para esta oferta recibí estos resultados:

Recibí un total de 7 cvs, de los que ninguno era adecuado del todo.

Pero hagamos unas pequeñas cuentas… 100 Euros de gasto, 96 visualizaciones, precio por visualización 1,04 Euros… ¡Por cada visualización! Esto, por si no os lo parece es carísimo. Calculemos que por cada 100 visualizaciones obtenemos 5cvs (1 de cada 20, esto es ser muy optimista), si de cada 10cvs obtenemos 1 al que entrevistar y que, de media, hay que entrevistar a 5 candidatos por puesto… Nos queda que necesitaríamos un mínimo de 5*10*20 = 1000 visualizaciones.

LinkedIn ¿me quieres decir que para contratar un programador (que tampoco busco un experto) tengo que gastarme 1.040 Euros?

A mi esto me ha parecido un error, y como tal se lo he preguntado a la amable gente de linkedin en twitter…

Qué majos! .. Vamos a ello…

Umm, no es ninguna de esas opciones, vamos a abrir incidencia

Vamos a ver que mi pregunta NO es sobre LinkedIn ADS, que de eso no tengo cuenta.. A ver si hay otra forma…

Pues no, no ayuda la verdad…

Y esto tampoco… ¿Cómo que las visitas disminuyen con el tiempo? Oye, que os habéis comido 100 pavos en dos días y solo me habéis dado 96 visualizaciones… Algo pasa

Y chin-pum ahí se acaba la interacción con la ayuda de linkedin… plasplasplas

Así que, si me preguntáis a mi, LinkedIn ha dejado de ser un sitio asequible para poner anuncios de trabajo…

Ser empresario también es tener que tratar con malnacidos

Como se diría en twitter, acompañemé a conocer esta triste historia…

Luis Carballo Rua con nuestro portatil

Llevo 19 años siendo empresario y he contratado unas cuantas decenas de personas. Antes era más sencillo dar con alguien competente, pero ahora con tanto bootcam y con tanto FP con esteroides es más complicado saber si un trabajador sabe lo que dice que sabe o no. Antes tener un título significaba un mínimo, ahora tienes que bucear para encontrar si la persona en cuestión sabe lo que es el http o le han dicho que eso es magia de Angular. En fin, que se te pueden colar inútiles sin comerlo ni beberlo.

Uno de esos casos me pasó recientemente, una persona respondió a un anuncio de trabajo que pusimos en LinkedIn. La plaza que pedíamos de desarrollador front la terminamos ocupando con otra persona, pero me pareció interesante el cv que nos pasó, lleno de dibujos hechos por él mismo.

El caso es que en la siguiente plaza para full stack se volvió a presentar, decidimos entrevistarle y, quitando que hablaba muy deprisa, nos dijo que si a todo lo que le preguntamos, no parecía perdido en ningún área de los que preguntamos y su CV era molón, así que le hicimos una oferta a los dos días… Oferta que rechazó porque dijo que ya estaba trabajando en otra empresa que le llamó después de nosotros… En fin, cosas que pasan, a seguir entrevistando.

Esta vez el proceso se hizo un poco más largo y a eso de las dos semanas me contacta de nuevo diciendo que las condiciones de la nueva empresa no le interesan y que si le mantengo la oferta. Yo, que soy un hombre de palabra, le digo que le mantengo exactamente la misma oferta que le hice… Y, dicho y hecho, le preparamos el contrato y quedamos ya para que empiece a trabajar en remoto, básicamente, aunque esperábamos que al menos el primer día se quedase en la oficina para que le explicásemos las cosas.

Primer día: quedamos a las 9:30 porque yo tenía reuniones antes… Espero, se hacen las 10, las 11.., le mando un whatsapp, no me contesta, a las 12 ya le llamo por teléfono y me dice que está en Alcorcón, pero llevando su madre al médico, que luego se pasa por aquí (no me parece lo mejor para el primer día y, además, sin avisar), en fin, que a las 13 se pasa por la oficina, firma el contrato, le enseño a entrar en el portatil y en su cuenta de correo; y… Se va. ¡¡!! Que si, que es un trabajo remoto, pero leche, no solo llegas 4 horas tarde sino que ni siquiera te quedas a que te expliquemos nuestra forma de trabajar…

La primera semana de trabajo se perdió intentando que arrancase solo en ubuntu el portatil y que no usase windows (windows=kk), le compramos hasta una docking station para que pudiese enchufar sus dos monitores (y se lo tuvimos que mandar a casa, que él pasar por l oficina ya le daba pereza), la segunda semana ya empieza a hacer algo productivo pero sin hacer puto caso de lo que le decimos. Nos llena el código de librerías que luego tenemos que borrar y nos quita más tiempo del que ahorramos. En la cuarta semana le ponemos a hacer algo para despliegue inmediato (tampoco era muy complicado, pero dediqué yo más horas que él) y nos dice que se va a vivir a la costa que, total, es remoto y no nos vamos a enterar… Y el pavo se va de mudanza el mismo día que pasamos a producción grrrrr. Obviamente la cosa peta y tengo que arreglarlo yo solo.

Lo primero que hace nada más llegar a su destino es pedirme un anticipo (estábamos a día 7 de mes), cosa que me extraña pero que procedemos a hacer sin ningún problema. A partir de ese momento su rendimiento fue cero. La lista de problemas (en orden cronológico):

  • Que el proveedor de internet que tenía no le permitía usar el puerto del ssh y no podía subir nada al servidor
  • Que los que han venido a repararlo no tenían idea y ha terminado tirando el router por la ventana
  • Que me he quedado dormido (excusa para no aparecer por el daily) y el movil estaba descargado
  • Que se me acaban los datos del móvil
  • Que me van a poner la fibra (ese día desapareció tras el daily y apareció después de haber terminado la jornada diciendo que se había dejado el movil en casa mientras le instalaban la fibra)
  • Que me he cargado el móvil (caída fortuita al suelo, dice)
  • Que sigue sin fibra y tiene que hacer el daily desde un bar
  • Que el del bar ha abierto más tarde hoy y no he podido hacer el daily

Y mientras el trabajo que tenía asignado ahí pudriéndose y teniendo que hacerlo entre sus compañeros y yo…

Llegados a este punto decido que es suficiente y que, obviamente, no ha superado el periodo de prueba. Se lo comunico y le indico que empaquete el portatil, la mochila y la docking station y que alguien pasará a recogerla.

Y ahora salta la sorpresa en las gaunas… Esta persona decide que va a quedarse con el material de la empresa, material que vale más que lo que él ha generado para la empresa. Esto no solo está tipificado como una apropiación indebida sino que dado el valor de lo apropiado puede ponerle en un grave aprieto. Mi empresa, como no puede ser de otra manera, le ha pagado finiquito y liquidación (muchas tentaciones de quedarnos con ese dinero en compensación, pero mi abogado me recomendó pagarlo de todas formas) y este desalmado malnacido no ha dado señales de vida.

Ya es duro mantener y gestionar una empresa como para tener que lidiar con gentuza de esta calaña. No solo ha perjudicado a sus compañeros sino que te deja una mala leche que terminas pagando con el primero que pasa… En fin, solo espero que el karma haga su trabajo. Si alguien quiere contratar a un full-stack developer, que me pregunte a quien no contratar nunca.