
Fuente: The Extremme Presentation
Por lo general, nuestras aplicaciones web necesitan ser escalables especialmente en las consultas a las bases de datos. Esto es extremadamente necesario cuando no se dispone de un cluster y el tráfico puede comprometer la performance de un sólo servidor de base de datos.
En este tutorial voy a detallar los pasos necesarios para hacer un sencillo load balancer de mysql a alto nivel utilizando PHP. Para lograr esto, es requerido que los dos o más servidores de bases de datos tengan exactamente la misma información. En MySQL, por ejemplo, pueden lograr esto utilizando la replicación que ofrece el motor de base de datos.
Para comenzar, imaginemos el posible escenario mÃnimo para setear nuestro balanceador de carga.
Un caso particularmente popular es tener, en el mismo equipo, el servidor web y el servidor de base de datos. Es ahà cuando nuestra infraestructura puede quedar chica y necesitamos otro servidor para balancear la carga. Para entonces podemos agregar otro servidor que replique la información del primero para tener asà una réplica exacta de nuestros datos.
El concepto es muy simple. Para que el balanceador de carga funcione como tal, es necesario conocer el load average de cada uno de los servidores. Luego, basándonos es ese dato, podemos decidir dinámicamente que servidor usar para establecer la conexión.
Entre las numerosas formas de lograr hacer un motor de búsqueda en MySQL, la mejor es el fulltext search. Pocos sitios lo usan y sigue siendo la solución más rápida y más completa de todas las opciones.
La única limitación del fulltext search es el lÃmite de letras de las palabras a buscar ya que en la configuración del MySQL este lÃmite viene por defecto en 4 letras, es decir, no va a tomar palabras menores a 4 letras para realizar la búsqueda. Pero esto puede ser cambiado y no es una excusa de peso para desplazar a las grandes ventajas del fulltext search: velocidad y rendimiento.
En este post intentaré explicar de forma simple como ordenar por relevancia una búsqueda en varios campos seleccionando los campos más importantes.
Ya hemos hablado acerca del poder de las expresiones regulares en la programación. Sin embargo, extraer información de una cadena con expresiones regulares puede ser un tanto complicado a la hora de navegar por los Ãndices del array generado.
Para solucionar este problema, varios lenguajes implementaron los tags en las expresiones regulares. Estos tags permiten al desarrollador organizar el array de salida en una cadena de coincidencias.
Para ejemplificar este mini tutorial, utilizaré la función preg_match_all() de php, ya que es la que mayormente uso en este tipo de casos. Los que usan python por ejemplo, podrán usar la misma expresión en la función re.findall().
Imaginemos por un momento que queremos obtener diferente información de una url y queremos extraer por un lado el protocolo, por otro lado ver si tiene las www, por otro el dominio propiamente dicho y por el otro lado el request.
Si usáramos una expresión regular común, con preg_match_all() que busca todas las coincidencias posibles y las guarda en un array indexado, se nos harÃa difÃcil calcular antes de ver el array en que posición está la información que necesitamos.
Por ejemplo:
preg_match_all ('/(.+://)(www.)?([^/]+)(.*)/', 'http://www.google.com.ar/search?q=elezeta', $array);
Nos dará como resultado un engorroso $array que estará compuesto por varios Ãndices en donde cada uno de esos Ãndices son las coincidencias que la función detectó y para utilizar esta información, tenemos primero que ver como es el array y después llamar al Ãndice que nos interesa.
En cambio, usando los tags, podemos decirle que además de crear el array indexado, nos agregue Ãndices asociativos con los tags de nuestra información.
El mismo ejemplo con tags:
preg_match_all ('/(?P<protocolo>.+://)(?P<w>www.)?(?P<dominio>[^/]+)(?P<query>.*)/', 'http://www.google.com.ar/search?q=elezeta', $array);
De esta forma sabemos que:
$array['protocolo']: va a tener el protocolo "http://".
$array['w']: va a tener si usa www "www", si no usa, va a ser nulo.
$array['dominio']: va a tener el dominio: "google.com.ar".
$array['query']: va a tener todo el resto.
Como verán es muy simple el uso de tags en las expresiones regulares en lenguajes que lo soportan. Tan sólo agreguen ?P<tagname> delante del grupo de coinsidencia y la función se encargará del resto.
Esto surge de una charla que tuvimos con MatÃas acerca de las virtudes de las expresiones regulares en PHP y en Python.
A partir del mysql 5, es posible replicar servidores de bases de datos MySql, algo que no mucha gente usa por el hecho que no siempre se dispone del acceso a la administración de más de un servidor.
Esta serie de posts tiene como objetivos:
1) Dar a conocer esta extraordinaria funcionalidad de MySql
2) Comentar mi experiencia en un proyecto que utiliza 5 servidores de mysql replicados en diferentes ubicaciones geográficas.
3) Retomar este tipo de post didáctico que hace mucho abandoné por falta de tiempo.
Ver primero la parte 1: “Introducción a la replicación“
O ver la parte 2: “Caso práctico de replicación de bases de datos”
Como ya les habÃa comentado en los post anteriores de esta serie, el proyecto en el que trabajo utiliza 5 servidores de MySql replicados. Dos de esos servidores se encuentran alojados en Argentina y tres en Estados Unidos.
La replicación entre ellos es constante y caudalosa, sin embargo ésta suele fallar por diferentes motivos inherentes a los datos y a la estructura de ls bases de datos.
A continuación listaré un conjunto de fallas comunes que suelen tener las replicaciones y sus respectivas soluciones que hemos probado con éxito.
Por lo general, para corroborar el estado de una replicación, conviene realizar un chequeo en el servidor esclavo con el siguiente comando en la consola mysql:
SHOW SLAVE STATUS \G;
Esta acción mostrará un listado de parámetros que nos indican en que estado se encuentra la replicación; a continuación les comentaré brevemente los más importantes e indicativos de posibles problemas.
Slave_IO_State: Indica el estado del esclavo
Master_Log_File: Indica el archivo del del master que esta siendo leÃdo
Read_Master_Log_Pos: Indica la ultima posición que el esclavo ya leyó del master
Relay_Log_File: Indica el archivo de log propio que el esclavo esta executando
Relay_Log_Pos: Indica la posición del log propio que el esclavo esta ejecutando
Relay_Master_Log_File: Indica el log del master que el esclavo esta ejecutando
Slave_IO_Running: Indica si esta conectado al servidor master
Skip_Counter: Indica si se ha salteado alguna posición
Exec_Master_Log_Pos: Indica la posición del log del maestro que esta siendo ejecutada
Seconds_Behind_Master: Parámetro de tiempo en que tardará el esclavo en llegar hasta la ultima posición del ultimo log del Master
Los primeros parametros que suelo fijarnme son el “Slave_IO_Running” ya que si está en “No”, es porque no está conectado con el master y el “seconds_behind_master” ya que si esta conectado lo ideal serÃa que tenga 0 segundos. Si no es cero, por lo gral ejecuto el show slave status \G; varias veces con cierto intevalo de tiempo para ver si se incrementa.
En caso que se incremente significa que el master guarda más resultados de lo que el slave está leyendo, entonces nos fijamos en el número del parámetro “Exec_Master_Log_Pos” Si no se mueve despues de un cierto tiempo, hay un problema.
Problemas comunes conocidos:
La consulta que el slave está ejecutando está trabada o tarda demasiado. Para esto por lo general sugiero parar la replicación del slave: “STOP SLAVE;” y adelantar posiciones en el los ejecutando: “SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 10;” (10 son las posiciones que nuestro log avanzará). Pueden probar de a uno si quieren, en mi caso que el sistema procesa más de 600,000 inserts por dÃa no es demasiado problema un salto de 10 registros. Una vez avanzado, hay que iniciar nuevamente el slave: “START SLAVE;”
Una de nuestras tablas MyIsam esta dañada: Para esto se deberá parar la replicación: “STOP SLAVE;” y ejecutar desde consola de MySQL el comando “REPAIR TABLE nombredetabla;”. Si esto no lo solucionó, se puede hacer desde afuera del motro mysql con el comando “myisamchk –safe-recover nombredetabla.MYI” (repito: fuera de mysql, en el shel de linux y dentro de la carpeta de los archivos binarios de los datos de mysql)
Muchas veces se requiere hacer consultas grandes que sólo queremos hacerlo en el master pero no queremos que se replique, casos muy comunes de este tipo son el OPTIMIZE o el REPAIR ambas consultas quedarÃan logueadas y pasarÃan al esclavo trabando considerablemente el flujo de la información. Para solucionar esto sólo hay que agregar: NO_WRITE_TO_BINLOG inmediatamente despues del comando. EJ: “OPTIMIZE NO_WRITE_TO_BINLOG TABLES nombredetabla;”
Espero que esta serie de posts pueda serles de utilidad algún dÃa. La replicación hasta 4 servidores de MySql, como ya mensioné en el primer post, es la forma de escalabilidad más económica que puede tener un sistema a nivel de bases de datos. Además puede ser de gran utilidad poara mantener backups sincronizados de forma permanente.
Creo haber cumplido con todos los objetivos propuestos y creo también que fue una buena forma de retomar con este blog un tanto olvidado.
A partir del mysql 5, es posible replicar servidores de bases de datos MySql, algo que no mucha gente usa por el hecho que no siempre se dispone del acceso a la administración de más de un servidor.
Esta serie de posts tiene como objetivos:
1) Dar a conocer esta extraordinaria funcionalidad de MySql
2) Comentar mi experiencia en un proyecto que utiliza 5 servidores de mysql replicados en diferentes ubicaciones geográficas.
3) Retomar este tipo de post didáctico que hace mucho abandoné por falta de tiempo.
Ver primero la parte 1: “Introducción a la replicación” o ve como solucionar problemas de replicación de mysql
Imaginemos que tenemos sistema requiere de dos servidores de base de datos que tengan la misma información. Pero como nuestro sistema tiene un módulo de estadÃsticas, necesitamos que uno de ellos mantenga históricamente todos los registros mientras que el otro sólo mantenga los últimos 30 dÃas para que las consultas sean mucho más rápidas ya que es información que se vuelve obsoleta y por lo tanto innecesaria fuera del módulo de estadÃsticas.
Realizar dos conexiones a dos bases de datos distintas para ejecutar nuestros inserts/updates es poco eficiente y poco seguro, serÃa común ver inconsistencias. Para este caso, entonces, nada mejor que realizar una replicación.
Configuraremos entonces para que que el servidor maestro replique hacia el slave todos los inserts y updates que se ejecuten en éste y se configurará un cron en el esclavo que borre diariamente todos los listings anteriores a 30 dÃas. De esta forma cada insert o update que se realice en el maestro se realizará también en el esclavo que, además, borrará los registros viejos todos los dÃas.
Esto es mucho más seguro, porque todos los inserts/updates son logueados y controlados. Podemos saber y corregir en todo momento cual es la inconsistencia si la hubiese entre ambos servidores.
A continuación les presento un ejemplo de cómo configurar esta funcionalidad en ambos servidores para que cumplan su papel.
1) Como primer paso, debemos decirle al servidor Master dónde va a loguear toda su actividad; qué va a loguear, es decir que base de datos queremos que loguee y además le asignaremos un identificador. Para esto debemos editar el my.cnf de mysql agregando lÃneas como éstas:
server-id=1 binlog-do-db=nuestra_DB log-bin = /var/log/mysql/mysql-bin.log
También debemos decir que permita el acceso remoto, no sólo el acceso desde el localhost; por lo que debemos comentar estos parámetros en caso de que existan.
#bind-address #skip-networking
2) Reiniciamos el servidor de mysql desde la consola de linux y nos logueamos por consola al mysql con acceso root
# /etc/init.d/mysql restart # mysql -u root -p
3) Como próximo paso, debemos crear un usuario con acceso a la replicación. Este usuario es el que usará el Slave para identificarse. En la consola MySql y con acceso root, podrán crear el usuario de esta forma (también pueden usar phpMyAdmin para crearlo)
GRANT REPLICATION SLAVE ON *.* TO 'slave1'@'%' IDENTIFIED BY 'slave_password'; FLUSH PRIVILEGES;
slave1: será el nombre de usuario
slave_password: será el password de ese usuario
4) Ahora necesitamos saber la información del log para configurar el servidor slave, lo podremos hacer con el siguiente comando tambien en la consola MySql:
USE exampledb; FLUSH TABLES WITH READ LOCK; SHOW MASTER STATUS;
Les aparecerá una tabla con la el nombre del log, la posición, la base, etc. Copien esa info a algun archivo de texto a menos que tengan mucha memoria fotográfica.
Para terminar con el servidor Maestro sólo resta desbloquear las tablas bloqueadas en el paso anterior desde la consola MySql:
UNLOCK TABLES; quit;
1) Suponiendo que ya creamos la base de datos con el mismo nombre que la del Maestro, vamos directamente a editar la configuración del archivo my.cnf de mysql agregando/editando estas lÃneas:
# Servirá como identificador server-id=2 # El ip del servidor Master master-host=190.17.9.105 # El monbre de usuario que configuramos en el master master-user=slave_user # El password del usuario que configuramos en el master master-password=slave_password # Segundos antes de reintentar conectarse master-connect-retry=60 # Base de datos a replicar replicate-do-db=nuestra_DB
2) Reiniciamos entonces el servidor esclavo para que tome la nueva configuración:
# /etc/init.d/mysql restart
3) Nos logueamos como root al MySql y le decimos al esclavo que carge la info que exista en la DB del maestro para tener como punto de partida:
#mysql -u root -p # Enter password: LOAD DATA FROM MASTER;
4) En este paso, le vamos a tener que proveer a nuestro slave, la info que guardamos en el txt acerca del log del master parando la replicación (estos valores son de ejemplo, cambienlo por el que tienen ustedes):
SLAVE STOP; CHANGE MASTER TO MASTER_HOST='190.17.9.105', MASTER_USER='slave_user', MASTER_PASSWORD='slave_password', MASTER_LOG_FILE='mysql-bin.002', MASTER_LOG_POS=4;
5) Reiniciamos el servicio esclavo y ya tenemos nuestra replicación andando:
START SLAVE; quit;
Para saber si la replicación está andando sólo basta con poner el siguiente comando en la consola MySql
SHOW SLAVE STATUS G;
Esto fue todo en cuanto a la configuración de los servidores, espero que puedan seguir los pasos sin mayores inconvenientes.
Para el próximo y último post de esta serie, voy a comentar mi experiencia con esta funcionalidad y voy a dejar varias soluciones a problemas que surgieron en el proyecto que administraba y que sin duda les será útil si esto alguna vez les falla.
A partir del mysql 5, es posible replicar servidores de bases de datos MySql, algo que no mucha gente usa por el hecho que no siempre se dispone del acceso a la administración de más de un servidor.
Esta serie de posts tiene como objetivos:
1) Dar a conocer esta extraordinaria funcionalidad de MySql
2) Comentar mi experiencia en un proyecto que utiliza 5 servidores de mysql replicados en diferentes ubicaciones geográficas.
3) Retomar este tipo de post didáctico que hace mucho abandoné por falta de tiempo.
Si ya leiste esta introducción o tenés conocimientos acerca de que se trata visita: “Caso práctico de replicación de bases de datos“ o “Solución de problemas comunes de replicación de BD MySql”
La replicación de bases de datos es una funcionalidad que permite que toda acción realizada a un servidor de base de datos se replique automáticamente en otro servidor. Bajo este concepto, cualquier insert, update, delete, optimize o cualquier otra consulta que modifique la base de datos en cuestión, se ejecutará de la misma forma en el servidor replicado.
Es extremadamente útil cuando se trabaja con servidores en distintas ubicaciones geograficas y forman parte de un mismo sistema. También para realizar backups automáticamente y tener las mismas bases de datos disponibles todo el tiempo en diferentes servidores.
Esta funcionalidad se basa en un sistema cliente-servidor aunque mysql lo llama esclavo-maestro (slave-master). Funcionalmente es el servidor esclavo quien lee y ejecuta todas las instrucciones que un maestro ejecutó. Estas instrucciones son registradas en un log binario en el maestro y el esclavo mantiene un log de las posiciones que ya leyó y ejecutó del maestro.
Toda esta operación se realiza de forma asÃncrona. Es decir, no hace falta que la conexión entre el esclavo y el maestro este constantemente activa ya que el maestro sigue logueando en su log y el esclavo lo leerá y ejecutará desde la última posición registrada cuando detecte nuevamente la conexión. Claro está que si se da esta asincronÃa, el esclavo no este siempre actualizado, sino sólo después de leer la ultima posición del master. Si la conexión es permanente, los datos serán los mismos ya que la replicación es inmediata.
Podemos realizar tantas conexiones slave-master como sean necesario siempre y cuando un mismo slave no tenga 2 masters, esto generarÃa inconsistencias. Incluso es posible, aunque no recomendado si no se esta completamente seguro, que dos servidores sean slave-master entre ellos y viceversa siempre y cuando se filtren los datos a replicar, es decir, que lo que se replique desde el master al slave, no regrese. Si esto ocurriese, tendrÃamos una recursividad sin final pasando datos a diestra y siniestra.
Hablando desde mi experiencia, creo que la replicación es una forma muy fácil, rápida y económica de incrementar la escalabilidad de un sistema ya que si bien no funciona como cluster, podemos balancear la carga entre los n servidores que disponemos. Hay que aclarar que el número mÃnimo de servidores para un cluster es de 4 y que el cambio es significativamente grande ya que utiliza otro tipo de estructura MySql.
En los próximos posts, hablare de cómo configurar diferentes sistemas replicados con casos prácticos.
Disculpen si el artÃculo no salió claro y preciso, necesito retomar la práctica de redactar este tipo de post que suelen aportar algo a la comunidad.
¿Alguna vez sus máquinas se les pusieron mortalmente lentas y el led del disco no paraba ni aunque la desenchufaran? Bueno, acá les intentaré explicar de la forma más sencilla que puedo, qué es lo que pasa en estos casos TAN desagradables.
Los sistemas operativos multi-procesos, deben administrar la memoria de la mejor manera posible para que todos los procesos coexistan de forma equilibrada. Para esto, el SO. usa una técnica llamada paginación, que divide la memoria en distintos frames o páginas que le son asignados a cada proceso.
Todos sabemos que la memoria no es un recurso ilimitado, por esto es que existe la memoria virtual. Esta memoria virtual, no es más que una extensión de esas páginas en otro dispositivo de almacenamiento que no sea la memoria Principal (por ejemplo el disco rÃgido). Esto es lo que se conoce comúnmente como swaping; utilizar otro dispositivo de almacenamiento como extensión de la memoria principal (lo hace Photoshop cuando trabaja con imágenes grandes).
Ahora bien; cada proceso, tiene un número mÃnimo de frames o páginas que requiere que estén en la memoria principal para funcionar de forma correcta; por lo que no funcionarÃa si le falta alguno de esos espacios de memoria. Cuando esto sucede, el proceso, llamémosle A, envÃa un error de paginación solicitando que se le dé más espacio en la memoria principal. Hasta acá funcionarÃa todo bajo control.
¿Qué pasa cuando no tenemos disponibles esa cantidad mÃnima de memoria que necesita este proceso A?, tendrÃamos dos posibilidades: la primera serÃa quitarle alguna página a otro proceso B que se esta ejecutando para dársela a este. La segunda y que no viene al caso, serÃa dejar en cola de espera el proceso hasta que haya memoria suficiente, lo cual podrÃa esperar eternamente sin resultados.
Supongamos que le quitamos páginas en memoria al proceso B y las bajamos al disco rÃgido haciendo swaping para que se cumpla que haya disponible el mÃnimo necesario para que nuestro proceso A funcione. Todo fantástico con el proceso A; pero resulta que el proceso B manda un error de paginación ya que necesitaba que sà o sà estén en la memoria principal esos frames que le quitamos. Otra vez corremos con la disyuntiva de que podrÃamos hacer.
Supongamos que somos un sistema operativo tipo Windows y le bajamos de nuevo al proceso A algunas páginas al disco rÃgido para dárselos al B; el B estarÃa fabulosamente bien, pero el A se morirÃa de bronca y le harÃa un piquete al SO con una bandera de “error de paginación”.
De esta forma, el procesador se matarÃa paginando y bajando de la memoria principal al swap y viceversa para que los dos estén felices… pero ninguno lo estarÃa. Ni el proceso A ni el proceso B que tardarÃan años en terminar sus funciones, ni el SO que estarÃa matando al microprocesador en acciones inútiles ni muchos menos nosotros que verÃamos como la PC esta casi muerta con el procesador al 100% y el led del disco estarÃa rojo en todo momento.
Imaginen por un momento esta situación cuando tenemos más arriba de 50 procesos simultáneos. SerÃa un verdadero quilombo.
Es por eso que mientras mayor es el grado de multiproceso más probabilidades hay que nuestra PC esté en estado de thrashing. Este gráfico podrÃa ayudar a entender el moco que serÃa.

