AdriNavarro’s old posts

Just another WordPress.com weblog

Iconos web para aplicaciones

dejar un comentario »

A la hora de hacer un desarrollo -principalmente web- se necesitan iconos para representar las diferentes funciones, enlaces, etc. Además, facilitan el uso de la página.

Hasta ahora se lleva usando Silk la mayoría del tiempo, un gran set de iconos de famfamfam.

Sin embargo, existen multitud de sustitutos para estos iconos, por ejemplo.

- Vaga Icon Set: conjunto de iconos gratuitos bastante buenos, algo escasos (sólo 66) y en formato PNG con fondo transparente.

- ASP.NET Icons: set realizado para una comunidad de desarrolladores de ASP.NET, a parte de eso los iconos son bastante buenos -dentro de lo que cabe-, están en formato GIF con fondo transparente y el conjunto es bastante completo.

- Mini Icons: iconos de la misma persona que hizo los de Silk, esos iconos tan desgastados y tan vistos. Son pequeños, están en formato GIF y tienen fondo transparente. Pocos iconos aunque la variedad es buena. Además, los uso en Linkloo.

Lógicamente también existen otros sets de iconos pero que no he podido analizar aquí -y que nunca he usado-. También me habría interesado probar los iconos Tango, usados en algunos estilos de GNOME. Tango tiene montones de iconos, muy variados y en multitud de tamaños. Stay tunned.

Escrito por Adrián Navarro

Agosto 24, 2008 a 4:33 pm

Escrito en Uncategorized

Fulltext en PHP (sin recurrir a métodos MySQLianos)

dejar un comentario »

Llevo trabajando (mentira, casi no me tomó tiempo) en un motor de almacenamiento Fulltext compatible con MySQL. De esta forma, por medio de fragmentos de archivos crea un índice.

En este caso podríamos usarlo de dos formas: realizando una indexación completa de MySQL o indexando fragmentos de forma independiente. En el caso de usar indexaciones independientes, es necesario asegurarse de la consistencia del índice de forma externa, o directamente (al menos, de forma de periodica) regenerar el índice desde una fuente de datos.

Requiere un archivo de configuración, aquí “searcher.ini” en la base de directorios. Un ejemplo de configuración:

[mysql]
server = localhost
user = root
password =
database = wp2

[data]
query = SELECT id, post_title, post_content FROM wp_posts WHERE post_type=’post’
query_info = SELECT id, post_title, guid FROM wp_posts WHERE id = ‘%ID%’ AND post_type = ‘post’

[misc]
return_info = On
delete_index = On

Los valores de la sección “misc” pueden alternar entre “On” y “Off”. La variable “delete_index” determina si hay que borrar el índice ya existente y volverlo a crear o simplemente añadir los nuevos datos al índice (Lo que en muchos casos provocaría una duplicación).

Esta configuración está preparada para indexar una instalación de WordPress. Se usa “return_info” junto a “query_info” para devolver un array asociativo con los campos del elemento indexado en lugar de tan sólo el identificador “id” del elemento como elemento “key” y las coincidencias como valor propio del array.

Una pequeña nota: hay que llamar primero al regulador para trabajar con el programa (imperativo): require 'libs/common.php';

Para realizar una indexación…

1. Indexación: para realizar una indexación de 500 posts de tamaño medio (el tamaño de este blog excluyendo los posts chorra) de forma limpia se tardan 6750 Ms (6,7 segundos).

Para realizar una indexación de forma limpia hay que mantener la variable “delete_index” en “On” (como en el ejemplo)  y añadir las lineas siguientes a un archivo:

<?php
require ‘libs/common.php’;
new loader;
?>

Voilà! Esperar, y listo. (No olvidarse de la configuración).

2. Indexación de elementos independientes. Es posible añadir elementos a la base de datos directamente.

<?php
require ‘libs/common.php’;
new mysql;
$indexer = new indexer;
$nombre = “John Doe”;
$direccion = “c/ Falsa, 99″;
mysql_query(”INSERT INTO personas (’nombre’, ‘direccion’) VALUES (’$nombre’, ‘$direccion’)”);
$indexer->index($nombre, mysql_insert_id());
$indexer->index($direccion, mysql_insert_id());
?>

De todas formas, tampoco es el método más recomendado.

Luego, buscar. Hay que incluir también la librería común y hacer, según la variable “return_info”:

1. Con return_info en Off:

<?php
require ‘libs/common.php’;
$search = new searcher;
$search = $search->query($query);
foreach ($search as $id => $founds){
echo “<p>Identificador: $id / Coincidencias: $founds</p>”;
}
?>

Devuelve un array con “key” (identificador) y contenido (coincidencias) ordenados por relevancia.

2. Con return_info en On:

<?php
require ‘libs/common.php’;
$search = new searcher;
$search = $search->query($query);
foreach ($search as $datos){
extract($datos);
echo “<p><a href=\”$guid\”>$post_title ($id) / Founds: $founds</a></p>”;
}
?>

Lo que hace la opción return_info es ejecutar el query query_info de la configuración reemplazando %ID% por el campo id del resultado, devolviendo un array con todos los campos.

Y lo último, pero no por ello menos importante, la descarga:

PS: Lo más probable es que falle, asi que no hay por que alamarse.

Escrito por Adrián Navarro

Agosto 24, 2008 a 4:27 pm

Escrito en Uncategorized

Twitter y la tecnología

dejar un comentario »

Si algo se ha discutido pero no tiene una respuesta a ciencia cierta es si Twitter tiene la posibilidad de implantar algún modelo de financiación. En parte podría financiarse de cierta publicidad contextual. Y es que la cantidad de visitas que recibe (Twitts que aparecen en Google + Portada + Perfiles) no es pequeña. De esta forma se necesitaría al menos $1 USD por usuario. Por ejemplo…

  • Digamos que un servidor soporta 250 usuarios (o transacciones p/u). En esto contamos el AJAX abundante, las notificaciones SMS/Jabber.
  • Un servidor no suele costar más de $120 USD al mes (estándar, gama media). En clúster de red.

También habría que tener en cuenta que hay cosas que el dinero los usuarios no pueden contar, para todo lo demás como es por ejemplo las impresiones que reciben todo lo que es interno (navegación, registros, timeline, API — muy abundantes).

Por eso habría que conseguir al menos, y según escalabilidad, $1 dólar estadounidense al mes por usuario registrado para mantener el servicio. ¿Funcionará? ¿Hay que usar anuncios contextuales?

Yo y muy personalmente aplicaría un modelo de negocio como ha hecho Google con GMail, pero con bastante cuidado y es que ahora que Twitter ya (casi) no tiene oportunidades de ser adquirido por la grande de Internet, sólo les queda hacer funcionar su infraestructura bien (¿he oído bye bye Rails? He dicho).

Siempre podría funcionar y en cuanto más crezca más pequeños serán los costos por usuario. Yo lo llamo opimización, señores.

Ahora queda ver que piensan los grandes.

Escrito por Adrián Navarro

Agosto 24, 2008 a 4:22 pm

Escrito en Uncategorized

Xen y Debian Etch

dejar un comentario »

En pocos pasos, un ejemplo:

apt-get install linux-image-2.6-xen-vserver-686 xen-hypervisor-3.0.3-1-i386-pae xen-tools xen-linux-system-2.6.18-5-xen-vserver-686 linux-headers-2.6-xen-vserver-686 libc6-xen bridge-utils

Luego editamos /etc/modules y modificamos de tal forma que:
pico /etc/modules
Añadimos al final (o editamos la linea loop)

loop max_loop=64

Y… ¡reiniciamos!
reboot
Una vez de vuelta, editamos el fichero /etc/xen/xend-config.sxp
pico /etc/xen/xend-config.sxp
Y descomentamos la linea “(network-script network-bridge)”:
#
# To bridge network traffic, like this:
#
# dom0: fake eth0 -> vif0.0 -+
# |
# bridge -> real eth0 -> the network
# |
# domU: fake eth0 -> vifN.0 -+
#
# use
#
(network-script network-bridge)
#

Después reiniciamos xend:
/etc/init.d/xend restart
Con esto se debería reiniciar todo lo que es el sistema de red con todas las interfaces nuevas funcionando.
Luego editamos “/etc/xen-tools/xen-tools.conf”:
pico /etc/xen-tools/xen-tools.conf
Y descomentamos la linea tal que:
dir = /home/xen
Luego editamos en este mismo archivo las lineas y las modificamos tal que:
kernel = /boot/vmlinuz-2.6.18-5-xen-vserver-686
initrd = /boot/initrd.img-2.6.18-5-xen-vserver-686

