<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Bosque Viejo</title>
	<atom:link href="http://bosqueviejo.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://bosqueviejo.net</link>
	<description>Sitio web sobre programación, software libre, redes, servidores, ofimática... y todo lo relacionado con la informática que nos rodea</description>
	<lastBuildDate>Tue, 08 May 2012 14:40:56 +0000</lastBuildDate>
	<language>es</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Juggernaut: invirtiendo el paradigma cliente/servidor</title>
		<link>http://bosqueviejo.net/2012/05/08/juggernaut-invirtiendo-el-paradigma-clienteservidor/</link>
		<comments>http://bosqueviejo.net/2012/05/08/juggernaut-invirtiendo-el-paradigma-clienteservidor/#comments</comments>
		<pubDate>Tue, 08 May 2012 14:40:56 +0000</pubDate>
		<dc:creator>bombadil</dc:creator>
				<category><![CDATA[programación]]></category>
		<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[juggernaut]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://bosqueviejo.net/?p=1371</guid>
		<description><![CDATA[ Juggernaut, además de ser un personaje del universo Marvel, es un servidor escrito en Node.JS, que permite su integración con Ruby on Rails para realizar el intercambio de mensajes en dirección del servidor hacia el navegador.
Este esquema permite al servidor poder enviar mensajes al navegador en cualquier momento, de modo que se mantiene una actualización mucho más precisa que con refrescos esporádicos del navegador web hacia el servidor.
¿Cómo funciona?
Juggernaut, para conseguir esto se basa en el uso de un código en Flash que le permite abrir un socket y mantener la comunicación con el servidor de forma constante. En la parte del cliente, por lo tanto, está el navegador que realiza las peticiones al código de Rails como siempre y, además, el código Flash que abre la comunicación con el servidor de Juggernaut, que le va enviando código en JavaScript que ejecuta para realizar acciones concretas.
En la parte del servidor tenemos también dos elementos bien diferenciados, por un lado tenemos al servidor de Juggernaut ejecutándose en el puerto 5001 (por defecto) y el servidor de Rails ejecutándose en otro puerto (por defecto en desarrollo suele ser el 3000). La comunicación con el servidor de Rails es como siempre en [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://bosqueviejo.net/wp-content/uploads/The_Juggernaut-150x150.jpg" alt="" title="The_Juggernaut" width="150" height="150" class="alignleft size-thumbnail wp-image-1372" /> <a href="http://juggernaut.rubyforge.org/">Juggernaut</a>, además de ser un <a href="http://es.wikipedia.org/wiki/Juggernaut_(Marvel_Comics)">personaje del universo Marvel</a>, es un servidor escrito en <a href="/2012/01/03/nodejs-el-servidor-javascript/">Node.JS</a>, que permite su integración con <a href="/2011/10/17/rails-3-1-mejorando-las-vistas/">Ruby on Rails</a> para realizar el intercambio de mensajes en dirección del servidor hacia el navegador.</p>
<p>Este esquema permite al servidor poder enviar mensajes al navegador en cualquier momento, de modo que se mantiene una actualización mucho más precisa que con refrescos esporádicos del navegador web hacia el servidor.</p>
<h3>¿Cómo funciona?</h3>
<p>Juggernaut, para conseguir esto se basa en el uso de un código en Flash que le permite abrir un socket y mantener la comunicación con el servidor de forma constante. En la parte del cliente, por lo tanto, está el navegador que realiza las peticiones al código de Rails como siempre y, además, el código Flash que abre la comunicación con el servidor de Juggernaut, que le va enviando código en JavaScript que ejecuta para realizar acciones concretas.</p>
<p>En la parte del servidor tenemos también dos elementos bien diferenciados, por un lado tenemos al servidor de Juggernaut ejecutándose en el puerto 5001 (por defecto) y el servidor de Rails ejecutándose en otro puerto (por defecto en desarrollo suele ser el 3000). La comunicación con el servidor de Rails es como siempre en protocolo HTTP, mientras que el intercambio de información a través del interfaz de Juggernaut se sucede en formato JSON, enviando información específica a ejecutar en el navegador.</p>
<h3>Instalación</h3>
<p>La verdad es que la instalación no queda nada clara, por lo que voy a explicar el cómo se instala el sistema para tenerlo funcionando en poco tiempo. En principio, necesitamos ejecutar lo siguiente:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">gem install json
gem install eventmachine
gem install juggernaut
gem install maccman-juggernaut -s http://gems.github.com</pre></div></div>

<p>Tenemos que crear un proyecto Rails. En principio, tendrá que ser una versión anterior a la 3.2, ya que en esa versión se ha eliminado el uso de plugins en favor de las gemas, por lo que, creamos nuestro proyecto Rails y ejecutamos:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">ruby script/plugin install git://github.com/maccman/juggernaut_plugin.git</pre></div></div>

<p>Ahora toca lanzar la parte servidora de Juggernaut, para eso, vamos a generar un fichero de configuración, el sistema nos puede generar uno automáticamente de la siguiente forma:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">juggernaut -g juggernaut.yml</pre></div></div>

<p>Con esto ya tenemos instalado todo el sistema de Juggernaut, y lo básico para poder integrarlo dentro de nuestro proyecto Rails.</p>
<h3>Implementando Juggernaut en Rails</h3>
<p>Introducir Juggernaut en Rails es tan sencillo como crear un nuevo controlador, por ejemplo uno llamado <em>Chat</em>, y escribir el siguiente código en el fichero <tt>chat_controller.rb</tt>:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> ChatController <span style="color:#006600; font-weight:bold;">&lt;</span> ApplicationController
  <span style="color:#9966CC; font-weight:bold;">def</span> index
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> send_data
    render <span style="color:#ff3333; font-weight:bold;">:juggernaut</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>page<span style="color:#006600; font-weight:bold;">|</span>
        page.<span style="color:#9900CC;">insert_html</span> <span style="color:#ff3333; font-weight:bold;">:top</span>, <span style="color:#996600;">'chat_data'</span>, <span style="color:#996600;">&quot;&lt;li&gt;&lt;strong&gt;#{params['id']}&lt;/strong&gt;: #{h params['chat_input']}&lt;/li&gt;&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    render <span style="color:#ff3333; font-weight:bold;">:nothing</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>En este código tenemos dos entradas, una es el <em>index</em> que lo emplearemos para entrar en la página inicial, y otra es la parte de envío de datos, a la que llamaremos mediante AJAX. El formulario lo montamos de la siguiente forma en el fichero <tt>index.html.erb</tt>:</p>
<pre style="color:#000000;background-color:#f9f9f9; border: #c0c0c0 solid 1px; font-size:12px;">
<b>&lt;html&gt;</b>
<b>&lt;head&gt;</b>
    <b>&lt;title&gt;</b>Chat<b>&lt;/title&gt;</b>
    <b>&lt;%=</b> <span style='color:#000080;'>javascript_include_tag</span> <span style='color:#d40000;'>:defaults</span>, <span style='color:#d40000;'>:juggernaut</span> <b>%&gt;</b>
    <b>&lt;%=</b> juggernaut(<span style='color:#d40000;'>:client_id</span> <span style='color:#ff00ff;'>=&gt;</span> params<span style='color:#ff00ff;'>[</span><span style='color:#d40000;'>:id</span><span style='color:#ff00ff;'>]</span>) <b>%&gt;</b>
<b>&lt;/head&gt;</b>
<b>&lt;body&gt;</b>
    <b>&lt;%=</b> <span style='color:#000080;'>form_remote_tag</span>(
          <span style='color:#d40000;'>:url</span> <span style='color:#ff00ff;'>=&gt;</span> <span style='color:#ff00ff;'>{</span> <span style='color:#d40000;'>:action</span> <span style='color:#ff00ff;'>=&gt;</span> <span style='color:#d40000;'>:send_data</span> <span style='color:#ff00ff;'>}</span>,
          <span style='color:#d40000;'>:complete</span> <span style='color:#ff00ff;'>=&gt;</span> <span style='color:#dd0000;'>&quot;$('chat_input').value = ''&quot;</span> ) <b>%&gt;</b>
    <b>&lt;%=</b> <span style='color:#000080;'>text_field_tag</span>( <span style='color:#dd4a4a;'>'chat_input'</span>, <span style='color:#dd4a4a;'>''</span>, <span style='color:#ff00ff;'>{</span> <span style='color:#d40000;'>:size</span> <span style='color:#ff00ff;'>=&gt;</span> <span style='color:#0000ff;'>20</span>, <span style='color:#d40000;'>:id</span> <span style='color:#ff00ff;'>=&gt;</span> <span style='color:#dd4a4a;'>'chat_input'</span><span style='color:#ff00ff;'>}</span> ) <b>%&gt;</b>
    <b>&lt;%=</b> <span style='color:#000080;'>hidden_field_tag</span>( <span style='color:#dd4a4a;'>'id'</span>, params<span style='color:#ff00ff;'>[</span><span style='color:#d40000;'>:id</span><span style='color:#ff00ff;'>]</span> ) <b>%&gt;</b>
    <b>&lt;%=</b> <span style='color:#000080;'>submit_tag</span> <span style='color:#dd0000;'>&quot;Add&quot;</span> <b>%&gt;</b>
    <b>&lt;/form&gt;</b>
    <b>&lt;ul</b><span style='color:#008000;'> id=</span><span style='color:#aa0000;'>&quot;chat_data&quot;</span><span style='color:#008000;'> style=</span><span style='color:#aa0000;'>&quot;list-style:none&quot;</span><b>&gt;</b>
    <b>&lt;/ul&gt;</b>
<b>&lt;/body&gt;</b>
<b>&lt;/html&gt;</b></pre>
<h3>Lanzando la aplicación</h3>
<p>Lanzamos Rails (ya sea con mongrel, thin o cualquier otro servidor) y Juggernaut. El lanzamiento de Juggernaut lo podemos hacer de la siguiente forma:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">juggernaut -c juggernaut.yml</pre></div></div>

<p>Ahora vamos al navegador, abrimos dos navegadores:</p>
<ul>
<li><a href="http://localhost:3000/chat/index/yo">http://localhost:3000/chat/index/yo</a></li>
<li><a href="http://localhost:3000/chat/index/tu">http://localhost:3000/chat/index/tu</a></li>
</ul>
<p>Si vamos escribiendo en una ventana, veremos como van apareciendo los textos en ambas, algo como esto:</p>
<p><img src="http://bosqueviejo.net/wp-content/uploads/chat_juggernaut.png" alt="" title="chat_juggernaut" width="709" height="283" class="aligncenter size-full wp-image-1392" /></p>
<p>Con lo que comprobamos que el sistema funciona correctamente.</p>
<h3>Algunas pegas</h3>
<p>Como hemos visto desde el principio, la comunicación del navegador se realiza a través de un puerto que no es el 80, típico del protocolo HTTP, y que tampoco es protocolo HTTP lo que transita por ese puerto, por lo que, en instalaciones con acceso a Internet restringido, es posible que este sistema no funcione correctamente.</p>
<p>Además, se suma el problema de que el puerto 5001 debe de mantenerse abierto hacia Internet, si no configuramos con suficiente seguridad, a través del fichero <tt>juggernaut.yml</tt> el sistema, podemos encontrarnos un verdadero agujero de seguridad&#8230; ya depende de para qué usemos Juggernaut, pero teniendo en cuenta de que ejecuta código JavaScript en el cliente, podría ser algo nocivo.</p>
<h3>Conclusiones</h3>
<p>Esta aproximación al sistema de Juggernaut ha sido bastante interesante para descubrir una forma de realizar este tipo de comunicaciones entre cliente y servidor de forma inversa, es decir, que el servidor pueda enviar información al cliente sin que el cliente la solicite. No obstante, los navegadores actuales implementan un sistema denominado <em>websocket</em> que tenderá a sustituir estos mecanismos artesanos de una forma más estándar y frameworks como ChicagoBoss ya lo implementan de forma nativa. El futuro nos mostrará los caminos que se van tomando, de momento, Juggernaut es una muy buena solución para todos los navegadores web actuales.</p>
]]></content:encoded>
			<wfw:commentRss>http://bosqueviejo.net/2012/05/08/juggernaut-invirtiendo-el-paradigma-clienteservidor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Estructura Lider/Trabajador en Erlang</title>
		<link>http://bosqueviejo.net/2012/05/07/estructura-lider-trabajador-en-erlang/</link>
		<comments>http://bosqueviejo.net/2012/05/07/estructura-lider-trabajador-en-erlang/#comments</comments>
		<pubDate>Mon, 07 May 2012 11:22:51 +0000</pubDate>
		<dc:creator>bombadil</dc:creator>
				<category><![CDATA[programación]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[gen_leader]]></category>
		<category><![CDATA[lider/trabajador]]></category>
		<category><![CDATA[maestro/esclavo]]></category>
		<category><![CDATA[otp]]></category>

		<guid isPermaLink="false">http://bosqueviejo.net/?p=1359</guid>
		<description><![CDATA[ Erlang es muy bueno para programación distribuida, y paralela, y concurrente, así mismo se hace muy simple la creación de servidores, tal y como he mostrado en entradas anteriores (servidor UDP y servidor TCP), pero nos queda una tipo de comportamiento que es algo complejo llevar a la práctica. Me refiero al paradigma de Maestro-Esclavo.
La teoría
El paradigma Maestro-Esclavo se basa en que, para acceder a un recurso que está disponible solo desde un punto o solo para un servicio, ya sea por que su acceso es crítico en concurrencia o porque solo se pueda acceder desde un único punto cada vez, se hace necesaria una estructura en la que un único punto sea el responsable de ese acceso, quedando todos los demás supeditados a este.
Esto genera igualmente un problema de cuello de botella, pero la misión no es distribuir, en este caso, para ganar más potencia de procesamiento, sino conseguir: una mayor alta disponibilidad para un recurso accesible solo desde un punto cada vez.
En la terminología de Erlang, la nomenclatura empleada es líder (leader) para referirse al maestro elegido cada vez, y trabajador (worker) para referirse a los esclavos. Esto es así por dos sutiles diferencias que existen entre [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://bosqueviejo.net/wp-content/uploads/lider-150x150.jpg" alt="" title="lider" width="150" height="150" class="alignleft size-thumbnail wp-image-1360" /> Erlang es muy bueno para programación distribuida, y paralela, y concurrente, así mismo se hace muy simple la creación de servidores, tal y como he mostrado en entradas anteriores (<a href="/2012/03/21/erlang-servidores-udp/">servidor UDP</a> y <a href="/2012/04/09/erlang-servidores-concurrentes-tcp/">servidor TCP</a>), pero nos queda una tipo de comportamiento que es algo complejo llevar a la práctica. Me refiero al paradigma de Maestro-Esclavo.<span id="more-1359"></span></p>
<h3>La teoría</h3>
<p>El paradigma Maestro-Esclavo se basa en que, para acceder a un recurso que está disponible solo desde un punto o solo para un servicio, ya sea por que su acceso es crítico en concurrencia o porque solo se pueda acceder desde un único punto cada vez, se hace necesaria una estructura en la que un único punto sea el responsable de ese acceso, quedando todos los demás supeditados a este.</p>
<p>Esto genera igualmente un problema de cuello de botella, pero la misión no es distribuir, en este caso, para ganar más potencia de procesamiento, sino conseguir: una mayor alta disponibilidad para un recurso accesible solo desde un punto cada vez.</p>
<p>En la terminología de Erlang, la nomenclatura empleada es <em>líder</em> (leader) para referirse al maestro elegido cada vez, y <em>trabajador</em> (worker) para referirse a los esclavos. Esto es así por dos sutiles diferencias que existen entre el modelo clásico de maestro-esclavo frente a este de lider-trabajador:</p>
<ul>
<li>El maestro es siempre uno y se carga con las tareas de replicación y de escritura, el líder, sin embargo, se carga con todas las tareas y no replica nada entre sus trabajadores.</li>
<li>El esclavo se encarga de las tareas más frecuentes, en su caso, las lecturas, sin pedir nada al maestro. Si le llega una escritura puede remitirla a su maestro o ignorarla, depende de la implementación. El trabajador, sin embargo, delega todos los trabajos al líder.</li>
<li>Cuando un maestro <em>muere</em>, los esclavos quedan atendiendo lecturas, pero el sistema de escritura queda sin servicio, a menos que haya algún mecanismo que permita, por alta disponibilidad, levantar a otro maestro, pero no es la base del paradigma. Cuando un líder <em>muere</em>, en cambio, de entre los trabajadores se elige a un nuevo líder, que se encarga de las peticiones. El esquema está pensado en sí para tener una alta disponibilidad.</li>
</ul>
<p>Aunque es un comportamiento bastante básico, aún no se ha introducido en la base de Erlang, ya que sus algoritmos de elección han sufrido cambios, incluso hasta hace pocos meses. Supongo que incluso aún habrá algún que otro cambio más, por lo que conviene mantenerse al día. El repositorio oficial (de momento) es <a href="https://github.com/abecciu/gen_leader_revival">este de github, gen_leader_revival de abecciu</a>.</p>
<p>Los autores de la base son Andrew Thompson, Dave Fayram, Hans Svensson y Ulf Wiger.</p>
<h3>La implementación</h3>
<p>El código podemos descargarlo del repositorio indicado anteriormente, solo necesitaremos el código de <a href="https://raw.github.com/abecciu/gen_leader_revival/master/src/gen_leader.erl">gen_leader.erl</a> y el código de <a href="https://raw.github.com/abecciu/gen_leader_revival/master/examples/skeleton.erl">skeleton.erl</a>.</p>
<p>La plantilla nos da lo básico para que el <tt>gen_leader</tt> funcione. Si compilamos ambas y lanzamos desde una consola el <tt>skeleton</tt>, podemos ver que funciona correctamente. Es más, vamos a modificarlo muy poquito agregando solo impresiones por pantalla para saber en qué momento se ejecuta cada uno:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">elected</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">State</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Election</span><span style="color: #6bb810;">,</span> undefined<span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #45b3e6;">Synch</span> <span style="color: #014ea4;">=</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span>
    <span style="color: #ff4e18;">io</span>:<span style="color: #ff3c00;">format</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;no one elected? ~p~n&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Election</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Synch</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
&nbsp;
<span style="color: #ff3c00;">elected</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">State</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Election</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Node</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #ff4e18;">io</span>:<span style="color: #ff3c00;">format</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;elected node [~p]: ~p~n&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Node</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Election</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>reply<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">surrendered</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">State</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Synch</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Election</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #ff4e18;">io</span>:<span style="color: #ff3c00;">format</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;surrendered (~p): ~p~n&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Synch</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Election</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">handle_leader_call</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Request</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_From</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Election</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #ff4e18;">io</span>:<span style="color: #ff3c00;">format</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;leader_call (~p): ~p~n&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span>gen_leader:<span style="color: #006600;">leader_</span><span style="color: #fa6fff;">node</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Election</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Request</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>reply<span style="color: #6bb810;">,</span> ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">from_leader</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Synch</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Election</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #ff4e18;">io</span>:<span style="color: #ff3c00;">format</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;from_leader (~p): ~p~n&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span>gen_leader:<span style="color: #006600;">leader_</span><span style="color: #fa6fff;">node</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Election</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Synch</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">handle_DOWN</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Node</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Election</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #ff4e18;">io</span>:<span style="color: #ff3c00;">format</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;DOWN (~p): ~p~n&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Node</span><span style="color: #6bb810;">,</span> gen_leader:<span style="color: #006600;">leader_</span><span style="color: #fa6fff;">node</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Election</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>El código modificado es llamado como <em>callback</em> cuando se suceden las siguientes situaciones:</p>
<ul>
<li><tt>elected</tt> (con nodo <tt>undefined</tt>), es llamada cuando el nodo es elegido para ser líder, si la variable de <tt>Nodo</tt> no es <tt>undefined</tt>, entonces es llamado cuando un nuevo trabajador se ha unido al líder.</li>
<li><tt>surrendered</tt>, llamada en trabajadores cuando un líder ha sido elegido, o cuando un nuevo nodo entra en el clúster, y se decide de nuevo quién es el líder, siendo llamado <tt>elected</tt> en el líder elegido y <tt>surrendered</tt> en el nuevo trabajador.</li>
<li><tt>handle_leader_call</tt>, esta llamada la realiza quien necesita algo del cluster, o cualquiera de los trabajadores al líder, pero en esencia, solo se proces en el líder.</li>
<li><tt>from_leader</tt>, mensajes que se emiten desde el líder hacia los trabajadores. Si la devolución de <tt>handle_leader_call</tt> es <tt>{reply, Reply, Broadcast, State}</tt>, se envía el mensaje de <em>Broadcast</em> a todos los trabajadores, con lo que pueden hacer alguna sincronización con su estado interno o realizar la acción que se requiera.</li>
<li><tt>handle_DOWN</tt>, mensaje de caída recibida por el líder de los nodos que han caído. Cuando cae el líder, un nuevo líder es elegido y se le envía la señal de caída del nodo del antiguo líder.</li>
</ul>
<p>Teniendo estas características en cuenta, podemos ejecutar el código y ver cómo se comporta:</p>
<p>En <strong>lider1@bosqueviejo</strong>:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">(lider1@bosqueviejo)1&gt; {ok, Pid} = datos:start_link(['lider1@bosqueviejo', 'lider2@bosqueviejo']).
no one elected? {election,&lt;0.55.0&gt;,none,datos,lider1@bosqueviejo,
                          [lider1@bosqueviejo,lider2@bosqueviejo],
                          [],
                          [lider2@bosqueviejo],
                          [],[],none,norm,
                          {1,6,0},
                          [],[],5000,
                          {interval,#Ref&lt;0.0.0.49&gt;},
                          lider2@bosqueviejo,6,1,sender}
{ok,&lt;0.55.0&gt;}</pre></div></div>

<p>Ahora levantamos en <strong>lider2@bosqueviejo</strong>:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">(lider2@bosqueviejo)1&gt; {ok, Pid} = datos:start_link(['lider1@bosqueviejo', 'lider2@bosqueviejo']).
{ok,&lt;0.55.0&gt;}
surrendered ([]): {election,&lt;6327.55.0&gt;,none,datos,lider1@bosqueviejo,
                            [lider1@bosqueviejo,lider2@bosqueviejo],
                            [],[],
                            [{lider1@bosqueviejo,lider1@bosqueviejo},
                             {#Ref&lt;0.0.0.59&gt;,lider1@bosqueviejo},
                             {#Ref&lt;0.0.0.57&gt;,lider1@bosqueviejo}],
                            [],none,norm,
                            {1,6,0},
                            [],[],5000,undefined,undefined,5,1,sender}</pre></div></div>

<p>En <strong>lider1@bosqueviejo</strong> se sucede el siguiente mensaje al levantar al <strong>lider2@bosqueviejo</strong>:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">elected node [lider2@bosqueviejo]: {election,&lt;0.55.0&gt;,none,datos,
                                       lider1@bosqueviejo,
                                       [lider1@bosqueviejo,lider2@bosqueviejo],
                                       [],[],
                                       [{#Ref&lt;0.0.0.74&gt;,lider2@bosqueviejo}],
                                       [],none,norm,
                                       {1,6,0},
                                       [],[],5000,
                                       {interval,#Ref&lt;0.0.0.49&gt;},
                                       lider2@bosqueviejo,6,1,sender}</pre></div></div>

<p>Ahora en <strong>lider1@bosqueviejo</strong> enviamos un mensaje:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">(lider1@bosqueviejo)2&gt; gen_leader:leader_call(Pid, &quot;hola&quot;).
leader_call (lider1@bosqueviejo): &quot;hola&quot;
ok</pre></div></div>

<p>Y lo que pasaba al mismo tiempo en <strong>lider2@bosqueviejo</strong>:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">from_leader (lider1@bosqueviejo): [118,117,101,115,116,114,111,32,108,105,100,
                                   101,114,32,100,105,99,101,58,32,&quot;hola&quot;,
                                   &quot;\n&quot;]</pre></div></div>

<p>En caso de que salgamos de la consola del <strong>lider1@bosqueviejo</strong> vemos lo siguiente en <strong>lider2@bosqueviejo</strong>:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">no one elected? {election,&lt;0.55.0&gt;,&lt;6327.55.0&gt;,datos,lider2@bosqueviejo,
                          [lider1@bosqueviejo,lider2@bosqueviejo],
                          [],
                          [lider1@bosqueviejo],
                          [{#Ref&lt;0.0.0.59&gt;,lider1@bosqueviejo},
                           {#Ref&lt;0.0.0.57&gt;,lider1@bosqueviejo}],
                          [],none,norm,
                          {2,5,1},
                          [],[],5000,
                          {interval,#Ref&lt;0.0.0.75&gt;},
                          lider2@bosqueviejo,5,2,sender}
DOWN (lider1@bosqueviejo): lider2@bosqueviejo</pre></div></div>

<p>Es decir, se elige a un nuevo líder y se envía el mensaje de caída del líder.</p>
<h3>Conclusiones</h3>
<p>Este esquema es bastante útil ya que simplifica el problema de tener varios servidores, por ejemplo, y recursos que solo pueden estar disponibles en un solo servidor cada vez. Por ejemplo, el acceso a un recurso propietario que solo nos da una licencia de uso, el acceso con control de concurrencia a un recurso.</p>
<p>Su interfaz de broadcast, permite que el sistema pueda recibir peticiones de lectura y escritura, haciendo que su <em>broadcast</em> deje la información en cada worker para, en caso de que cayese el líder, puedan seguir funcionando sin problema alguno.</p>
<p>Realmente, otro elemento más para facilitar la creación de sistemas servidores de alta disponibilidad en Erlang.</p>
]]></content:encoded>
			<wfw:commentRss>http://bosqueviejo.net/2012/05/07/estructura-lider-trabajador-en-erlang/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UUID: Identificador Único Universal</title>
		<link>http://bosqueviejo.net/2012/04/26/uuid-identificador-unico-universal/</link>
		<comments>http://bosqueviejo.net/2012/04/26/uuid-identificador-unico-universal/#comments</comments>
		<pubDate>Thu, 26 Apr 2012 05:00:12 +0000</pubDate>
		<dc:creator>bombadil</dc:creator>
				<category><![CDATA[Base de Datos]]></category>
		<category><![CDATA[md5]]></category>
		<category><![CDATA[rfc4122]]></category>
		<category><![CDATA[sha-1]]></category>
		<category><![CDATA[uuid]]></category>

		<guid isPermaLink="false">http://bosqueviejo.net/?p=1333</guid>
		<description><![CDATA[ Últimamente, cada más sistemas, y cada más sitios emplean algo llamado UUID, cuyas siglas vienen a decir: Universally Unique ID; aunque suene algo arrogante, el cálculo de un UUID casi que podríamos decir que garantiza el que sea único. Es más, su grado de colisión es tan bajo que si lo colocásemos como identificador de clave primaria de una tabla que alberga elementos recogidos aleatoriamente de otras tablas de bases de datos de todo el mundo, que hayan empleado este tipo de dato, garantizamos que no habrá repetidos.
Suena excitante, pero&#8230;
¿Cómo funciona esto?
Referenciado en el RFC 4122 del IETF, el UUID se puede definir como un número de 16 bytes (128-bits) que se representa por 32 dígitos hexadecimales, mostrados en cinco grupos separados por guiones:

12345678-abcd-1b3d-a2c4-0123456789ab

Cada uno de los cinco grupos identifica un dato específico para garantizar su carácter único. En principio, se toma el timestamp de la hora actual con precisión de 100 nanosegundos y en formato UTC desde el 15 de octubre de 1582 (la fecha de la reforma gregoriana para el calendario cristiano) de la siguiente forma:

time_low el campo bajo del timestamp, este ocupa los primeros 32 bits.
time_mid el campo medio del timestamp, ocupa los siguientes 16 bits.
time_high [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://bosqueviejo.net/wp-content/uploads/real_id_blanco-150x150.jpg" alt="" title="real_id_blanco" width="150" height="150" class="alignleft size-thumbnail wp-image-1334" /> Últimamente, cada más sistemas, y cada más sitios emplean algo llamado UUID, cuyas siglas vienen a decir: <em>Universally Unique ID</em>; aunque suene algo arrogante, el cálculo de un UUID casi que podríamos decir que garantiza el que sea único. Es más, su grado de colisión es tan bajo que si lo colocásemos como identificador de clave primaria de una tabla que alberga elementos recogidos aleatoriamente de otras tablas de bases de datos de todo el mundo, que hayan empleado este tipo de dato, garantizamos que no habrá repetidos.</p>
<p>Suena excitante, pero&#8230;</p>
<h3>¿Cómo funciona esto?</h3>
<p>Referenciado en el <a href="http://tools.ietf.org/html/rfc4122">RFC 4122</a> del <a href="http://www.ietf.org/" tooltip="Internet Engineering Task Force">IETF</a>, el UUID se puede definir como un número de 16 bytes (128-bits) que se representa por 32 dígitos hexadecimales, mostrados en cinco grupos separados por guiones:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">12345678-abcd-1b3d-a2c4-0123456789ab</pre></div></div>

<p>Cada uno de los cinco grupos identifica un dato específico para garantizar su carácter único. En principio, se toma el timestamp de la hora actual con precisión de 100 nanosegundos y en formato UTC desde el 15 de octubre de 1582 (la fecha de la reforma gregoriana para el calendario cristiano) de la siguiente forma:</p>
<ul>
<li><strong>time_low</strong> el campo bajo del timestamp, este ocupa los primeros 32 bits.</li>
<li><strong>time_mid</strong> el campo medio del timestamp, ocupa los siguientes 16 bits.</li>
<li><strong>time_high</strong> la última parte del timestamp, este no ocupa todo el grupo, sino solo los bits de menor peso, los primeros 12 bits.</li>
</ul>
<p>Para llegar a los primeros 64 bits nos faltan 4, esto es porque estos se emplean para identificar la versión de UUID que se emplea, según el RFC4122, de momento se contemplan 5:</p>
<ol>
<li>Versión basada en tiempo. Especificada en el RFC4122.</li>
<li>Versión de Seguridad DCE con UIDs POSIX embebidos.</li>
<li>Versión basada en nombre que usa MD5 (también se especifica en el RFC4122).</li>
<li>Versión aleatoria o pseudo-aleatoria de generación (también se especifica en el RFC4122).</li>
<li>Versión basada en nombre que usa SHA-1 (también se especifica en el RFC4122).</li>
</ol>
<p>El 4º campo se divide en dos, pero para un mismo concepto, que es la secuencia de reloj. Se escribe con datos de 8 bits especificando el de mayor y menor peso, quedando en este orden almacenados en el cuarto grupo. Aunque el grupo ocupa 16 bits, las versiones 3, 4 y 5 lo emplean como un dato de 14 bits, siendo en las versiones 3 y 5 una secuencia de reloj construida desde un nombre, y en la versión 4 una secuencia de reloj aleatoria o pseudo-aleatoria.</p>
<p>El 5º grupo es denominado <em>el nodo</em>. Ocupa 48 bits. En la versión 1 de UUID este dato se corresponde con la dirección MAC (dirección física de una interfaz de red) definida en el IEEE 802. Para equipos sin interfaz de red, se emplea un dato aleatorio o pseudo-aleatorio. Para las versiones 3 y 5 de UUID, este dato cambio construyéndose a través de una elección de nombre y codificándola con MD5 o SHA-1. Para la versión 4, este dato se construye a través de un número aleatorio o pseudo-aleatorio.</p>
<h3>Conclusiones</h3>
<p>Los UUID son identificadores únicos y muy difíciles de que se produzcan dos iguales dados los parámetros que se emplean para su generación. Al igual que los datos que se emplean para la generación del <em>conference ID</em> de la comunicación de H.323, este dato puede ser empleado como identificador de tablas y estar seguro que, aunque la tabla esté fraccionada y después se mezcle en una, los datos no colisionarán nunca.</p>
]]></content:encoded>
			<wfw:commentRss>http://bosqueviejo.net/2012/04/26/uuid-identificador-unico-universal/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cassandra: la NoSQL de facebook</title>
		<link>http://bosqueviejo.net/2012/04/25/cassandra-la-nosql-de-facebook/</link>
		<comments>http://bosqueviejo.net/2012/04/25/cassandra-la-nosql-de-facebook/#comments</comments>
		<pubDate>Wed, 25 Apr 2012 05:00:42 +0000</pubDate>
		<dc:creator>bombadil</dc:creator>
				<category><![CDATA[Base de Datos]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[cassandra]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[nosql]]></category>

		<guid isPermaLink="false">http://bosqueviejo.net/?p=1328</guid>
		<description><![CDATA[ Tras haber visto Riak un poco más de cerca, ahora le toca el turno a Cassandra. Esta base de datos NoSQL fue desarrollada en el seno de Facebook, como una de sus 7 tecnologías clave. En 2008 fue donada a Apache y desde entonces su popularidad ha ido creciendo cada vez más.
La ventaja de Cassandra es su capacidad de escalar a través de una configuración de anillo en un cluster. La información de la base de datos se distribuye entre todos los nodos configurados y puede ser accedida desde cualquiera de ellos. En este caso, la distribución es muy parecida a Riak, incluso emplean el mismo protocolo para intercomunicación entre nodos: Gossip; además, se requiere de generar un token especial balanceado para la configuración de cada nodo de Cassandra. En esta página hay un código escrito en Python para poder hacer esta tarea.
El acceso a la base de datos se realiza mediante RPC y usando Thrift, que representa otra de las 7 tecnologías clave de Facebook, y también liberada como software libre. Como Thrift es multi-lenguaje, está implementado en muchos de los lenguajes existentes, no hay problemas de implementación, ya sea en Python, Perl, PHP, Java, Erlang, etc.
¿Es NoSQL?
En [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://bosqueviejo.net/wp-content/uploads/cassandra-150x150.jpg" alt="" title="cassandra" width="150" height="150" class="alignleft size-thumbnail wp-image-1329" /> Tras haber visto <a href="/2012/04/24/riak-revisando-y-practicando/">Riak</a> un poco más de cerca, ahora le toca el turno a Cassandra. Esta base de datos NoSQL fue desarrollada en el seno de Facebook, como una de sus <a href="http://alt1040.com/2011/02/7-tecnologias-de-software-que-sostienen-a-facebook">7 tecnologías clave</a>. En 2008 fue donada a Apache y desde entonces su popularidad ha ido creciendo cada vez más.</p>
<p>La ventaja de Cassandra es su capacidad de escalar a través de una configuración de anillo en un cluster. La información de la base de datos se distribuye entre todos los nodos configurados y puede ser accedida desde cualquiera de ellos. En este caso, la distribución es muy parecida a Riak, incluso emplean el mismo protocolo para intercomunicación entre nodos: Gossip; además, se requiere de generar un token especial balanceado para la configuración de cada nodo de Cassandra. En <a href="http://wiki.apache.org/cassandra/GettingStarted">esta página</a> hay un código escrito en Python para poder hacer esta tarea.</p>
<p>El acceso a la base de datos se realiza mediante RPC y usando Thrift, que representa otra de las <a href="http://alt1040.com/2011/02/7-tecnologias-de-software-que-sostienen-a-facebook">7 tecnologías clave</a> de Facebook, y también liberada como software libre. Como Thrift es multi-lenguaje, está implementado en muchos de los lenguajes existentes, no hay problemas de implementación, ya sea en Python, Perl, PHP, Java, Erlang, etc.</p>
<h3>¿Es NoSQL?</h3>
<p>En un principio, usando la base de Thirft y las funciones estándar que podemos ver en cualquier documentación, podríamos decir que sí es <a href="/2010/05/04/nosql/">NoSQL</a>. Nos proveen de funciones para realizar un CRUD básico a través de la inserción, actualización, eliminación y obtención de datos desde la base de datos. No obstante, la búsqueda queda un poco en el aire, ya que para poder buscar por cualquiera de las columnas creadas, hay que prefijar un índice.</p>
<p>Vamos al principio para entenderlo mejor. Haciendo una similitud con el modelo relacional, podemos ver que Cassandra dispone de los siguientes elementos:</p>
<ul>
<li><strong>Keyspace</strong>: debe de crearse un <em>keyspace</em> para almacenar la información y, a la hora de conectar, hay que indicar que <em>keyspace</em> se quiere utilizar. Esto es similar a lo que en las bases de datos tradicionales es la <em>base de datos</em> en sí.</li>
<li><strong>Column Family</strong>: la información se guarda en columnas dentro de la <em>keyspace</em>, pero se agrupan en familias para identificar la separación entre un conjunto de datos y otro. Por lo tanto, dentro de las <em>keyspace</em> debemos de crear <em>column families</em>, lo que en las bases de datos tradicionales serían las <em>tablas</em>.</li>
<li><strong>Columnas</strong>: son cada una de las columnas que se agrupan bajo una familia, que se declaran con un tipo (para validación del dato) y con un nombre. Si se establece un índice sobre la misma, entonces se da la posibilidad de poder buscar utilizándola.</li>
</ul>
<p>Llegados a este punto, vemos diferencias con otras NoSQL, como por ejemplo Riak. Riak tiene <em>buckets</em> donde Cassandra tiene <em>keyspaces</em>. En Riak cada <em>bucket</em> almacena claves a las que se les asigna un valor&#8230; en Cassandra esto no existe, ya que la clave de Cassandra está un nivel más abajo, cuando ya se han definido las familias de columnas. Esto deja a Cassandra entre <em>dos mundos</em>.</p>
<h3>Entre SQL y NoSQL&#8230; CQL</h3>
<p>Para confirmarlo, Cassandra dispone de un lenguaje de consulta que hace posible el empleo del mismo para realizar búsquedas entre sus familias de columnas, sobre las columnas que se hayan definido (con índice, claro). Este lenguaje provee de las órdenes básicas para realizar inserciones, actualizaciones, eliminaciones y obtención de datos.</p>
<p>Es más, el lenguaje en sí es llamado CQL y, viendo su sintaxis se sabe el porqué de la similitud con SQL. Por ejemplo, si tenemos creada la familia de columnas <strong>contactos</strong>, con una columna llamada <strong>nombre</strong>, y otra <strong>telefono</strong>, podemos realizar la siguiente consulta:</p>

<div class="wp_syntax"><div class="code"><pre class="cql" style="font-family:monospace;">SELECT nombre, telefono FROM contactos</pre></div></div>

<p>En las nuevas versiones de Cassandra, además, se puede emplear, en lugar de <tt>cassandra-cli</tt> el nuevo <tt>cqlsh</tt>, que permite emplear los comandos en formato CQL para manejar el cluster y hacer consultas al mismo. Esto hace pensar que Cassandra se comienza a desplazar cada vez más hacia el modelo relacional, dejando el paradigma de clave-valor muy atrás.</p>
<p>No obstante, facilita el acceso a este tipo de base de datos, a sistemas tan potentes, como para mantener un conjunto de máquinas en activo, en un anillo balanceando peticiones y en modo maestro-maestro con cada nodo.</p>
<h3>Conclusiones</h3>
<p>Después de darle bastantes vueltas y emplearlo para un par de desarrollos, he encontrado Cassandra bastante potente para el desarrollo de aplicaciones en las que la información se mantiene estática y se puede capturar de forma fácil a través de sus claves. Es muy rápido dando la información y él mismo balancea entre los nodos que tenga configurado.</p>
<p>Una nota negativa puede ser el hecho de que la búsqueda de información se hace bastante dificultosa debido a que, los datos de las columnas tienen que estar prefijados y muchos datos, en el enlace con Thrift, no funcionan bien. Así mismo, el filtrado por cualquier campo obliga a crear un índice sobre ese campo, lo que conlleva más ocupación de espacio y ralentizar un poco las inserciones, modificaciones y eliminaciones.</p>
<p>En definitiva, es una base de datos con capacidad fácil para montarse en forma de cluster, que permite una rápida ingesta de datos (siempre que tengan un formato prefijado), y una consulta también rápida de los mismos. No es indicado para sistemas en los que las consultas se puedan complicar, ya que requiere en ese caso de la creación de muchos índices e incluso muchas tablas intermedias para no perder la pista de la información. Al final, la mayoría de código hay que ejecutarlo del lado del cliente, por lo que cuanto más difícil sea el esquema de datos, más lento se volverá.</p>
]]></content:encoded>
			<wfw:commentRss>http://bosqueviejo.net/2012/04/25/cassandra-la-nosql-de-facebook/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Riak: revisando y practicando</title>
		<link>http://bosqueviejo.net/2012/04/24/riak-revisando-y-practicando/</link>
		<comments>http://bosqueviejo.net/2012/04/24/riak-revisando-y-practicando/#comments</comments>
		<pubDate>Tue, 24 Apr 2012 12:13:18 +0000</pubDate>
		<dc:creator>bombadil</dc:creator>
				<category><![CDATA[Base de Datos]]></category>
		<category><![CDATA[basho]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[mapreduce]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[riak]]></category>

		<guid isPermaLink="false">http://bosqueviejo.net/?p=1287</guid>
		<description><![CDATA[ Después de la introducción que hice ya hace unos meses sobre la teoría en la que se fundamenta esta base de datos, me he dispuesto a someterla a unas pruebas de funcionamiento, para así aprender a manejar de forma apropiada esta herramienta.
En principio, como revisé solo los conceptos en los que se basa y no el funcionamiento a nivel de usuario, de programador, no sabía si era una interfaz amigable para realizar consultas o búsquedas, y la forma de realizar las cargas, inserciones y demás. Tengo que decir que, al menos el acceso y la comunicación con el servidor resulta muy cómoda y sencilla, ya que se basa en REST.
A través de peticiones HTTP muy sencillas y que se pueden generar incluso desde la línea de comandos con herramientas como curl, podemos realizar peticiones a la base de datos. 
Mensajes hacia Riak
En principio, Riak se basa en REST, esto quiere decir que cada URI especifica un recurso dentro de la base de datos, y sobre ese recurso podemos realizar las acciones HTTP que se relacionan a cualquiera de las acciones básicas de una petición:

GET equivale a tomar datos, sería la R del CRUD (retrieve) o el SELECT del SQL.
PUT [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://bosqueviejo.net/wp-content/uploads/riaklogo1-150x150.png" alt="" title="riaklogo" width="150" height="150" class="alignleft size-thumbnail wp-image-858" /> Después de la <a href="/2011/09/14/riak-base-de-datos-sin-spof/">introducción que hice ya hace unos meses</a> sobre la teoría en la que se fundamenta esta base de datos, me he dispuesto a someterla a unas pruebas de funcionamiento, para así aprender a manejar de forma apropiada esta herramienta.</p>
<p>En principio, como revisé solo los conceptos en los que se basa y no el funcionamiento a nivel de usuario, de programador, no sabía si era una interfaz amigable para realizar consultas o búsquedas, y la forma de realizar las cargas, inserciones y demás. Tengo que decir que, al menos el acceso y la comunicación con el servidor resulta muy cómoda y sencilla, ya que se basa en REST.</p>
<p>A través de peticiones HTTP muy sencillas y que se pueden generar incluso desde la línea de comandos con herramientas como <tt>curl</tt>, podemos realizar peticiones a la base de datos. </p>
<h3>Mensajes hacia Riak</h3>
<p>En principio, Riak se basa en REST, esto quiere decir que cada URI especifica un recurso dentro de la base de datos, y sobre ese recurso podemos realizar las acciones HTTP que se relacionan a cualquiera de las acciones básicas de una petición:</p>
<ul>
<li>GET equivale a tomar datos, sería la R del CRUD (retrieve) o el SELECT del SQL.</li>
<li>PUT equivale a insertar datos nuevos, sería la C del CRUD (create) o el INSERT del SQL.</li>
<li>POST equivale a una modificación o actualización de datos, sería la U del CRUD (update) o el UPDATE de SQL.</li>
<li>DELETE equivale a una eliminación del dato, sería la D (delete) o el DELETE de SQL.</li>
</ul>
<p>Esto permite muchas ventajas, como el uso, en el GET, de la cabecera <em>If-Modified-Since</em>, que nos dará la posibilidad de comprobar si un elemento pesado (imagen, vídeo o similar) es nuevo o no, para volver a descargarlo. Riak nos retornará el objeto con el mensaje 200 para indicar que hay uno nuevo, o solo la cabecera 304 (Not Modified) para indicarnos de que es el mismo que ya tenemos, por lo que no hace falta volver a transmitirlo.</p>
<p>Ante una petición de POST, o una de PUT en el que no exista el registro, se retornará el mensaje 201 (Created), y ante una operación de DELETE, si ha salido bien recibiremos un 204 (No Content) o 404 (Not Found).</p>
<h3>Composición de la URI</h3>
<p>La URI para localizar recursos dentro de Riak se puede establecer como sigue:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">/riak/BUCKET/RESOURCE</pre></div></div>

<p><strong>NOTA</strong>: la palabra clave <em>riak</em> ha sido modificada en nuevas versiones por <em>buckets</em>, pero se mantiene <em>riak</em> por compatibilidad hacia atrás. Por lo que, si estás instalando una versión nueva tomada de la parte de descargas de Riak, puedes usar en lugar de <em>riak</em> la palabra <em>buckets</em>.</p>
<p>Riak configura su URI de modo que la primera palabra clave es precisamente <em>riak</em>, seguida por el <em>bucket</em> donde se almacenarán los recursos que se indique a continuación en la URI. El bucket es un <em>bolsillo</em> en el que se puede almacenar lo que se desee. Además, el <em>bucket</em> se puede configurar a través del paso de algunos parámetros de configuración específicos. Esto se sale un poco del objetivo del artículo, por lo que si tienes curiosidad de lo que se puede configurar puedes echarle un vistazo a <a href="http://wiki.basho.com/HTTP-Set-Bucket-Properties.html">este enlace</a>.</p>
<p>Volviendo al tema, tenemos recursos. Estos recursos son un espacio en el que podemos guardar la información que necesitemos. Puede ser un texto normal, codificado como YAML, como JSON, como XML, o incluso una imagen o un vídeo&#8230; o incluso una imagen ISO (comprobado con una ISO de Sabayon de 700 MB aproximadamente).</p>
<p>Por lo que, podemos probar a hacer algunas prácticas. Lanzamos Riak. Si lo tenemos en ejecución en el puerto 8098 (es el de por defecto cuando se instala el paquete <em>deb</em>), podemos hacer lo siguiente:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">curl -v -X PUT -H &quot;Content-type: image/jpeg&quot; --data-binary @imagen.jpg http://127.0.0.1:8098/riak/pruebas/imagen.jpg</pre></div></div>

<p><strong>Nota</strong>: asegúrate de que la localización de la imagen es correcta, a una imagen de tu disco válida, y no olvidas poner la arroba (@) justo antes de esa ruta (sin espacios).</p>
<p>La comprobación más simple es a través del cualquier navegador que tengas instalado en esa misma máquina:</p>
<p><a href="http://127.0.0.1:8098/riak/pruebas/imagen.jpg">http://127.0.0.1:8098/riak/pruebas/imagen.jpg</a></p>
<p>Con esto ya tendríamos la primera pureba satisfactoria de nuestro sistema de clave-valor para el almacenamiento de datos. Ahora, si lo que queremos es eliminarla, podemos hacerlo así:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">curl -v -X DELETE http://127.0.0.1:8098/riak/pruebas/imagen.jpg</pre></div></div>

<p>Si recargamos el navegador con la URL anterior, veremos que nos responde <tt>not found</tt>.</p>
<h3>Búsquedas en Riak</h3>
<p>En caso de que tengamos información formateada en JSON dentro de cada clave y queramos hacer una búsqueda de esta información para extraer únicamente las claves que nos sean útiles, tendremos que emplear el sistema conocido como <em>map-reduce</em>, para realizar una búsqueda a través de todas las claves de un <em>bucket</em>.</p>
<p>Voy a basarme en lo explicado en la <a href="http://wiki.basho.com/Loading-Data-and-Running-MapReduce-Queries.html">documentación oficial de Riak</a>, para no tener que inventar datos. En principio, si descargamos los dos siguientes ficheros y los ejecutamos:</p>
<ul>
<li><a href="http://wiki.basho.com/attachments/goog.csv">goog.csv</a>, datos a insertar en Riak (en formato CSV).</li>
<li><a href="http://wiki.basho.com/attachments/load_data">load_data</a>, script en Erlang que insertará los datos, convirtiéndolos en un formato JSON. Hay que editar el scirpt y cambiar la URL para que tenga el puerto correcto, en mi caso puse 8098.</li>
</ul>
<p>Esto nos da un <em>bucket</em> bastante grande en el que poder practicar.</p>
<p>Como decíamos antes, vamos a dar un repaso al sistema de MapReduce, el cual fue popularizado por Google. Este se basa en el algoritmo de divide y vencerás, realmente, ya que realiza un lanzamiento sobre cada elemento individual (<em>map</em>) tomando un resultado y, después, la parte de <em>reduce</em>, se encarga de analizar y unificarlo todo en un solo resultado.</p>
<p>Por lo tanto, tenemos que enviar mediante POST, a una URI concreta, un formato JSON de dato que será el siguiente:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;inputs&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;goog&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;query&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span>
    <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;map&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">&quot;language&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;javascript&quot;</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;source&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;function(value, keyData, arg) { var data = Riak.mapValuesJson(value)[0]; if(data.High &amp;&amp; parseFloat(data.High) &gt; 600.00) return [value.key]; else return []; }&quot;</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;keep&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#125;</span></pre></div></div>

<p>Si guardamos esto en un fichero, podemos lanzarlo con el siguiente comando:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">curl -X POST http://127.0.0.1:8098/mapred -H &quot;Content-type: application/json&quot; -d @mapred.json</pre></div></div>

<p>En este caso, la función de <em>map</em> es la siguiente:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>value<span style="color: #339933;">,</span> keyData<span style="color: #339933;">,</span> arg<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> data <span style="color: #339933;">=</span> Riak.<span style="color: #660066;">mapValuesJson</span><span style="color: #009900;">&#40;</span>value<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>data.<span style="color: #660066;">High</span> <span style="color: #339933;">&amp;&amp;</span> data.<span style="color: #660066;">High</span> <span style="color: #339933;">&gt;</span> <span style="color: #CC0000;">600.00</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#91;</span>value.<span style="color: #660066;">key</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">else</span>
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Esto quiere decir que se toma el contenido de cada clave, se parsea con una función especial de Riak para convertir de JSON y retornar la primera línea para que sea almacenada en <tt>data</tt>. Se comprueba que tenga campo <em>High</em> y que <em>High</em> sea mayor de 600.</p>
<p>Es un filtro como se puede hacer con cualquier función <em>map</em> en cualquier lenguaje (que disponga de ella, claro).</p>
<p>Ahora, para emplear tanto <em>map</em>, como <em>reduce</em>, imagina que lo que queremos, de esta información, es econtrar la máxima varianza diaria del precio por mes. Para eso, en el <em>map</em> sacaríamos la varianza diaria, y en el <em>reduce</em> tomaríamos solo la máxima varianza por mes, las funciones serían así:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/* Map calcula la varianza diaria y asigna la clave por mes */</span>
<span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>value<span style="color: #339933;">,</span> keyData<span style="color: #339933;">,</span> arg<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> data <span style="color: #339933;">=</span> Riak.<span style="color: #660066;">mapValuesJson</span><span style="color: #009900;">&#40;</span>value<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
  <span style="color: #003366; font-weight: bold;">var</span> month <span style="color: #339933;">=</span> value.<span style="color: #660066;">key</span>.<span style="color: #660066;">split</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'-'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">slice</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">join</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'-'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #003366; font-weight: bold;">var</span> obj <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
  obj<span style="color: #009900;">&#91;</span>month<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> data.<span style="color: #660066;">High</span> <span style="color: #339933;">-</span> data.<span style="color: #660066;">Low</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#91;</span> obj <span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009966; font-style: italic;">/* Reduce encuentra la varianza máxima por mes */</span>
<span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>values<span style="color: #339933;">,</span> arg<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#91;</span> values.<span style="color: #660066;">reduce</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>acc<span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">item</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
             <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> month <span style="color: #000066; font-weight: bold;">in</span> <span style="color: #000066; font-weight: bold;">item</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
                 <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>acc<span style="color: #009900;">&#91;</span>month<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> acc<span style="color: #009900;">&#91;</span>month<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>acc<span style="color: #009900;">&#91;</span>month<span style="color: #009900;">&#93;</span> <span style="color: #339933;">&lt;</span> <span style="color: #000066; font-weight: bold;">item</span><span style="color: #009900;">&#91;</span>month<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> <span style="color: #000066; font-weight: bold;">item</span><span style="color: #009900;">&#91;</span>month<span style="color: #009900;">&#93;</span> <span style="color: #339933;">:</span> acc<span style="color: #009900;">&#91;</span>month<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
                 <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span> acc<span style="color: #009900;">&#91;</span>month<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">item</span><span style="color: #009900;">&#91;</span>month<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
             <span style="color: #009900;">&#125;</span>
             <span style="color: #000066; font-weight: bold;">return</span> acc<span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
         <span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Codificado para enviarlo en el fichero <tt>mapred.json</tt>, lo anterior quedaría así:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;inputs&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;goog&quot;</span><span style="color: #339933;">,</span>
 <span style="color: #3366CC;">&quot;query&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;map&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;language&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;javascript&quot;</span><span style="color: #339933;">,</span>
                  <span style="color: #3366CC;">&quot;source&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;function(value, keyData, arg){ var data = Riak.mapValuesJson(value)[0]; var month = value.key.split('-').slice(0,2).join('-'); var obj = {}; obj[month] = data.High - data.Low; return [ obj ];}&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
         <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;reduce&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;language&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;javascript&quot;</span><span style="color: #339933;">,</span>
                    <span style="color: #3366CC;">&quot;source&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;function(values, arg){ return [ values.reduce(function(acc, item){ for(var month in item){ if(acc[month]) { acc[month] = (acc[month] &lt; item[month]) ? item[month] : acc[month]; } else { acc[month] = item[month]; } } return acc;  }) ];}&quot;</span><span style="color: #339933;">,</span>
                    <span style="color: #3366CC;">&quot;keep&quot;</span><span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">true</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#125;</span>
         <span style="color: #009900;">&#93;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong>NOTA</strong>: el parámetro <em>keep</em> es el que nos dice qué es lo que se retorna. Si agregamos este mismo parámetro en las dos secciones (<em>map</em> y <em>reduce</em>), nos encontramos que el retorno de la búsqueda es tanto de uno como de otro.</p>
<h3>Otras cosas</h3>
<p>Otra de las cosas que han agregado es la posibilidad de enlazar recursos, de modo que, asignando un enlace y una etiqueta (con el nombre del tipo de enlace), podamos tener relacionado un recurso con otro. Esto da un abanico de posibilidades tan grande como el que se consigue con las bases de datos relacionales, ya que es posible tener en un <em>bucket</em> contactos, en otro datos específicos de un servicio y relacionar el contacto con esos datos agregando una etiqueta al mismo, e incluso que el enlace sea bidireccional agregando las etiquetas en los dos sentidos, cambiando la etiqueta para que sea semántica.</p>
<p>Una imagen de lo que se puede conseguir:</p>
<p><a href="http://bosqueviejo.net/wp-content/uploads/circle-of-friends.png"><img src="http://bosqueviejo.net/wp-content/uploads/circle-of-friends-300x163.png" alt="" title="circle-of-friends" width="300" height="163" class="aligncenter size-medium wp-image-1347" /></a></p>
<p>Las partes de administración (para ajustar las variables del <a href="http://es.wikipedia.org/wiki/Teorema_CAP">teorema CAP</a>) y configuración de otros nodos es algo que dejamos a revisar de la <a href="http://wiki.basho.com/What-is-Riak%3F.html">documentación oficial</a>.</p>
<h3>Conclusiones</h3>
<p>Como puede verse, Riak solventa con su paradigma de NoSQL, basado en el almacenamiento por clave-valor y búsquedas por MapReduce, la mayoría de necesidades que se pueden encontrar a la hora de emplear este tipo de sistemas. Lo único que queda un poco en el aire, o hay que realizar con llamadas sucesivas, son las actualizaciones y eliminaciones masivas, pero realmente, puede ser un mal menor, si estas no son empleadas en el esquema que se vaya a implementar Riak.</p>
<p>Hay que tener presente que Riak es una muy buena base de datos, que fundamenta sus potencias en la posibilidad de contar con un cluster, lecturas rápidas con caché, y búsquedas artificiosas con <em>MapReduce</em>, pero puede haber otros usos en los que las consultas de modificación y eliminación masivas sean lo más importante y esto ya sería mejor abarcarlo con otra base de datos de otro tipo.</p>
]]></content:encoded>
			<wfw:commentRss>http://bosqueviejo.net/2012/04/24/riak-revisando-y-practicando/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>No, Erlang no es eso</title>
		<link>http://bosqueviejo.net/2012/04/18/no-erlang-no-es-eso/</link>
		<comments>http://bosqueviejo.net/2012/04/18/no-erlang-no-es-eso/#comments</comments>
		<pubDate>Wed, 18 Apr 2012 11:45:39 +0000</pubDate>
		<dc:creator>bombadil</dc:creator>
				<category><![CDATA[curiosidades]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[modelo actor]]></category>
		<category><![CDATA[programación concurrente]]></category>
		<category><![CDATA[programación orientada a la concurrencia]]></category>
		<category><![CDATA[programación orientada a objetos]]></category>

		<guid isPermaLink="false">http://bosqueviejo.net/?p=1340</guid>
		<description><![CDATA[ Vale, después de leer varios artículos que llevan a lo mismo, intentar meter la orientación a objetos en Erlang (y como estos otros ejemplos más que no citaré de momento).
Si pensamos lo que Alan Kay decía sobre la orientación a objetos, no se refería a tener un espacio en la memoria en la que albergar datos que pudiesen ser modificados a través de llamadas a funciones. Él definía de manera conceptual la instancia de un objeto, vivo, al que se le pasan mensajes para trabajar con esa información y retornar una respuesta. ¿No es más parecido a lo que se puede hacer con un gen_server, por ejemplo?
También hay gente que intenta hacer que los procesos de Erlang sean más eficientes que los de otros lenguajes y, sino lo son, Erlang no sirve&#8230; cuando, creo que está claro o sino es mejor repasarlo&#8230; que Erlang no destaca por la velocidad de sus procesos, sino por la versatilidad de poder crear millones de ellos e incluso a través de un cluster, de modo que se facilita la computación distribuida, no solo la concurrente.
Entonces, ¿cuál es realmente el fallo de que la gente piense en cosas como orientación a objetos o rendimiento [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://bosqueviejo.net/wp-content/uploads/erlang-150x150.jpg" alt="" title="erlang" width="150" height="150" class="alignleft size-thumbnail wp-image-822" /> Vale, después de leer varios artículos que llevan a lo mismo, intentar meter la <a href="http://ceylan.sourceforge.net/main/documentation/wooper/">orientación a objetos en Erlang</a> (y como estos otros ejemplos más que no citaré de momento).</p>
<p>Si pensamos lo que <a href="http://es.wikipedia.org/wiki/Alan_Kay">Alan Kay</a> decía sobre la orientación a objetos, no se refería a tener un espacio en la memoria en la que albergar datos que pudiesen ser modificados a través de llamadas a funciones. Él definía de manera conceptual la instancia de un objeto, vivo, al que se le pasan mensajes para trabajar con esa información y retornar una respuesta. ¿No es más parecido a lo que se puede hacer con un <tt>gen_server</tt>, por ejemplo?</p>
<p>También hay gente que intenta hacer que los procesos de Erlang sean más eficientes que los de otros lenguajes y, sino lo son, Erlang no sirve&#8230; cuando, creo que está claro o sino es mejor repasarlo&#8230; que Erlang no destaca por la velocidad de sus procesos, sino por la versatilidad de poder crear millones de ellos e incluso a través de un cluster, de modo que se facilita la computación distribuida, no solo la concurrente.</p>
<p>Entonces, ¿cuál es realmente el fallo de que la gente piense en cosas como orientación a objetos o rendimiento de los procesos? &#8230; que no han entendido el cambio de paradigma.</p>
<h3>Programación Orientada a la Concurrencia</h3>
<p>El paradigma que ofrece Erlang, y que está ofreciendo <a href="/2012/04/10/go-el-lenguaje-de-google/">Go</a>, y que se ofrece <a href="/2011/10/06/celluloid-concurrencia-en-ruby/">a través de Celluloid en Ruby</a>, y otros muchos frameworks en otros diversos lenguajes, es lo que se conoce como <a href="http://en.wikipedia.org/wiki/Actor_model">Modelo Actor</a>, o a mi me gusta llamar <strong>Programación orientada a la Concurrencia</strong>.</p>
<p>La programación orientada a la concurrencia se basa en los procesos, que son la unidad mínima de computación para concurrencia en este paradigma. Un proceso se define a través de un módulo y puede ser lanzado una o varias veces, dependiendo de la cantidad de procesos que puedan existir en ejecución para un programa específico.</p>
<p>El proceso es en este paradigma lo que el objeto en el paradigma de la orientación a objetos, teniendo un espacio de memoria (<em>heap</em>) en el que almacena datos privados y que él solo puede manipular, y la posibilidad de recibir mensajes para realizar acciones concretas retornando, o no, un valor. En este sentido, agregamos la posibilidad, porque de concurrencia hablamos, de llamadas síncronas o asíncronas.</p>
<p>Como cada proceso, es una entidad de memoria que almacena datos y que responde a la ejecución de código, se puede especificar con un diagrama de clases UML este diseño, teniendo presente la cardinalidad para la existencia de 1 a N posibles instancias de procesos.</p>
<p>Además, a través de los comportamientos, Erlang nos permite crear entidades avanzadas como supervisores, máquinas de estados y generadores de eventos. Estas entidades facilitan enormemente el trabajo de programación de entidades que antes, en el paradigma de objetos, eran impensables.</p>
<p>Diseñar una web en la que se emplea un controlador a través de una máquina de estados para hacer un sistema <em>statefull</em> que mantiene la sesión en memoria sin necesidad de serializar/deserializar información. Además de, en caso de necesitar enviar información a un log o una inserción demorada (sea cual sea la base de datos), es algo que tan solo se puede hacer a través de programación paralela.</p>
<p>Por otro lado, la optimización. El cómputo del coste algorítmico queda totalmente desfasado, realmente. En un servidor de cuádruple núcleo con dos procesadores (16 en total), un algoritmo que se ejecuta de forma distribuida, además, en dos instancias una en cada servidor como el mencionado, tiene la posibilidad de ejecutarse 32 veces más rápido que un programa escrito de forma secuencial o empleando hilos (que normalmente no emplean varias CPUs).</p>
<h3>¿Ahora sí?</h3>
<p>En esencia. Esto es como cuando salió GTK para PHP, si PHP no está diseñado para estar más de 15 minutos en ejecución (porque se suele bloquear y tiene siempre algún que otro leak de memoria), ¿por qué intentamos introducir orientación a objetos en un lenguaje funcional cuando la metodología más idónea es la orientación a la concurrencia (o el modelo actor)? Acepto comentarios que lo aclaren (si es que esto es posible <img src='http://bosqueviejo.net/wp-includes/images/smilies/icon_biggrin.gif' alt=':-D' class='wp-smiley' />  ).</p>
]]></content:encoded>
			<wfw:commentRss>http://bosqueviejo.net/2012/04/18/no-erlang-no-es-eso/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Go: El lenguaje de Google</title>
		<link>http://bosqueviejo.net/2012/04/10/go-el-lenguaje-de-google/</link>
		<comments>http://bosqueviejo.net/2012/04/10/go-el-lenguaje-de-google/#comments</comments>
		<pubDate>Tue, 10 Apr 2012 17:32:54 +0000</pubDate>
		<dc:creator>bombadil</dc:creator>
				<category><![CDATA[programación]]></category>
		<category><![CDATA[go]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[lenguajes]]></category>

		<guid isPermaLink="false">http://bosqueviejo.net/?p=1314</guid>
		<description><![CDATA[ Hace un par de años que escuché que Google trabajaba en un lenguaje, y hace poco que ya había visto la luz una versión estable, la primera.
Hay personas que me han comentado que Go era parecido a Erlang, que Go hacía concurrencia de forma muy simple, y que Go es un lenguaje muy a tener en cuenta y presente, sobretodo en terreno de concurrencia y escalabilidad. Hoy le he dedicado un par de horas a revisar la documentación y a programar un poco y ver cómo se programa en Go, las potencias que tiene el lenguaje según sus creadores (y lo que han podido introducir a lo largo del tutorial y el manual).
En 2007, un diseño inicial de Go fue comenzado por Robert Griesemer, junto a Rob Pike (creador del lenguaje Limbo) y Ken Thompson (uno de los creadores del lenguaje C y Unix), todos ellos bajo el seno de Google, donde los tres trabajan actualmente, por lo que, de momento, por su historia, promete.
Revisión del lenguaje
En principio, Go es un lenguaje tipado y fuertemente tipado. Tiene auto-detección de tipos para no tener que escribir mucho y han organizado su declaración de modo que resulta un poco extraño para [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://bosqueviejo.net/wp-content/uploads/Go-Mascota-de-Go-Gordon-150x150.jpg" alt="" title="Go-Mascota-de-Go-Gordon" width="150" height="150" class="alignleft size-thumbnail wp-image-1315" /> Hace un par de años que escuché que Google trabajaba en un lenguaje, y hace poco que ya había visto la luz una <a href="http://blog.golang.org/2012/03/go-version-1-is-released.html">versión estable, la primera</a>.</p>
<p>Hay personas que me han comentado que Go era parecido a Erlang, que Go hacía concurrencia de forma muy simple, y que Go es un lenguaje muy a tener en cuenta y presente, sobretodo en terreno de concurrencia y escalabilidad. Hoy le he dedicado un par de horas a revisar la documentación y a programar un poco y ver cómo se programa en Go, las potencias que tiene el lenguaje según sus creadores (y lo que han podido introducir a lo largo del tutorial y el manual).</p>
<p>En 2007, un diseño inicial de Go fue comenzado por Robert Griesemer, junto a Rob Pike (creador del lenguaje Limbo) y Ken Thompson (uno de los creadores del lenguaje C y Unix), todos ellos bajo el seno de Google, donde los tres trabajan actualmente, por lo que, de momento, por su historia, promete.</p>
<h3>Revisión del lenguaje</h3>
<p>En principio, Go es un lenguaje tipado y fuertemente tipado. Tiene auto-detección de tipos para no tener que escribir mucho y han organizado su declaración de modo que resulta un poco extraño para quien haya programado en C y Java, por ejemplo. Mientras que un código en estos lenguajes declara el tipo y modificadores para después indicar el nombre de la variable, Go lo hace al revés. Se indica primero el nombre de las variables y después el tipo. Además, el tipo puede tomarse de forma intrínseca si se hace una inicialización con un valor. Por ejemplo:</p>

<div class="wp_syntax"><div class="code"><pre class="unknown" style="font-family:monospace;">var x int  // declaración simple
var y, z int  // declaración múltiple, ambas serán int
var a := 1  // declaración intrínseca a int
var a, b := 1, 2 // declaración intrínseca de a y b a int</pre></div></div>

<p>En este aspecto, recuerda bastante a Python, pudiendo hacer asignación múltiple en una misma línea. La palabra <tt>var</tt> es necesaria en la declaración de las variables de modo global, y solo opcional dentro de las funciones. Un dato de tipo intrínseco dentro de las funciones, a menos que se emplee <tt>var</tt>, debe de indicarse con el operador :=</p>
<p>La declaración de funciones se realiza con la palabra clave <tt>func</tt>, pudiendo aceptar parámetros tipados de la misma forma que la declaración de variables. El retorno, al igual que la asignación, se realiza de modo que se puedan retornar varios valores, igualmente, otro parecido más a Python en este sentido:</p>

<div class="wp_syntax"><div class="code"><pre class="unknown" style="font-family:monospace;">func add( x, y int ) int {
    return x + y
}</pre></div></div>

<p>En parecido con C, para que el código sea ejecutado, debe de existir una función <em>main</em>.</p>
<p>Como estructuras de control, tenemos <tt>if</tt>, <tt>for</tt> y <tt>switch</tt>. El bucle <em>while</em> se puede simular a través del uso simplificado de <tt>for</tt>, que permite eliminar la parte de inicialización y actualización para realizar son la condición de bucle. Igualmente, si no se indican ninguna de las tres, se realiza un bucle infinito.</p>

<div class="wp_syntax"><div class="code"><pre class="unknown" style="font-family:monospace;">for i := 1; i&lt;10; i++ {
    // bucle for normal
}
&nbsp;
for i &lt; 10 {
    // simulación de while
}
&nbsp;
for {
    // bucle infinito
}</pre></div></div>

<p>Las estructuras <tt>if</tt> permiten el uso de la parte de inicialización, como si se tratase de un bucle <tt>for</tt>, y las estructuras <tt>switch</tt> permiten declarar comparadores, no solo valores estáticos como en Java, C, PHP y otros, además de también el bloque de inicialización como <tt>if</tt>:</p>

<div class="wp_syntax"><div class="code"><pre class="unknown" style="font-family:monospace;">if i == 10 {
    // if normal
}
&nbsp;
if i=10; i==10 {
    // if con inicialización
}
&nbsp;
switch i=10; i {
    case 1: // si es 1
    case 2: // si es 2
    case 10: // aqui entra
    default: // por defecto
}
&nbsp;
switch {
    case i == 1: // si es 1
    case i == 2: // si es 2
    case i &gt; 3: // aqui entra
    default: // por defecto
}</pre></div></div>

<p>La organización de las estructuras de datos se puede hacer mediante <tt>struct</tt>, al igual que en C, e incluso se pueden definir funciones que trabajen como si uno de sus parámetros intrínsecos fuese un <tt>struct</tt>. Con esto se puede simular el uso de los métodos, pero queda muy lejos de lo que respecta a la programación orientada a objetos.</p>
<p>Se pueden ver más ejemplos en <a href="http://tour.golang.org/">tutorial de Go (en inglés)</a>.</p>
<h3>Potencias del lenguaje</h3>
<p>Revisándolo a fondo, veo que la tendencia de los lenguajes de tipado estático comienza a estar de moda, tienen sus ventajas ya que permiten cazar fallos en tiempo de compilación (cuando no hay inferencia de tipos, claro). En este caso esa cualidad es bastante evidente, así como que el código pueda compilarse de forma nativa como hace también Opa.</p>
<p>La concurrencia que emplea Go se parece bastante a Erlang en base en que es por paso de mensajes. La única diferencia radica en que el buzón para el paso de mensajes se debe de crear. Go nomina sus buzones como canales de comunicación. Un símil muy aproximado a los sockets Unix, ya que se establecen como recursos independientes y se pueden emplear en cualquier proceso y en cualquier momento.</p>
<h3>Conclusiones</h3>
<p>El lenguaje Go es un lenguaje que ha nacido con un propósito claro, según sus objetivos entre los que se encuentran: seguridad (de tipos y de memoria), buen soporte de concurrencia y comunicación, eficiencia en la recolección de basura (sin latencias) y alta velocidad de compilación.</p>
<p>Viniendo de dos de los trabajadores de los laboratorios Bell que contribuyeron a lenguajes como Limbo, C, BPEL, etc. y estando en el seno de Google, el futuro de este lenguaje se ve muy prometedor.</p>
<p>Este lenguaje permite la programación orientada a la concurrencia o modelo actor, con lo que, la orientación a objetos, realmente, no es una característica que se eche en falta, ni mucho menos, siempre teniendo presente que el paradigma de programación al que se orienta no son los objetos, en su núcleo central, sino los procesos (o hilos).</p>
<p>Cabe destacar que el uso de la memoria compartida es un hecho ya que el comando <tt>go</tt> lo que hace es lanzar, como dice el tutorial <em>goroutines</em>, que a nivel interno son hilos, por lo que comparte el mismo <em>heap</em> de memoria y puede llegar a ser un problema en el uso de la concurrencia y el modelo actor propiamente dicho.</p>
<p>Por otro lado, carece de estructuras que faciliten el uso de monitores de hilos a modo de que cuando uno muera se notifique este hecho a otro y poder construir estructuras como las de los supervisores.</p>
<p>Veremos como va progresando a lo largo de las siguientes liberaciones, de momento son buenos pasos los que ha dado el pequeño, y con la promesa de Google de mantener la sintaxis y compatibilidad en sus futuras versiones, es una seguridad de cara a programar y no tener que refactorizar al cambiar a una nueva versión.</p>
]]></content:encoded>
			<wfw:commentRss>http://bosqueviejo.net/2012/04/10/go-el-lenguaje-de-google/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Erlang: Servidores Concurrentes TCP</title>
		<link>http://bosqueviejo.net/2012/04/09/erlang-servidores-concurrentes-tcp/</link>
		<comments>http://bosqueviejo.net/2012/04/09/erlang-servidores-concurrentes-tcp/#comments</comments>
		<pubDate>Mon, 09 Apr 2012 10:43:10 +0000</pubDate>
		<dc:creator>bombadil</dc:creator>
				<category><![CDATA[programación]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[gen_server]]></category>
		<category><![CDATA[gen_tcp]]></category>
		<category><![CDATA[otp]]></category>
		<category><![CDATA[programación concurrente]]></category>

		<guid isPermaLink="false">http://bosqueviejo.net/?p=1270</guid>
		<description><![CDATA[ Para la programación de elementos que requieran concurrencia, Erlang, es una de las mejores elecciones que se puede tomar. El hecho de construir servidores UDP con los mecanismos que nos ofrece OTP es algo trivial, muy simple de conseguir, tal y como se puede ver en este otro artículo, pero la cosa se complica, cuando lo que queremos obtener es una conexión, o un conjunto de conexiones concurrentes para TCP.
Para comenzar, vamos a poner de nuevo de manifiesto la plantilla del gen_server, si se quieren tener más referencias sobre el gen_server se puede consultar este otro artículo, o de forma más extensa en este artículo del Blog Aprendiendo Erlang.
Por lo tanto, la estructura de un código con gen_server es la siguiente:

-module&#40;server&#41;.
-author&#40;'bombadil@bosqueviejo.net'&#41;.
&#160;
-behaviour&#40;gen_server&#41;.
&#160;
-define&#40;SERVER, ?MODULE&#41;.
&#160;
-export&#40;&#91;start_link/0&#93;&#41;.
-export&#40;&#91;init/1, handle_call/3, handle_cast/2, handle_info/2,
         terminate/2, code_change/3&#93;&#41;.
&#160;
-record&#40;state, &#123;&#125;&#41;.
&#160;
start_link&#40;&#41; -&#62;
    gen_server:start_link&#40;&#123;local, ?SERVER&#125;, ?MODULE, &#91;&#93;, &#91;&#93;&#41;.
&#160;
init&#40;&#91;&#93;&#41; -&#62;
    &#123;ok, #state&#123;&#125;&#125;.
&#160;
handle_call&#40;_Request, _From, State&#41; -&#62;
    Reply = ok,
    &#123;reply, Reply, State&#125;.
&#160;
handle_cast&#40;_Msg, State&#41; -&#62;
    &#123;noreply, State&#125;.
&#160;
handle_info&#40;_Info, State&#41; -&#62;
    &#123;noreply, State&#125;.
&#160;
terminate&#40;_Reason, _State&#41; -&#62;
    ok.
&#160;
code_change&#40;_OldVsn, State, _Extra&#41; -&#62;
    &#123;ok, State&#125;.

Agregando conexiones TCP
TCP, a diferencia de [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://bosqueviejo.net/wp-content/uploads/telefonistas-150x150.jpg" alt="" title="telefonistas" width="150" height="150" class="alignleft size-thumbnail wp-image-1304" /> Para la programación de elementos que requieran concurrencia, Erlang, es una de las mejores elecciones que se puede tomar. El hecho de construir servidores UDP con los mecanismos que nos ofrece OTP es algo trivial, muy simple de conseguir, tal y como se puede ver en <a href="/2012/03/21/erlang-servidores-udp/">este otro artículo</a>, pero la cosa se complica, cuando lo que queremos obtener es una conexión, o un conjunto de conexiones concurrentes para TCP.</p>
<p>Para comenzar, vamos a poner de nuevo de manifiesto la plantilla del <tt>gen_server</tt>, si se quieren tener más referencias sobre el <tt>gen_server</tt> se puede consultar <a href="/2012/03/21/erlang-servidores-udp/">este otro artículo</a>, o de forma más extensa en <a href="http://aprendiendo-erlang.blogspot.com.es/2011/11/genserver-servidor-generico.html">este artículo del Blog Aprendiendo Erlang</a>.</p>
<p>Por lo tanto, la estructura de un código con <tt>gen_server</tt> es la siguiente:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #014ea4;">-</span><span style="color: #5400b3;">module</span><span style="color: #109ab8;">&#40;</span>server<span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">author</span><span style="color: #109ab8;">&#40;</span><span style="">'bombadil@bosqueviejo.net'</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">behaviour</span><span style="color: #109ab8;">&#40;</span>gen_server<span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">define</span><span style="color: #109ab8;">&#40;</span><span style="color: #6941fd;">SERVER</span><span style="color: #6bb810;">,</span> ?<span style="color: #6941fd;">MODULE</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">export</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span>start_link<span style="color: #014ea4;">/</span><span style="color: #ff9600;">0</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">export</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span>init<span style="color: #014ea4;">/</span><span style="color: #ff9600;">1</span><span style="color: #6bb810;">,</span> handle_call<span style="color: #014ea4;">/</span><span style="color: #ff9600;">3</span><span style="color: #6bb810;">,</span> handle_cast<span style="color: #014ea4;">/</span><span style="color: #ff9600;">2</span><span style="color: #6bb810;">,</span> handle_info<span style="color: #014ea4;">/</span><span style="color: #ff9600;">2</span><span style="color: #6bb810;">,</span>
         terminate<span style="color: #014ea4;">/</span><span style="color: #ff9600;">2</span><span style="color: #6bb810;">,</span> code_change<span style="color: #014ea4;">/</span><span style="color: #ff9600;">3</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">record</span><span style="color: #109ab8;">&#40;</span><span style="color: #d400ed;">state</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
start_<span style="color: #fa6fff;">link</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #ff4e18;">gen_server</span>:<span style="color: #006600;">start_</span><span style="color: #fa6fff;">link</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>local<span style="color: #6bb810;">,</span> ?<span style="color: #6941fd;">SERVER</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> ?<span style="color: #6941fd;">MODULE</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">init</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">handle_call</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">_Request</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_From</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #45b3e6;">Reply</span> <span style="color: #014ea4;">=</span> ok<span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>reply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Reply</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">handle_cast</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">_Msg</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">handle_info</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">_Info</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">terminate</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">_Reason</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #006600;">ok</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">code_change</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">_OldVsn</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_Extra</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span></pre></div></div>

<h3>Agregando conexiones TCP</h3>
<p>TCP, a diferencia de UDP, necesita formalizar que está escuchando en un nodo, y aceptar cada petición entrante para mantener una comunicación bilateral. En este caso, el <tt>init</tt> se complica. Debemos de establecer la escucha del puerto y esto requiere de que pasemos algunos parámetro y opciones:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #014ea4;">-</span><span style="color: #5400b3;">record</span><span style="color: #109ab8;">&#40;</span><span style="color: #d400ed;">state</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>lsocket<span style="color: #6bb810;">,</span> socket<span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">init</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #45b3e6;">Opts</span> <span style="color: #014ea4;">=</span> <span style="color: #109ab8;">&#91;</span><span style="color: #fa6fff;">binary</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>packet<span style="color: #6bb810;">,</span> <span style="color: #ff9600;">0</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>active<span style="color: #6bb810;">,</span> true<span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span>
    <span style="color: #186895;">case</span> <span style="color: #ff4e18;">gen_tcp</span>:<span style="color: #ff3c00;">listen</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff9600;">5000</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Opts</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
        <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">LSocket</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span>
            <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>lsocket <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">LSocket</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #ff9600;">0</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Reason</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span>
            <span style="color: #109ab8;">&#123;</span>stop<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Reason</span><span style="color: #109ab8;">&#125;</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>Para esto, tendremos que agregar el parámetro <tt>lsocket</tt> y <tt>socket</tt> al registro de estado.</p>
<p>La función <tt>init</tt> se encarga de establecer la escucha en el puerto 5000, de forma activa. Para más opciones se puede revisar tanto la documentación de <a href="http://www.erlang.org/doc/man/gen_tcp.html">gen_tcp</a>, como las opciones específicas disponibles en el paquete <a href="http://www.erlang.org/doc/man/inet.html#setopts-2">inet a través de setops</a>.</p>
<p>Como se puede ver, en caso de que la escucha se establezca de forma apropiada, hay un <tt>timeout</tt> configurado a cero, por lo que, se llamará al <em>callback</em> de <tt>handle_info</tt>, con el parámetro <tt>timeout</tt>. En ese punto, es donde tenemos que agregar la parte del servidor TCP en la que se espera por una conexión entrante para poder atenderla. La función, por tanto, sería:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_info</span><span style="color: #109ab8;">&#40;</span>timeout<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #014ea4;">=</span>#<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>lsocket<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">LSocket</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Socket</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">gen_tcp</span>:<span style="color: #ff3c00;">accept</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">LSocket</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>socket<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Socket</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
&nbsp;
<span style="color: #ff3c00;">handle_info</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Info</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #014ea4;">=</span>#<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>socket<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Socket</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #ff4e18;">io</span>:<span style="color: #ff3c00;">format</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;~p~n&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Info</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #ff4e18;">gen_tcp</span>:<span style="color: #ff3c00;">send</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Socket</span><span style="color: #6bb810;">,</span> <span style="color: #ff4e18;">io_lib</span>:<span style="color: #ff3c00;">format</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;~p~n&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#123;</span><span style="color: #fa6fff;">date</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span><span style="color: #fa6fff;">time</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #ff4e18;">gen_tcp</span>:<span style="color: #ff3c00;">close</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Socket</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #6bb810;">,</span> <span style="color: #ff9600;">0</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>El programa es algo simple, ya que acepta la conexión, espera una transmisión y responde enviando la fecha y hora y cierra la conexión. Podemos probarlo de la siguiente forma:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ nc localhost 5000
hola
{{2012,4,4},{20,5,49}}</pre></div></div>

<h3>Y ahora&#8230; la concurrencia</h3>
<p>Como puedes observar, mientras tienes abierta la primera conexión, la segunda no se establece porque el sistema está ocupado con la primera petición. Esto conlleva un cuello de botella, ya que la concurrencia es nula.</p>
<p>Para conseguir ampliar la concurrencia, desde el primer servidor, el proceso que tiene en escucha el puerto, debe de lanzar un proceso, un nuevo servidor para atender cada petición de forma independiente.</p>
<p>Para esto necesitamos crear otro nuevo <em>gen_server</em>, pero con unas características diferentes, ya que no se mantendrá a la espera de conexiones entrantes, sino que será para manejar una conexión activa.</p>
<p>El módulo <tt>gen_tcp</tt> nos ayuda en esta tarea, ya que cada mensaje entrante lo recibimos a través de <tt>handle_info</tt> en el proceso padre, como habíamos visto antes, y esto debemos de redireccionarlo hacia el proceso hijo que creemos. En principio, copiando la estructura de <tt>gen_server</tt> de nuevo y llamándola <tt>request</tt>, agregamos un par de cambios como el siguiente:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;">start_<span style="color: #fa6fff;">link</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Socket</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Pid</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">gen_server</span>:<span style="color: #006600;">start_</span><span style="color: #fa6fff;">link</span><span style="color: #109ab8;">&#40;</span>?<span style="color: #6941fd;">MODULE</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Socket</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #ff4e18;">gen_tcp</span>:<span style="color: #006600;">controlling_</span><span style="color: #fa6fff;">process</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Socket</span><span style="color: #6bb810;">,</span><span style="color: #45b3e6;">Pid</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #ff4e18;">inet</span>:<span style="color: #ff3c00;">setopts</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Socket</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#123;</span>active<span style="color: #6bb810;">,</span> once<span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Pid</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>Esta forma de lanzar el <tt>gen_server</tt>, hace que el proceso no tenga un nombre asociado, por lo que se pueden lanzar tantos como queramos o necesitemos. Para el <tt>gen_tcp</tt>, indicamos que el proceso que atenderá las peticiones de ese socket será el que se acaba de crear, y se le indica que puede enviar una petición.</p>
<p>La función de inicialización tendrá esta forma:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #014ea4;">-</span><span style="color: #5400b3;">record</span><span style="color: #109ab8;">&#40;</span><span style="color: #d400ed;">state</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>socket<span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">init</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Socket</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>socket<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Socket</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>En el módulo <tt>server</tt> podemos eliminar la parte de gestión de la petición (la parte de <tt>handle_info</tt> que se refiere estrictamente a la gestión de la petición) y dejar solo la parte de la aceptación de la petición de esta forma:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_info</span><span style="color: #109ab8;">&#40;</span>timeout<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #014ea4;">=</span>#<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>lsocket<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">LSocket</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Socket</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">gen_tcp</span>:<span style="color: #ff3c00;">accept</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">LSocket</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    request:<span style="color: #006600;">start_</span><span style="color: #fa6fff;">link</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Socket</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #6bb810;">,</span> <span style="color: #ff9600;">0</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>En el nuevo módulo <tt>request</tt>, agregamos la parte de código que se encarga de realizar la contestación:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_info</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Info</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #014ea4;">=</span>#<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>socket<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Socket</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #ff4e18;">io</span>:<span style="color: #ff3c00;">format</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;~p~n&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Info</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #ff4e18;">gen_tcp</span>:<span style="color: #ff3c00;">send</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Socket</span><span style="color: #6bb810;">,</span> <span style="color: #ff4e18;">io_lib</span>:<span style="color: #ff3c00;">format</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;~p~n&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#123;</span><span style="color: #fa6fff;">date</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span><span style="color: #fa6fff;">time</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #ff4e18;">gen_tcp</span>:<span style="color: #ff3c00;">close</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Socket</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>stop<span style="color: #6bb810;">,</span> normal<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>En este caso, cuando <tt>gen_tcp</tt> envía un mensaje desde el cliente al servidor, este mensaje disparará la ejecución de esta función, imprimirá por pantalla el mensaje recibido, contestará de forma fija con la fecha y hora actual, cerrará la conexión con el cliente y detendrá la ejecución del proceso.</p>
<h3>Algunas pruebas</h3>
<p>Si ejecutamos en una máquina virtual de Erlang el servidor, y abrimos dos consolas o tres o más con el siguiente comando:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ nc localhost 5000</pre></div></div>

<p>Veremos que todas y cada una de las consolas obtienen conexión y quedan en el proceso hijo a la espera de un mensaje que envíes. Puedes poner el texto que quieras y presionar el retorno de carro. Volviendo a la consola de Erlang, se verá el mensaje escrito en cada una de las consolas.</p>
<p>Si modificamos el código para que acepte paquetes de tipo <em>http</em> y procesamos una respuesta válida, podemos probar la carga a través de programas como <a href="https://github.com/wg/wrk">wrk</a> o <a href="">ab</a>. En mis pruebas, he conseguido:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ ab -n 10000 -c 50 http://127.0.0.1:5000/
[...]
Concurrency Level:      50
Time taken for tests:   0.885 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      760000 bytes
HTML transferred:       110000 bytes
Requests per second:    11303.38 [#/sec] (mean)
Time per request:       4.423 [ms] (mean)
Time per request:       0.088 [ms] (mean, across all concurrent requests)
Transfer rate:          838.92 [Kbytes/sec] received</pre></div></div>

<p>Una tasa de unas 11 mil peticiones por segundo. Nada mal.</p>
]]></content:encoded>
			<wfw:commentRss>http://bosqueviejo.net/2012/04/09/erlang-servidores-concurrentes-tcp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Clean Code: para ser mejor programador</title>
		<link>http://bosqueviejo.net/2012/04/03/clean-code-para-ser-mejor-programador/</link>
		<comments>http://bosqueviejo.net/2012/04/03/clean-code-para-ser-mejor-programador/#comments</comments>
		<pubDate>Tue, 03 Apr 2012 08:21:51 +0000</pubDate>
		<dc:creator>bombadil</dc:creator>
				<category><![CDATA[Libros]]></category>
		<category><![CDATA[bjarne stroustrup]]></category>
		<category><![CDATA[clean code]]></category>
		<category><![CDATA[robert c martin]]></category>

		<guid isPermaLink="false">http://bosqueviejo.net/?p=1294</guid>
		<description><![CDATA[ Dando un repaso a mi biblioteca he vuelto a topar con un libro que me llamó la atención antaño, leí aunque muy por encima y, hoy dándole otro repaso he pensado, ¡qué razón tiene!
El libro se llama Clean Code es de Robert C. Martin, e intenta arrojar un poco de luz sobre el hecho de programar mejor, o como su título indica, hacer el código más claro, más limpio.
Una de las frases iniciales es (al pie de la imagen que he empleado para este artículo): Estás leyendo este libro por dos motivos. El primero es que eres programador. El segundo, quieres ser mejor programador. Hace mención a la clave de todo buen programa: que sea pequeño; algo que la filosofía de Unix nos dejó claro en su enunciado: hacer programas que solo hagan una cosa, pero que la hagan muy bien.
También comenta un problema que surgió, una experiencia personal, en la que desarrollaron una killer app, que todo el mundo quería, se vendió muy bien y comenzó a crecer, más características, pero también más fallos. El crecimiento fue descontrolado y el código empezó a ser cada vez peor. Esto llevó a la empresa a la quiebra.
En este sentido, podemos [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://bosqueviejo.net/wp-content/uploads/Chapter1CleanCode-150x150.gif" alt="" title="Chapter1CleanCode" width="150" height="150" class="alignleft size-thumbnail wp-image-1295" /> Dando un repaso a mi biblioteca he vuelto a topar con un libro que me llamó la atención antaño, leí aunque muy por encima y, hoy dándole otro repaso he pensado, ¡qué razón tiene!</p>
<p>El libro se llama <strong>Clean Code</strong> es de Robert C. Martin, e intenta arrojar un poco de luz sobre el hecho de programar mejor, o como su título indica, hacer el código más claro, más limpio.</p>
<p>Una de las frases iniciales es (al pie de la imagen que he empleado para este artículo): <em>Estás leyendo este libro por dos motivos. El primero es que eres programador. El segundo, quieres ser mejor programador.</em> Hace mención a la clave de todo buen programa: <em>que sea pequeño</em>; algo que la filosofía de Unix nos dejó claro en su enunciado: <em>hacer programas que solo hagan una cosa, pero que la hagan muy bien</em>.</p>
<p>También comenta un problema que surgió, una experiencia personal, en la que desarrollaron una <em>killer app</em>, que todo el mundo quería, se vendió muy bien y comenzó a crecer, más características, pero también más fallos. El crecimiento fue descontrolado y el código empezó a ser cada vez peor. Esto llevó a la empresa a la quiebra.</p>
<p>En este sentido, podemos incluso ver un gráfico de productividad frente a tiempo cuando el código es desordenado y malo:</p>
<p><img src="http://bosqueviejo.net/wp-content/uploads/productivity_vs_time-300x140.png" alt="" title="productivity_vs_time" width="300" height="140" class="aligncenter size-medium wp-image-1296" /></p>
<p>Cuanto más aumenta el tiempo de desarrollo del software, más cuesta agregar nuevas funcionalidades.</p>
<p>Seguro que ahora se nos vendrán a la cabeza muchos casos vividos acerca de este hecho, muchas vivencias incluso, código heredado que hemos tenido que mantener, reescribir e incluso nuestro propio código después, haberlo tenido que reescribir igualmente porque, erróneamente, seguimos los principios equivocados.</p>
<p>Las claves para escribir buen código, o código limpio y claro, se relatan en este libro, el cual se hace bastante ameno y en algunos puntos bastante divertido, e incluso revelador. Podemos citar algunos de esos puntos, aunque en modo esquemático:</p>
<ul>
<li>Cuestión de <strong>actitud</strong>, obviamente, si consideras que el código bien hecho es inviable para tu día a día, ese el primer punto que deberías de cambiar, ya que no te estás dando cuenta de que, cuanto más barro echas encima, más lento te desplazas.</li>
<li><strong>Refactorizar</strong> debe de ser una tarea cotidiana o al menos parte del desarrollo de una nueva característica, ya que cuando se introduce nuevo código, cambios o correcciones, muchas veces conviene dar un repaso a todo el código y rehacer algunas partes que puedan no tener sentido&#8230; o incluso borrar otras que ya no se usen, para no dificultar la lectura de código que está <em>muerto</em>.</li>
</ul>
<p>Como decía Bjarne Stroustrup: <em>Me gusta que mi código sea elegante y eficiente. La lógica debe ser directa, clara, para que a los fallos les sea difícil esconderse, las dependencias mínimas para facilitar el mantenimiento, el manejo de errores completo acorde a una estrategia planificada y el rendimiento muy próximo a óptimo para no tentar a la gente a hacer código desordenado con optimizaciones sin base alguna. El código limpio y claro hace las cosas bien.</em></p>
<p>Hay más comentarios de Grady Booch, Dave Thomas, Michael Feathers, Ron Jeffries y Ward Cunningham. Todos ellos comentando y/o definiendo lo que significa, para ellos, el código limpio.</p>
<p>El libro es muy recomendable, por su contenido, por sus enseñanzas y por ver la forma de progresar y hacer código que tenga un tiempo de mantenimiento mayor, es decir, que sea fácil de mantener, extender y corregir.</p>
]]></content:encoded>
			<wfw:commentRss>http://bosqueviejo.net/2012/04/03/clean-code-para-ser-mejor-programador/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Erlang: Servidores UDP</title>
		<link>http://bosqueviejo.net/2012/03/21/erlang-servidores-udp/</link>
		<comments>http://bosqueviejo.net/2012/03/21/erlang-servidores-udp/#comments</comments>
		<pubDate>Wed, 21 Mar 2012 10:03:23 +0000</pubDate>
		<dc:creator>bombadil</dc:creator>
				<category><![CDATA[programación]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[netcat]]></category>
		<category><![CDATA[otp]]></category>
		<category><![CDATA[programación concurrente]]></category>
		<category><![CDATA[udp]]></category>

		<guid isPermaLink="false">http://bosqueviejo.net/?p=1274</guid>
		<description><![CDATA[ Una de las grandes potencias de Erlang es su capacidad para construir servidores. A través de OTP, esta tarea se convierte en algo tan sencillo, que asombra ver con qué pocas líneas de código se crea un servidor.
En este caso vamos a montar un servidor UDP. Esto lo revisé en su día porque estuve realizando un pequeño servidor para el protocolo syslog, de lo que resultó este servidor, que permite pasar a través de un manejador de eventos (gen_event) los mensajes de syslog recibidos a través del puerto 514 en formato UDP.
En principio, comentaré un poco la estructura del comportamiento (behaviour) de Erlang/OTP que emplearemos: gen_server.
Empleando los gen_server
El gen_server es el comportamiento más básico que se encuentra disponible en OTP, ya que sobre él se construyen otros como gen_fsm. Este comportamiento específico se fundamenta en la recepción de mensajes y su manejo a través de unos callbacks, de modo que tenemos tres tipos de mensajes que podemos procesar:

call: referidos a llamadas en las que se envía una petición y se espera por una respuesta del servidor. Siendo realizadas desde otros procesos de Erlang.
cast: estas son llamadas que se envían y no se espera por una respuesta. También son realizadas [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://bosqueviejo.net/wp-content/uploads/cables-150x150.jpg" alt="" title="cables" width="150" height="150" class="alignleft size-thumbnail wp-image-1276" /> Una de las grandes potencias de Erlang es su capacidad para construir servidores. A través de OTP, esta tarea se convierte en algo tan sencillo, que asombra ver con qué pocas líneas de código se crea un servidor.</p>
<p>En este caso vamos a montar un servidor UDP. Esto lo revisé en su día porque estuve realizando un pequeño servidor para el protocolo <em>syslog</em>, de lo que resultó este servidor, que permite pasar a través de un manejador de eventos (gen_event) los mensajes de syslog recibidos a través del puerto 514 en formato UDP.</p>
<p>En principio, comentaré un poco la estructura del comportamiento (<em>behaviour</em>) de Erlang/OTP que emplearemos: <em>gen_server</em>.</p>
<h3>Empleando los <em>gen_server</em></h3>
<p>El <em>gen_server</em> es el comportamiento más básico que se encuentra disponible en OTP, ya que sobre él se construyen otros como <em>gen_fsm</em>. Este comportamiento específico se fundamenta en la recepción de mensajes y su manejo a través de unos callbacks, de modo que tenemos tres tipos de mensajes que podemos procesar:</p>
<ul>
<li><strong>call</strong>: referidos a llamadas en las que se envía una petición y se espera por una respuesta del servidor. Siendo realizadas desde otros procesos de Erlang.</li>
<li><strong>cast</strong>: estas son llamadas que se envían y no se espera por una respuesta. También son realizadas desde otros procesos de Erlang.</li>
<li><strong>info</strong>: este podría considerarse un comodín, ya que en esta categoría entran todos los mensajes que no entran en las anteriores. Normalmente, aquí es donde recibiremos la información UDP y TCP de los servidores que creemos de cara a la red.</li>
</ul>
<p>La estructura de un código con <tt>gen_server</tt> es la siguiente:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #014ea4;">-</span><span style="color: #5400b3;">module</span><span style="color: #109ab8;">&#40;</span>server<span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">author</span><span style="color: #109ab8;">&#40;</span><span style="">'bombadil@bosqueviejo.net'</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">behaviour</span><span style="color: #109ab8;">&#40;</span>gen_server<span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">define</span><span style="color: #109ab8;">&#40;</span><span style="color: #6941fd;">SERVER</span><span style="color: #6bb810;">,</span> ?<span style="color: #6941fd;">MODULE</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">export</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span>start_link<span style="color: #014ea4;">/</span><span style="color: #ff9600;">0</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">export</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span>init<span style="color: #014ea4;">/</span><span style="color: #ff9600;">1</span><span style="color: #6bb810;">,</span> handle_call<span style="color: #014ea4;">/</span><span style="color: #ff9600;">3</span><span style="color: #6bb810;">,</span> handle_cast<span style="color: #014ea4;">/</span><span style="color: #ff9600;">2</span><span style="color: #6bb810;">,</span> handle_info<span style="color: #014ea4;">/</span><span style="color: #ff9600;">2</span><span style="color: #6bb810;">,</span>
         terminate<span style="color: #014ea4;">/</span><span style="color: #ff9600;">2</span><span style="color: #6bb810;">,</span> code_change<span style="color: #014ea4;">/</span><span style="color: #ff9600;">3</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">record</span><span style="color: #109ab8;">&#40;</span><span style="color: #d400ed;">state</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
start_<span style="color: #fa6fff;">link</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #ff4e18;">gen_server</span>:<span style="color: #006600;">start_</span><span style="color: #fa6fff;">link</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>local<span style="color: #6bb810;">,</span> ?<span style="color: #6941fd;">SERVER</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> ?<span style="color: #6941fd;">MODULE</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">init</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">handle_call</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">_Request</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_From</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #45b3e6;">Reply</span> <span style="color: #014ea4;">=</span> ok<span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>reply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Reply</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">handle_cast</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">_Msg</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">handle_info</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">_Info</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">terminate</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">_Reason</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #006600;">ok</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">code_change</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">_OldVsn</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_Extra</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>Si guardamos esta estructura como <tt>server.erl</tt> (que es el nombre del módulo, tal y como se indica en la primera línea), el sistema compilará y lo podremos incluso lanzar con el comando:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;">server:<span style="color: #006600;">start_</span><span style="color: #fa6fff;">link</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></pre></div></div>

<h3>Convirtiendo nuestro <em>gen_server</em> en servidor UDP</h3>
<p>Para convertir nuestro <tt>gen_server</tt> en un servidor UDP solo necesitamos abrir en escucha el puerto que queramos en modo UDP a través de <tt>gen_udp</tt> y el resto lo hará la estructura <tt>gen_server</tt>. Sería tan simple como modificar la función <tt>init</tt> para que albergase el siguiente código:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">init</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #45b3e6;">Port</span> <span style="color: #014ea4;">=</span> <span style="color: #ff9600;">5000</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Socket</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">gen_udp</span>:<span style="color: #ff3c00;">open</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Port</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #ff4e18;">error_logger</span>:<span style="color: #ff3c00;">info_msg</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;Listen in port ~p~n&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Port</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>socket<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Socket</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>Y también la estructura del registro de estado, para albergar la información que necesitamos almacenar en el proceso, que será el recurso del puerto abierto:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #014ea4;">-</span><span style="color: #5400b3;">record</span><span style="color: #109ab8;">&#40;</span><span style="color: #d400ed;">state</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>socket<span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>Es bueno que, además, agregemos en el <tt>terminate</tt> la cláusula que nos permita cerrar el servidor UDP, esto lo podemos agregar modificando la función <tt>termiante</tt> de la siguiente forma:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">terminate</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">_Reason</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #ff4e18;">gen_udp</span>:<span style="color: #ff3c00;">close</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">State</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">state</span><span style="color: #6bb810;">.</span>socket<span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    ok<span style="color: #6bb810;">.</span></pre></div></div>

<p>Por último, vamos a hacer que cada mensaje que nos llegue desde el servidor UDP se presente a modo de log en la consola. Esto lo haremos modificando la función <tt>handle_info</tt>, que como habíamos visto antes, es la que recibe los mensajes UDP:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_info</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Info</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #ff4e18;">error_logger</span>:<span style="color: #ff3c00;">info_msg</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;Received via INFO: ~p~n&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Info</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span></pre></div></div>

<h3>Probando el servidor</h3>
<p>Para probarlo, solo tenemos que ejecutar en una consola:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ erl 
Erlang R15B (erts-5.9) [source] [64-bit] [smp:4:4] [async-threads:0] [kernel-poll:false]
&nbsp;
Eshell V5.9  (abort with ^G)
1&gt; server:start_link().
&nbsp;
=INFO REPORT==== 21-Mar-2012::10:52:44 ===
Listen in port 5000
{ok,&lt;0.34.0&gt;}</pre></div></div>

<p>Abrimos otra consola, y ejecutamos el siguiente comando para generar un paquete UDP:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ nc -u localhost 5000
hola</pre></div></div>

<p><strong>NOTA</strong>: tras escribir <tt>hola</tt> hay que presionar el retorno de carro (enter o intro) para que el paquete sea enviado.</p>
<p>Esto generará en la consola de Erlang el siguiente mensaje:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">=INFO REPORT==== 21-Mar-2012::10:54:01 ===
Received via INFO: {udp,#Port&lt;0.506&gt;,{127,0,0,1},36772,&quot;hola\n&quot;}</pre></div></div>

<p>Empleando el <em>match</em> en la función <tt>handle_info</tt> e incluso con expresiones regulares o lo que queramos, podremos tratar de forma más adecuada el mensaje.</p>
<p>Un ejemplo de aplicación de este servidor, como comenté al principio, se puede ver en este proyecto que comencé hace tiempo, <a href="http://project.bosqueviejo.net/esyslog">un servidor de <em>syslog</em></a>, que se basa en la recepción de mensajes por el puerto UDP 514, y el envío, a través de <tt>gen_event</tt> de los mensajes recibidos.</p>
<h3>Conclusiones</h3>
<p>Con este ejemplo, Erlang demuestra que es muy fácil construir servidores de red, con muy pocas líneas de código. En este ejemplo, el hecho de ser un servidor UDP permite eliminar el payload de la escucha, aceptación y mantenimiento de conexión con el destinatario, simplemente se acepta el mensaje, se lee y procesa, muy simple y con un buen rendimiento del sistema.</p>
]]></content:encoded>
			<wfw:commentRss>http://bosqueviejo.net/2012/03/21/erlang-servidores-udp/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