Ahora ya lo entienden al Windows, cuando hace esto o simplemente cuando dice que hay un error de paginación y unos números que nadie podrÃa entender. No es tarea fácil ser un sistema operativo. :P
Es probable que si programás sitios webs, hayas visto la necesidad de programar una ventana pop up que interactúe con la ventana padre.
Para lograr esto en IE no es nada de otro mundo, ya que el ámbito de los objetos puede ser salteado. Pero para hacer lo mismo en Mozilla u Opera, esto tiene que ser algo mucho más preciso
Ejemplo:
Tenemos una ventana padre con un formulario con nombre "formulario"; dentro un campo de texto con nombre "resultado". y un link que abre una ventana pop up.
Y en el pop up: Un formulario llamado "formu", un campo de texto llamado "datos" y un link que pasa los datos del pop up a la ventana padre.
Entonces, para hacer referencia al valor de “resultado” desde la ventana hija tenemos 4 instancias: window.opener (ventana padre), .document (documento html), .formulario (form), .resultado (input text) las cuales hay que respetar a rajatabla para que funcione en otro navegador que no sea IE.
QuedarÃa asi:
window.opener.document.formulario.resultado.value
Lo que faltarÃa ahora asignarle el valor del texto “dato” desde la ventana hija asi:
window.opener.document.formulario.resultado.value = window.document.formu.datos.value;
Ver el ejemplo funcionando (habiliten popups en sus navegadores para este ejemplo)
Acá les dejo el código, Vale aclarar que los campos de texto son sólo para el ejemplo, esto puede hacerse con cualquier objeto.
Ventana padre:
Ventana popup:
Si querés agregar algo te será agradecido, si querés más información acerca de como funciona Mozilla con JS esta página te puede servir.
Hace unos dÃas atras, publique un link para integrar la busqueda de este blog al navegador FireFox. Algunos me preguntaron como habÃa hecho, ahora les intentaré explicar como conseguirlo con su motor de búsqueda.
Para empezar, el FireFox necesita un archivo que lo podrÃamos llamar con la extensión src (source) que contiene la información necesaria para encontrar la ubicación del formulario de búsqueda en nuestra página, tambien la localización del Ãcono correspondiente.
PodrÃa ser una cosa similar a esta: (modificada de la versión que hicieron para Technorati):
<search#método de envio del formulario
name="Nombre de tu página/blog/foro/etc"
description="brebe descripcion de la busqueda que se realizara"
version = "1.0"
#(en caso de WordPress es el index.php)
method="GET"
#(WP tambien lo tiene en el index)
action="http://pagina-que-procesa-el-form.php
searchForm="http://pagina-con-el-form-de-busqueda.php"
># Este caso es el nombre del parametro o variable que contiene el string de búsqueda
# El index de WordPress recibe de el parámetro s el string de búsqueda
# Google lo toma de la variable q el string de búsqueda (se pueden fijar en la direccion una vez realizada la busqueda)
<input name="s" user>
</search>
# Este tag se refiere a las direcciones que necesita el buscador
<BROWSER
# Para actualizar el src (debe presisar en que lugar se encuentra este archivo en tu web)
update="http://dir-de-tu-pagina/nombre-de-src.src"
# Para mostrar y actualizar el Ãcono (debe presisar en que lugar se encuentra el Ãcono en tu web)
updateIcon="http://dir-de-tu-pagina/nombre-de-img.png"
updateCheckDays="10"
>
Una vez que tenemos este archivo ya configurado, lo subimos a nuestra web junto con la imágen.
Para implementar el link en tu web, te hace falta una pequeña función en JavaScript que explicaré a continuación:
(modificada de la que hicieron para technorati)
/* este if detecta que sea un Mozilla FireFox*/
<script language="javascript">
<!--
function addEngine()
{/*esta función agrega la búsqueda a tu navegador (coloca las direcciones de tu src, Ãcono y el nombre de tu busqueda)*/
if ((typeof window.sidebar == "object") && (typeof window.sidebar.addSearchEngine == "function"))
{/* Modifica el versito que le aparece en el alert cuando entra con otro navegador */
window.sidebar.addSearchEngine(
"http://tu-pagina/tu-archivo.src",
"http://tu-pagina/tu-imagen.png",
"eleZeta",
"Blog" );
}
else
{
alert("Este plug-in es para Mozilla, ¿Qué parte de Mozilla FireFox no entendiste? (http://mozilla.org/productos/firefox)");
}
}
-->
</script>>
Personaliza esta funcion y pegala en cualquier parte del index.
Luego agrega el link apuntando a esta funcion de esta forma:
<a href="javascript:addEngine();">Agrega la búsqueda en tu FireFox</a>
Y eso es todo. Cualquier duda o sugerencia, ya saben: Comentario, Guestbook o de última el email.
Ejemplo: Asi tengo configurado mi src y el java script que pueden ver en el codigo de la pagina que lo pegue en el menu.
Archivo .src:
JavaScript para pegar en tu página: