Mostrando entradas con la etiqueta Apache. Mostrar todas las entradas
Mostrando entradas con la etiqueta Apache. Mostrar todas las entradas

miércoles, 27 de agosto de 2014

Configurar la concurrencia en Apache y MySQL

Llega un momento en el que una aplicación Web tiene tanto éxito que el número de conexiones concurrentes satura las capacidades del servidor. Empiezan a aparecer errores de timeout o errores 500 Internal Server Error.

Para evitar ésto, se puede configurar Apache y MySQL para que admitan más concurrencia, es decir, más conexiones funcionando al mismo tiempo.

Concurrencia en Apache

Para configurar la concurrencia en Apache, hemos de configurar el archivo httpd.conf (el archivo será apache2.conf si está instalado en un Linux basado en Debian e instalado mediante sudo apt-get install apache2) o el archivo 000-default.conf.

Lo primero que debemos hacer es extraer la configuración actual de Apache. Para ello ejecutaremos el siguiente comando desde la terminal:

$ apache2 -V

El resultado será similar al siguiente:
Server version: Apache/2.2.22 (Debian)
Server built: Jul 24 2014 15:34:00
Server's Module Magic Number: 20051115:30
Server loaded: APR 1.4.6, APR-Util 1.4.1
Compiled using: APR 1.4.6, APR-Util 1.4.1
Architecture: 64-bit
Server MPM: Prefork
threaded: no
forked: yes (variable process count)
Server compiled with....
-D APACHE_MPM_DIR="server/mpm/prefork"
-D APR_HAS_SENDFILE
-D APR_HAS_MMAP
-D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
-D APR_USE_SYSVSEM_SERIALIZE
-D APR_USE_PTHREAD_SERIALIZE
-D APR_HAS_OTHER_CHILD
-D AP_HAVE_RELIABLE_PIPED_LOGS
-D DYNAMIC_MODULE_LIMIT=128
-D HTTPD_ROOT="/etc/apache2"
-D SUEXEC_BIN="/usr/lib/apache2/suexec"
-D DEFAULT_PIDLOG="/var/run/apache2.pid"
-D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
-D DEFAULT_LOCKFILE="/var/run/apache2/accept.lock"
-D DEFAULT_ERRORLOG="logs/error_log"
-D AP_TYPES_CONFIG_FILE="mime.types"
-D SERVER_CONFIG_FILE="apache2.conf"

Los primeros ajustes a realizar son:

  • KeepAlive On: Permite conexiones persistentes (más de una petición por conexión)
  • MaxKeepAliveRequests 100: Número máximo de peticiones permitidas durante una conexión persistente
  • KeepAliveTimout 5: Número de segundos de espera para la próxima petición en la misma conexión

A continuación, se ha de configurar el módulo de multiprocesamiento (MPM). En el ejemplo anterior lo conoceremos por la primera línea de la sección "Server compiled with...", en el parámetro APACHE_MPM_DIR. Como se puede observar, el módulo de multiprocesamiento es prefork. Por tanto, hemos de buscar en el archivo de configuración de Apache la sección correspondiente a este módulo, el cual contendrá los siguientes parámetros:

<IfModule mpm_prefork_module>
   StartServers 50
   MinSpareServers 20
   MaxSpareServers 70
   ThreadLimit 64
   ThreadsPerChild 25
   ServerLimit 500
   MaxClients 500
   MaxRequestsPerChild 0
</IfModule>

Los significado de estos parámetros es el siguiente:

  • StartServers: Número de servidores con los que arranca
  • MinSpareServers: Número mínimo de procesos de servidor que se mantienen de repuesto
  • MaxSpareServers: Número máximo de procesos de servidor que se mantienen de respuesto
  • ThreadLimit: Número máximo de hilos concurrentes
  • ThreadsPerChild: Número de hilos en funcionamiento en cada proceso del servidor
  • ServerLimit: Núḿeros máximo de servidores
  • MaxClients: Número máximo de procesos de servidor con los que arranca
  • MaxRequestsPerChild: Número máximo de peticiones que un proceso puede servir

NOTA: En el caso de nuestro Apache no tenga instalado un módulo de multiprocesamiento, podemos instalar uno mediante los siguientes comandos:

sudo apt-get update
sudo apt-get install apache2-mpm-prefork

Concurrencia en MySQL

