- Creación de la
funcionalidad básica - Temporizar una
función - Creación del
Interfaz de Usuario - Ejecución
- Otros usos
adicionales
Cuando somos responsables de un Web empresarial,
debemos cuidar el nivel de servicio que
proporcionamos a nuestros clientes.
Normalmente se da la circunstancia de que cuando se cae nuestro
Web nos enteramos por una protesta de un cliente o un
usuario de negocio.
Hay veces que contratamos un Hosting y llegamos a un
acuerdo de nivel de servicio (SLA). Más habitualmente de
lo que me gustaría poder contar,
estos niveles de servicio no se respetan.
Debemos tener la capacidad de medir estos servicios por
nuestros propios medios. Hace
no mucho, os mostrábamos un tutorial sobre una herramienta
profesional que cubre de sobra esta funcionalidad, llamada
e-test
(Rendimiento
de aplicaciones Web).
A mi personalmente me gusta tener la capacidad de
verificar por mis propios medios (y desde mi casa con ADSL) si el
sistema funciona
bien o mal. Os recomiendo una herramienta llamada WebSupervisor,
que puede cubrir esta funcionalidad.
Si sabéis un poco de Java, es bastante
sencillo construir un pequeño programa para
este propósito… y con algún valor
añadido.
Vamos a empezar a hacerlo paso a paso. El objetivo es
construir el esqueleto de lo que podrá ser una herramienta
de monitorización y mostrar algunas notas para poder darle
continuidad.
Creación de la
funcionalidad básica
Creamos un nuevo proyecto en
NetBeans 3.6
Debemos ser consciente que el interfaz de usuario es lo
menos importante a la hora de diseñar un programa. Debemos
intentar acotar la funcionalidad y hacerla independiente de como
sea invocada.
public String EjecutarTarea() try { // inicializamos el destino si es if(destino == null) { destino = new URL("http://www.adictosaltrabajo.com/"); } // abrimos la conexión al servidor HttpURLConnection enlace = String respuesta = " – Codigo: " + //respuesta += return respuesta; } catch(Exception e) { return "Error " + e.getMessage() + } } // esta función recupera el texto String { try { String respuesta = ""; BufferedReader in = new BufferedReader (new String cadena = ""; while (cadena != null) { cadena = in.readLine(); if (cadena != null) { respuesta+=("n" + cadena); } } in.close(); return respuesta; } catch(Exception e) { return "Error " + e.getMessage() + } } |
Con la función anterior, tenemos la capacidad de
conectarnos a una URL y recuperar el código
de retorno, e incluso recuperar el contenido de la página
(//respuesta += recuperaContenido(enlace);)
El diseño
inicial no es muy bueno así que tenedlo en cuenta en
vuestros desarrollos (esto solo es un tutorial parcial)
:
- La URL esta fija y dentro del
código - No se gestionan ni propagan excepciones
Java dispone de una clase para
planificar la ejecución de una función de un modo
periódico, sin bajar al detalle de los
hilos (Threads) Timer
public void Arrancar() { java.util.Timer timer = new // creamos una clase inline timer.scheduleAtFixedRate(new TimerTask() public void run() { String resultado = EjecutarTarea(); AddTexto("" + new Date().toString() + resultado } }, retardo, periodo); } |
Creación del
Interfaz de Usuario
Usando las capacidades de NetBeans, vamos a crear un
interfaz sencillo
NetBeans es un entorno bastante intuitivo, aunque puede
costar un poco cogerle el tacto…
Como primera aproximación podemos obtener el
siguiente código
/* * Temporizador.java * * 1 Julio, 2004 * El objetivo de este programa es comprobar * * Es un ejemplo parcial … */ import java.util.*; import javax.swing.*; import java.net.*; import java.io.*; /** * * @author Roberto Canales */ public class Temporizador extends /** Creates new form Temporizador */ public Temporizador() { initComponents(); } /** This method is called from within the * initialize the form. * WARNING: Do NOT modify this code. The content * always regenerated by the Form */ private void initComponents() jScrollPane1 = new jTextArea1 = new jMenuBar1 = new jMenu1 = new javax.swing.JMenu(); jMenuItem2 = new jMenuItem1 = new setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); setTitle("Ejemplo de Temporizador"); addWindowListener(new public void exitForm(evt); } }); jTextArea1.setPreferredSize(new jScrollPane1.setViewportView(jTextArea1); getContentPane().add(jScrollPane1, jMenu1.setText("Menu"); jMenu1.addActionListener(new public void jMenu1ActionPerformed(evt); } }); jMenuItem2.setText("Arrancar"); jMenuItem2.addActionListener(new public void jMenuItem2ActionPerformed(evt); } }); jMenu1.add(jMenuItem2); jMenuItem1.setText("Salir"); jMenuItem1.setToolTipText("Menu jMenuItem1.addActionListener(new public void jMenuItem1ActionPerformed(evt); } }); jMenu1.add(jMenuItem1); jMenuBar1.add(jMenu1); setJMenuBar(jMenuBar1); pack(); } private void // TODO add your handling code here: Arrancar(); } private void dispose(); } private void // TODO add your handling code here: } /** Exit the Application */ private void System.exit(0); } /** * @param args the command line */ public static void main(String args[]) new Temporizador().show(); } // la función Arrancar simplemente crea // y ejecuta una función public void Arrancar() { jMenuItem2.setEnabled(false); java.util.Timer timer = new // creamos una clase inline timer.scheduleAtFixedRate(new TimerTask() public void run() { String resultado = EjecutarTarea(); AddTexto("" + new Date().toString() + resultado } }, retardo, periodo); } // la tarea a ejecutar es independiente del public String EjecutarTarea() try { // inicializamos el destino si es if(destino == null) { destino = new } // abrimos la conexión al HttpURLConnection enlace = String respuesta = " – Codigo: " + //respuesta += return respuesta; } catch(Exception e) { return "Error " + e.getMessage() + } } // esta función recupera el texto de la String { try { String respuesta = ""; BufferedReader in = new BufferedReader (new String cadena = ""; while (cadena != null) { cadena = in.readLine(); if (cadena != null) { respuesta+=("n" + cadena); } } in.close(); return respuesta; } catch(Exception e) { return "Error " + e.getMessage() + } } // añadimos texto al componente en public void AddTexto(java.lang.String jTextArea1.append(nodo + "n"); } // Variables declaration – do not private javax.swing.JMenu jMenu1; private javax.swing.JMenuBar private javax.swing.JMenuItem private javax.swing.JMenuItem private javax.swing.JScrollPane private javax.swing.JTextArea // End of variables declaration // inicializamos las variables no gestionadas private URL destino = null; private int retardo = 0; // no private int periodo = 2 * 60 * 1000; // ejecutar } |
Si ejecutamos el programa, obtenemos la siguiente
respuesta… Nuestro Hosting de www.adictosaltrabajo.com
es bastante estable.
Si somos un poco hábiles, podemos determinar las
dependencias de nuestro sistema Web a otros subsistemas y crear
un pequeño JSP/PHP/ASP que sea capaz
de probar si tenemos acceso a ellos:
- LDAP
- Base de Datos
- Host transaccional
- Servidor de Aplicaciones
- Sistema remoto de ficheros
- Middleware
- etc…
Podríamos también modificar nuestro
programa para que, al encontrar un error en la página
probada, recorriendo cada una de las rutinas que prueban cada
subsistema individualmente, analizase quién lo está
produciendo.
De este modo, cuando se produzca un problema en producción, desde vuestra casa
podréis prever errores (siempre y cuando lo que falle no
sea el propio servidor Web).
Con un sistema de estas características (que se
puede desarrollar en día) podéis tanto medir la
estabilidad del sistema como adelantaros a la llamada del usuario
de negocio cabreado porque la aplicación, en medio de una
demo, lleva media hora sin funcionar. Además, si cuando se
produce un error, mandáis un email a una pasarela SMS, te
enterarás sin tener que estar atento al correo.
Otra mejora puede consistir en monitorizar al mismo
tiempo un Web
muy estable (como google) y solo
considerar los datos como válidos cuando esté
último de una respuesta correcta …. ya que
sería una pena que lo que fallase fuera nuestra
configuración local ;-))
- Enlace ADSL
- Red Inalámbrica
- Configuración TCP/IP
- Desconexión de algún cable (que pasa
muy habitualmente)
Muchos sabréis que hay un montón de causas
por las que fallan las aplicaciones y normalmente es por falta de
procedimientos
organizativos a la hora de operar sistemas:
- Lagunas de memoria en
programas
(normalmente construidos por nosostros). - Cambios de contraseñas en un turno que se
aplican al rea-rrancar en otro. - Caducidad de certificados digitales.
- Modificaciones aparentemente inocuas del
LDAP. - Llenado de los discos o espacio de tablas de base de
datos. - Borrado accidental de ficheros/campos.
- Falta de pruebas
automáticas de regresión funcional - Y un largo etc …..
Ampliando este ejemplo un poquito, las posibilidades son
interesantes:
- Obtener una gráfica de
disponibilidad - Enviar un correo
electrónico cuando el código de retorno la
petición cambie - Analizar el contenido HTML para
verificar que no cambia… o es sustituido (nos han
jaqueado) - Asegurarnos que nuestras fuentes de
contenido (sindicado o alimentado por autores) funcionan
correctamente
Determinar la disponibilidad, rendimiento y capacidad de
los sistemas, requiere de práctica y
técnica.
Adquirir una herramienta puede ser muchas veces
más interesante que construirla aunque puede ser un
negocio rentable (o un buen proyecto de fin de carrera con salida
comercial) para la demanda
creciente de estos servicios …..
Roberto Canales Mora
www.adictosaltrabajo.com