Ejecutamos:
mkdir /home/xen
Y aquí empieza la diversion:
xen-create-image --debootstrap --hostname xen-etch --dhcp --dist=etch
Esto genera una maquina virtual con Debian. Mientras se ejecuta el proceso, tomate una cerveza…
Cuando se termine finalice la cerveza el proceso ejecutamos:
xm create /etc/xen/xen-etch.cfg
¡Nuestra maquina ya está funcionando! Comandos útiles:

  • xm list para ver las maquinas y detalles
  • xm console xen-etch inicia sesión en nuestra vm

Escrito por Adrián Navarro

Agosto 24, 2008 a 4:22 pm

Escrito en Uncategorized

Escalar una aplicación LAMP

dejar un comentario »

Lo más común en las pequeñas aplicaciones que recién se lanzan es el uso de una solución LAMP, que comporta un servidor Linux, Apache, MySQL y PHP.

En cuanto crecen hay que re-escalarlas o volver a programarlas usando una infraestructura diferente. Por eso quería dar un repaso a las soluciones para hacer crecer una gran aplicación.

Primeramente hay que escalar lo que es el servidor de ficheros web, puesto que es prácticamente impensable ir modificando un fichero por cada servidor. Como primer recurso se suele poner en marcha un filer que aloja todos los ficheros y realiza las correspondientes copias de seguridad (incluidos ficheros de MySQL, PHP y contenido estático).

Más tarde se puede implementar una solución independiente de sincronización automática entre un servidor master que aloje los ficheros y un resto de slaves que sincronize con el principal.

Luego hay que escalar el sistema de base de datos, esto suele más “doloroso”. Aunque en la mayoría de aplicaciones existen ciertos puntos a favor…

En primer lugar, la mayoría de conexiones a la base de datos suelen ser consultas (y no actualizaciones ni inserciones). Las inserciones son una mínima parte de las instrucciones enviadas a la base de datos.

Aquí podemos emplear el esquema básico de MySQL de un servidor master y de luegos unos “slaves” o servidores esclavos que tendrán una replica exacta del contenido del master, con la pega de que no podremos hacer inserciones ahí.

Si se trata de mostrar una portada, listar unos datos o ver el perfil de un usuario, en la gran mayoría de los casos no es necesario realizar inserciones con lo que se puede mantener un sólo o una serie pequeña de masters donde se insertarán los datos y luego todo un “equipo” de servidores “slave” donde se realizarán el resto de consultas, es decir, las de selección.

Para los filers se puede usar NFS, y en el caso de preferir un almacenamiento local sincronizado se puede usar entonces un proceso de Rsync programado (Cron, claro).

Volviendo a MySQL, basta con darse una vuelta por la documentación donde lo dejan bastante claro, yo lo llevo implementando para pequeños downtimes del servidor de bases de datos, que por ahora tiende a ser 0.

Ya contaré más, que seguro que algo me he dejado…

Escrito por Adrián Navarro

Agosto 24, 2008 a 4:21 pm

Escrito en Uncategorized

Servidor web en PHP (con extra de sockets!)

dejar un comentario »

Ahora mismo estoy desarrollando capas de abstracción web, para bases de datos e interfaces. En esto me he puesto a jugar con los sockets en PHP, y lo primero que se me ha ocurrido ha sido hacer un servidor web en PHP. Tiene muy pocas opciones, pero se pueden añadir más editando el switch de la función parse_response añadiendo un case. El contenido que se devolverá será el contenido en la variable $response. Por ahora soporta escuetamente los estándares HTTP/1.1, por lo que no envia header Content-Type si se trata de contenido ajeno a texto/HTML o headers de tamaño/longitud del archivo.

Aunque nunca está de más probar, he colgado el código de forma que cualquiera pueda descargarlo. Sólo una nota: ejecutarlo desde consola, en Debian/Ubuntu el paquete se llama php5-cli.

# php ejemplo.php

» Descargar

Escrito por Adrián Navarro

Agosto 24, 2008 a 4:19 pm

Escrito en Uncategorized

Ventajas penales de la ley del canon

dejar un comentario »

1. PREGUNTA

a) Luis se descarga una canción de Internet.
b) Luis decide que prefiere el disco original y va a El Corte Inglés a hurtarlo. Una vez allí, y para no dar dos viajes, opta por llevarse toda una discografía. La suma de lo hurtado no supera los 400 euros.

RESPUESTA: La descarga de la canción sería un delito con pena de 6 meses a dos años. El hurto de la discografía en El Corte Inglés ni siquiera sería un delito, sino una simple falta (art. 623.1 del Código Penal).

2. PREGUNTA:

a) Luis se descarga una canción de Internet.
b) Luis va a hurtar a El Corte Inglés y, como se la va la mano, se lleva cincuenta compactos, por valor global de 1.000 euros.

RESPUESTA: Seguiría siendo más grave la descarga de Internet. El hurto sería un delito, porque supera los 400 euros, pero sería de menor pena que la descarga (art. 234 del Código Penal).

3. PREGUNTA:

a) Sergio, en el pleno uso de sus facultades mentales, se descarga una canción de Malena Gracia.
b) Sergio, en un descuido de Malena Gracia, se lleva su coche y lo devuelve 40 horas después.

RESPUESTA: Sería mas grave la descarga. El hurto de uso de vehículo tiene menos pena, a tenor del articulo 244.1 del Código Penal.

4. PREGUNTA:

a) Ocho personas se intercambian copias de su música favorita.
b) Ocho personas participan en una riña tumultuosa utilizando medios o instrumentos que pueden poner en peligro sus vidas o su integridad física.

RESPUESTA: Es menos grave participar en una pelea que participar en el intercambio de compactos. Participar en una riña tumultuosa tiene una pena de tres meses a un año (art. 154 del Código Penal) y el intercambio tendría una pena de 6 meses a 2 años (art. 270 del Código Penal). Si algún día te ves obligado a elegir entre participar en un intercambio de copias de CDs o participar en una pelea masiva, escoge siempre la segunda opción, que es obviamente menos reprobable.

5. PREGUNTA:

a) Juan copia la última película de su director favorito de un DVD que le presta su secretaria Susana.
b) Juan, aprovechando su superioridad jerárquica en el trabajo, acosa sexualmente a su secretaria Susana.

RESPUESTA: El acoso sexual tendría menos pena según el articulo 184.2 del Código Penal.

6. PREGUNTA:

a) Pedro y Susana van a un colegio y distribuyen entre los alumnos de preescolar copias de películas educativas de dibujos animados protegidas por copyright y sin autorización de los autores.
b) Pedro y Susana van a un colegio y distribuyen entre los alumnos de preescolar películas pornográficas protagonizadas y creadas por la pareja.

RESPUESTA: La acción menos grave es la de distribuir material pornográfico a menores según el articulo 186 del Código Penal. La distribución de copias de material con copyright sería un delito al existir un lucro consistente en el ahorro conseguido por eludir el pago de los originales cuyas copias han sido objeto de distribución.

7. PREGUNTA:

a) Ramón, que es un bromista, le copia a su amigo el último disco de Andy y Lucas, diciéndole que es el “Kill’em All” de Metallica.
b) Ramón, que es un bromista, deja una jeringuilla infectada de SIDA en un parque público.

RESPUESTA: La segunda broma sería menos grave, a tenor del articulo 630 del Código Penal

8. PREGUNTA:

a) Juan fotocopia una página de un libro.
b) Juan le da un par de puñetazos a su amigo por recomendarle ir a ver la película “Los Ángeles de Charlie”.

RESPUESTA: La acción más grave desde un punto de vista penal sería la “a”, puesto que la reproducción, incluso parcial, seria un delito con pena de 6 meses a dos años de prisión y multa de 12 a 24 meses. Los puñetazos, si no precisaron una asistencia médica o quirúrgica, serían tan solo una falta en virtud de lo dispuesto en el artículo 617 en relación con el 147 del Código Penal.

– Transcripción de un video de David Bravo

Escrito por Adrián Navarro

Agosto 24, 2008 a 4:17 pm

Escrito en Uncategorized

Capa de abstracción MySQL con PHP5

dejar un comentario »

Quien haya tenido un sitio web con muchas visitas funcionando con un SGDB / frontend MySQL o MSSQL (este último no tiene remedio), se habrá dado cuenta de que con una avalancha de visitas o con un flujo grande y constante de accesos, se producen cuellos de botella en el acceso de lectura a la base de datos.

Se destacan varios puntos en común: los accesos de escritura son casi inexistentes, y los accesos de lecturas se repiten de forma múltiple ofreciendo siempre la misma respuesta durante cierto tiempo, a falta de una actualización.

Una opción que queda por ver es la de usar un servidor principal donde se realizarán las escrituras y luego una serie de servidores esclavos que vienen a ser replicas de la página web.

De ésta forma tenemos que ir escalando los servidores web y los servidores de bases de datos al mismo tiempo, puesto que si no se crearía un cuello de botella (más visitas = más conexiones a la base de datos = todo al garete).

Mas información y descarga después del salto.

Una solución es usar un sistema que haga de conector entre los servidores web y los de bases de datos. Esto ya existe, y se llama Database Access Layer, una implementación propia del New York Times (!).

Hagamos un ejemplo para entedernos mejor:

Ejemplo: EL PAÍS (diario)

  • 4 servidores web Apache2
  • 5 servidores MySQL

Las cifras son completamente arbitrarias, pero a mi parecer lo que mejor representa la solución LAMP que se suele implementar en estos casos.

Yo propondría lo siguiente:

Ejemplo 2 usando capas de abstracción

  • 2 servidores web Apache2
  • 1/2 servidor(es) sqlayer/dbslayer
  • 1 servidor MySQL

De por sí viene a ser mucho más eficaz y económico. Aquí es cuando entra en juego una capa de abstracción. Lo que hace es mediante una conexión persistente intercambiar consultas entre el servidor web y el frontend de base de datos. Una buena opción es crear una caché en memoria de las consultas selects, que expire en un minuto (por ejemplo).

Visto que DBSlayer no encaja con mis necesidades, aquí es donde yo entro en juego. He programado SQLayer, que presenta como carácteristicas:

  • pool de conexiones persistentes
  • cambio de servidor / base de datos en caliente
  • cache volátil de consultas (select, show, list)
  • escalable

Ni más ni menos, basta con ejecutarlo:

$ php sqlayer.php

Empezará a escuchar en el puerto 8636 esperando conexiones realizadas desde un script. En el caso de ser una consulta de tipo select, show o list (mira que me repito…) la ejecuta y devuelve un escueto esquema en XML de los datos, además de guardarlos en cache. Y para la comodidad de todos, también acepta consultas de tipo update, insert y otros aunque este no se haya diseñado el programa para esto.

Destaca por su flexibilidad pues cualquiera puede alterar el código para ajustarlo a sus servidores o distribuir las consultas.

Al grano: veamos un ejemplo de conector:

function pool_query ($query){
global $sock;
$sock = fsockopen(’localhost’, 8636);
fputs($sock, $query);
$read = fread($sock, 1048576);
return $read;
}

$sql_query = “SELECT * FROM wp_posts”;
pool_query($sql_query);

fclose($sock);

Devuelve un esquema XML de los campos devueltos por la DB. Con este ejemplo se puede adaptar a cualquier lenguaje de programación que por rudimentario que sea implemente sockets. Es decir, prácticamente cualquiera.

Y finalmente… La descarga. Esta empaquetado para usarse en Windows aunque incluye el script para Linux. Hay que instalar, en Debian/Ubuntu/Mint el paquete php5-cli de los repositorios.

Y una nota de pie en cuanto a rendimiento: junto a usar una capa de abstracción hay que tener en cuenta que NO hay que abusar del sistema. Hay que evitar acceder a cada uno de los recursos disponibles guardando copias locales de ellos y usando el mínimo de querys. Por ejemplo, más allá de 50 querys con este sistema puede empezar a ralentizar la página. Según los benchmarks que he hecho, se pueden hacer 50 querys en 293 MS mediante red mientras que de forma directa (pila TCP/IP) se pueden llegar a hacer en 178 MS, pero la ventaja del balancing y caching es un punto a tener en cuenta.

» Descargar por MegaUpload (07/12/07: Nuevo cliente / Soporte Winsock / Pequeños cambios)

Escrito por Adrián Navarro

Agosto 24, 2008 a 4:13 pm

Escrito en Uncategorized