Aunque configuremos Apache para que abastezca una gran cantidad de concurrencia, si nuestras webs acceden a bases de datos MySQL, encontrarán otro cuello de botella, pues MySQL también tiene una configuración predeterminada de concurrencia a la base de datos (unas 100 conexiones).

Para ajustar la concurrencia en MySQL, hemos de editar en el archivo my.cnf los siguientes parámetros:

  • max_connections: Número máximo de conexiones
  • thread_concurrency: Número de hilos concurrentes

A continuación, hay que rearrancar la base de datos para que MySQL asuma los cambios:

/etc/init.d/mysql restart

NOTA: Este comando es para Linux. En Windows, es similar, salvo la ruta.

Por último, verificamos que MySQL está funcionando con los valores actualizados. Para ello, arrancamos el cliente MySQL:

mysql -u root -p

Una vez nos logamos como administrador (hay que introducir la contraseña), en la línea de comandos del cliente MySQL introducimos la siguiente sentencia:

mysql> SHOW VARIABLES;

Buscamos las variables max_connections y thread_concurrency para verificar sus valores.

jueves, 21 de agosto de 2014

Guía de Instalación de Apache y PHP en Ubuntu y Linux Mint

Instalación de Apache y PHP5:

$ sudo apt-get install apache2
$ sudo apt-get install php5
$ sudo apt-get install libapache2-mod-php5
$ sudo /etc/init.d/apache2 restart

Para arrancar, parar y rearrancar Apache:

$ sudo /etc/init.d/apache2 start
$ sudo /etc/init.d/apache2 stop
$ sudo /etc/init.d/apache2 restart

Adicionalmente, se pueden instalar extensiones o módulos pdo, con lo que podremos añadir funcionalidades a php, tales como acceder a bases de datos, internacionalización, encriptación, json, etc.

$ sudo apt-get install php5-dev
$ sudo apt-get install php5-mysql
$ sudo apt-get install php5-pgsql
$ sudo apt-get install php5-sqlite
$ sudo apt-get install php5-intl
$ sudo apt-get install php5-mcrypt
$ sudo apt-get install php5-gd
$ sudo apt-get install php5-curl
$ sudo apt-get install php5-json

Para conocer los módulos PHP instalados con apt-get:

$ dpkg --list | grep php

Para ver la versión de PHP:

$ php -v

Para ver la información completa de la configuración de PHP:

$ php -i

Para ver los módulos instalados con PHP:

$ php -m

Para verificar que Apache y PHP están configurados bien, crear un archivo info.php en /var/www (o en el directorio html por defecto de Apache):

<?php
phpinfo();
?>
Abrir un navegador y escribir la url: http://localhost/info.php. Debería aparecer la siguiente pantalla con toda la información de nuestra instalación de PHP:

viernes, 29 de enero de 2010

Apache Pivot: Una RIA más

Las RIA's están revolucionando el modo en que interactuamos con Internet, gracias a las interfaces de usuario que proporcionan una experiencia diferente y amena, en contraste con las vetustas y aburridas interfaces tradicionales. En un artículo anterior (¿Cuál es la mejor plataforma RIA?) hice un análisis superficial sobre las distintas propuestas existentes: Ajax, Adobe Flex, OpenLaszlo, Microsoft Silverlight y JavaFX.

He descubierto una RIA más que me parece muy interesante, pues viene de la comunidad Apache, líder en proyectos de tecnologías web libres. Esta propuesta se denomina Apache Pivot, basándose en el archiconocido y popular lenguaje Java, líder mundial en cuanto a número de desarrollos y desarrolladores. El concepto es distinto al de JavaFX de Oracle (anteriormente Sun MicroSystems), pues esta comunidad ha sabido ver lo mejor de cada mundo y desarrollar una tecnología agradable y sencilla.



Al ser un desarrollo en Java, contamos con multitud de IDE's para desarrollar, en cualquier plataforma. Sólo es necesario descargar el framework y empezar a trabajar, sin necesidad de plugins adicionales en el navegador (sólo la máquina virtual de Java). Cuenta con un lenguaje de marcado llamado WTK basado en el modelo vista controlador, que facilita mucho el desarrollo de las aplicaciones, y que permite también combinar con código Java, del mismo que Adobe Flex combina MXML y ActionScript.


Apache Pivot ha desarrollado un conjunto de elementos de interfaz de usuario amplia, que abarca cualquier necesidad que podamos tener, incluyendo contenedores, árboles, menús, etc.

Aconsejo al lector que pueda verla y probarla mediante la siguiente demo: http://pivot.apache.org/tutorials/sample-application.html


Apache Pivot dispone también de recursos para conectar con servicios de datos remotos, como SOA, Web Services, HTTPServices o servicios de queries web (por citar algunos). La gestión de XML es simple y potente, al igual que que trabajar con JSON y con colecciones. No se olvida tampoco de efectos visuales ni del tratamiento del drag and drop. Asimismo, incluye un módulo especialmente dedicado a gráficos estadísticos.



Tampoco se olvida de las pieles para los elementos de interfaz, así como tampoco de los renderers, pudiendo ser capaz de añadir elementos de edición a las interfaces, como a una tabla o Grid.


Apache Pivot es una buena alternativa libre a las RIA's, con una comunidad con solera y con muchos adeptos. Los desarrolladores Java lo van a acoger muy bien, pues la interfaz de usuario es muy rica y bien definida y organizada, además de poder seguir desarrollando en Java o integrar este lenguaje al WTK.

Para ser imparcial, debo añadir algunas críticas:
1) La velocidad de carga. La carga del applet es tediosa, pudiendo llegar a minutos. Lo más importante en una página web o en una aplicación es que el usuario no tenga que esperar.
2) La velocidad de navegación. Cuando navegas por una aplicación, al cambiar de escenario (mediante una opción, por ejemplo), parece que la aplicación se para durante un tiempo indeterminado. El usuario no sabe qué hacer, hace clic en otros sitios y no responde. Crea estupefacción y confusión.
3) Recursos multimedia. Apache Pivot parece más pensado para aplicaciones de gestión, y no añade recursos multimedia, aunque conociendo Java, sería posible importar alguna librería y poder usar estos recursos. Tampoco tiene muchos efectos.


Enlaces
Página oficial: http://pivot.apache.org/index.html
Tutoriales: http://pivot.apache.org/tutorials
Demos: http://pivot.apache.org/demos

sábado, 10 de enero de 2009

Instalar Apache y PHP en Windows Vista

Resulta un tanto frustrante intentar instalar PHP bajo Apache en Windows Vista. Yo lo he intentando multitud de veces. He accedido a foros donde parecen dar la solución tocando allí y acá en los archivos de configuración del Apache y de PHP. Si bien la orientación es buena, en la práctica no es así. Tras probar todo tipo de configuraciones casi tiro la toalla, pues Apache no enlazaba con Apache a pesar de tener configurado correctamente el fichero httpd.conf y el fichero php.ini

Otra propuesta es instalar XAMP, pero pierdes el control sobre lo que instalas, y las versiones de los productos pueden no ser las que necesites.

Probé a desactivar la protección en tiempo real (uso Spyware Terminator), por si afectaba en algo. Tampoco era así.

Al final, tras dos días de intensas batallas con mi ordenador, instalando, desinstalando, borrando el registro de Windows, eliminando ficheros temporales, etc.; una bombilla se encendió en la única neurona que me queda. ¡Y funcionó!

Al final, la solución era mucho más sencilla. Bajo la premisa de que todo lo que se instala en el directorio Program Files de Windows Vista está regido por las normas de usuario de cuenta, probé a instalarlo todo fuera de él con los instaladores de Apache y PHP. He aquí los pasos que utilicé para hacerlo:

1) Desinstalar Apache y PHP de vuestro equipo.
2) Borrar los directorios y archivos generados y que no se han quitado tras la desinstalación
3) Borrar todas las entradas en el registro de apache y php (utilizar regedit)
4) Desactivar la protección en tiempo real del antivirus
5) Abrir la consola en modo administrador (menú Inicio > Todos los programas > Accesorios > clic derecho en Símbolo del Sistema > Ejecutar como administrador)
6) Ejecutar el programa de instalación de Apache mediante el comando: msiexec /i archivoSetupApache.msi
7) Con la configuración personalizada indicar que no se instale en el directorio por defecto (C:\Program Files), si no en otro directorio (en mi caso C:\Apache)
8) Una vez instalado Apache, parar éste (con Apache Monitor y saliendo por completo de la aplicación). Esto evitará que el fichero httpd.conf esté bloqueado por Apache mientras se instala PHP, y así poder escribir en él durante su instalación.
9) Ejecutar el programa de instalación de PHP mediante el comando: msiexec /i archivoSetupPHP.msi
10) Con la configuración personalizada indicar que no se instale en el directorio por defecto, si no en otro directorio (en mi caso C:\php)
11) Una vez instalado php, arrancar nuevamente Apache
12) Crear con el bloc de notas el archivo testphp.php en el directorio htdocs de Apache, con el siguiente contenido:

<html>
<head>
<title>PHP Test</title>
</head>
<body>
<?php echo '<p>Hello World</p>'; ?>
<?php phpinfo(); ?>
</body>
</html>

13) Para verificar que funciona correctamente, abrir el navegador e indicar la siguiente URL: http://localhost/testphp.php. El resultado debería ser el siguiente:


Por último, indicar mi configuración de entorno:
- Windows Vista Ultimate + Service Pack 1
- Apache 2.2.10
- PHP 5.2.8

Espero que estas indicaciones os saquen del apuro.

Safe Creative #1001195348600

lunes, 27 de octubre de 2008

Flex: Ejemplo de acceso a datos remotos

El objetivo de este interesante artículo es demostrar cuán sencillo y potente es el uso de la tecnología Flex. En esta ocasión procederemos a invocar a datos almacenados remotamente, y visualizarlos en varios componentes, como una lista o un DataGrid.



El escenario será, por un lado, un sistema remoto (o local) basado en Apache, en donde se ha instalado un servidor de base de datos MySQL y el motor de PHP. Este sistema contendrá un servicio que retornará un XML con la información recogida, la cual será interpretada por la aplicación Flex, que mostrará dicha información.

En primer lugar, se ha creado una base de datos con una tabla muy sencilla que contendrá una relación de categorías. Esta tabla tiene la siguiente estructura:


TABLA: gallery_categories
CAMPO: id_category - unsigned integer, not null, primary key
CAMPO: category_name - varchar(16), not null
CAMPO: category_directory - varchar(255), not null

Para acceder a la base de datos, utilizaremos PHP, el cual se ha instalado sobre el servidor web Apache. En el directorio "htdocs" de Apache, se ha creado el fichero "service_categories.php". Este fichero contendrá el siguiente código:


<?php
function getCategories() {
$xml = "";
mysql_select_db('basedatos');
$qry_categories = "select id_category, category_name
from gallery_categories";
$result_categories = mysql_query($qry_categories);
$num_categories = mysql_num_rows($result_categories);
if ($num_categories>0) {
$xml="<gallery_categories>\n";

for ($i=0; $i<$num_categories; $i++)
{
$row_categories = mysql_fetch_array($result_categories);
$category_name = $row_categories['category_name'];
$xml = $xml." <category>\n";
$xml = $xml." <label>".$row_categories['category_name'].
"</label>\n";
$xml = $xml." <data>".$row_categories['id_category'].
"</data>\n";
$xml = $xml." </category>\n";
}

$xml= $xml."</gallery_categories>\n";
}

return $xml;
}


@ $db = mysql_pconnect('localhost', 'usuario', 'password');

if ($db)
{
$categories = getCategories();
echo "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n\n";
echo $categories;
mysql_close($db);
}

?>

El código PHP conecta con la base de datos (mysql_pconnect), invoca a la función getCategories(), la cual accede a la tabla, leyendo todos sus registros, y componiendo un XML, el cual será retornado por PHP. Este XML será como el siguiente:


<?xml version="1.0" encoding="ISO-8859-1" ?>

<gallery_categories>
<category>
<label>Categoria1</label>
<data>1</data>
</category>
<category>
<label>Categoria2</label>
<data>2</data>
</category>
</gallery_categories>

Podríamos haber usado los nombres de los campos en el XML. El uso de los tags "label" y "data" es debido a que el componente lista de Flex, utiliza estos tags clave para formar automáticamente la lista, mostrando el texto (label) y asociando el código correspondiente (data).


Una vez resuelta la lógica de negocio, le toca el turno a la presentación, en la cual Flex es el protagonista. Se comienza con la siguiente estructura de código:


<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
creationComplete="categoriesRequest.send()">

</mx:Application>

Flex utiliza el lenguaje MXML, basado en un juego especial de códigos en formato XML. Por ello, la primera línea (<?xml...), corresponde a un fichero en sintaxis XML. Tras esta línea, comienza la aplicación, la cual está representada por los tags <mx:Application> y </mx:Application>, y entre estos tags iría toda nuestra aplicación. A modo aclaratorio, todos los tags de Flex utilizan el prefijo "mx:", seguido de un tag correspondiente a un comando del lenguaje MXML.


El atributo "<xmlns..." apunta al juego de comandos del lenguaje XML.


El atributo "layout", indica la forma en que se distribuirán los componentes en el espacio de visualización de la aplicación. El valor "absolute" indica que la posición estará basada en coordenadas X e Y, desde la esquina superior izquierda, expresada en píxeles.


El atributo "creationComplete" indica qué debe hacer la aplicación una vez haya sido creada la instancia de la misma. En este caso, invocará al método send() del objeto "categoriesRequest", el cual se verá a continuación, y que se encargará de invocar al servicio creado en PHP.


El primer comando a utilizar dentro de nuestra aplicación será la siguiente:


<mx:HTTPService
id="categoriesRequest"
url="http://localhost/service_categories.php"
resultFormat="e4x"
useProxy="false"
/>

Este comando crear un servicio HTTP, el cual invocará al servicio creado en PHP, indicando la ubicación de éste en el atributo "url". El atributo "id" genera el nombre de cualquier objeto. En este caso, el objeto "categoriesRequest" es invocado a través de su método send() una vez creada la aplicación (ver el atributo creationComplete()". El atributo "resultFormat" establece el formato del XML a ser tratado, que, en este caso, es el "e4x", el cual permitirá tratar el XML de forma sencilla e intuitiva. Por último, el atributo "useProxy" determinará el uso de un proxy en caso de ser necesario (en nuestro caso no lo es).


Para probar el correcto funcionamiento de este servicio, utilizaremos el componente TextArea, el cual mostrará el XML recuperado por el objeto "categoriesRequest". Se incluirá el siguiente código justo después del anterior:


<mx:TextArea
width="300" height="200"
text="{categoriesRequest.lastResult.toString()}"/>

El componente TextArea mostrará una caja de texto grande que permite visualizar varias líneas. El atributo "width" establece el ancho (en píxeles) del componente. El atributo "height" establece el ancho. El atributo "text" contiene el texto a visualizar en el componente. En este caso, el resultado del comando ejecutado entre las llaves será lo que se visualice. El comando en cuestión es el texto devuelto por el método toString(), correspondiente al XML invocado por el objeto "categoriesRequest". "lastResult" permite posicionarse al inicio del XML obtenido.


El resultado sería el siguiente:



Una vez verificado que se recoge bien el XML, se procede a utilizar el mismo para utilizar los datos obtenidos de forma funcional. En el primer ejemplo se utilizará una lista, la cual mostrará los valores legibles, uno debajo de otro. Cuando se selecciona uno de estos valores legibles, internamente tendrá asociado un valor clave, como un código o un identificador. Para ello, el XML debe tener los tags clave <label> y <data>. Para ello, se sustituirá el código del componente TextArea por este otro código:


<mx:List
id="lst_categories"
dataProvider="{categoriesRequest.lastResult.category}"/>

El componente List accederá al nivel del tags "category" dentro del XML, recogiendo de cada uno encontrado los atributos "label" y "data", y aplicando el texto y el valor correspondientes a la lista. El atributo "dataProvider" se encargará de acceder a dicho nivel, dentro del XML obtenido en el objeto "categoriesRequest".


El último componente a probar será DataGrid, que mostrará una tabla con los datos. En este caso, no sería necesario que utilice los tags clave "label" y "data", pudiendo utilizarse los tags deseados. El código para este componente será el siguiente:


<mx:DataGrid
dataProvider="{categoriesRequest.lastResult.category}">
<mx:columns>
<mx:DataGridColumn
headerText="ID"
dataField="data"/>
<mx:DataGridColumn
headerText="Nombre"
dataField="label"/>
</mx:columns>
</mx:DataGrid>

"DataGrid" define el objeto de tabla, que se alimentará de los niveles "category" del XML (dataProvider). El tag "mx:columns" define la estructura de columnas de la tabla, cada una de las cuales está representada por el tag "mx:DataGridColumn", estableciendo el texto de cabecera (headerText) y el campo origen de los datos (dataField).


El resultado sería el siguiente: