<?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 &#187; erlang</title>
	<atom:link href="http://bosqueviejo.net/tag/erlang/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>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>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>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>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>
		<item>
		<title>Charla: Gestión de Llamadas con Erlang/OTP</title>
		<link>http://bosqueviejo.net/2012/03/07/charla-gestion-de-llamadas-con-erlangotp/</link>
		<comments>http://bosqueviejo.net/2012/03/07/charla-gestion-de-llamadas-con-erlangotp/#comments</comments>
		<pubDate>Wed, 07 Mar 2012 09:57:48 +0000</pubDate>
		<dc:creator>bombadil</dc:creator>
				<category><![CDATA[Noticias]]></category>
		<category><![CDATA[conferencia]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[erlounge]]></category>
		<category><![CDATA[upm]]></category>

		<guid isPermaLink="false">http://bosqueviejo.net/?p=1255</guid>
		<description><![CDATA[ Este será el título de la charla, dentro de la erlounge de mañana, que daré en la Universidad Complutense de Madrid, organizado por el grupo de usuarios de Erlang de Madrid. Hace tiempo que no doy una charla y la verdad, ya  lo echaba de menos, sobretodo de este tema que me tiene tan motivado últimamente.
Después de la conferencia, como hice con la charla de Metodologías Ágiles en la Práctica, colgaré la presentación para que pueda ser visionada por todo aquél que lo desee.
A todos los que vayáis&#8230; nos vemos allí&#8230; a los que no, pues nos seguimos viendo por el blog&#8230; ¡a ver si dejáis comentarios!  
Actualización 09/03/2012: aquí dejo las transparencias de la charla:
Gestión de Llamadas con Erlang/OTP
View more presentations from Manuel Angel Rubio Jiménez.

Actualizado 11/03/2012: después de 5 horas de procesamiento del vídeo de 8 GB con corrección de color, brillo, agregación de información y conversión a FLV para el visor en web (324MB), ya está disponible el vídeo de la charla. Agradecer sobretodo a Guillermo el podérmelo facilitar (y haberlo grabado).

Si alguien quiere tener acceso al vídeo en mejor calidad, puede solicitármelo y le envío el enlace. No lo dejo en abierto porque [...]]]></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" /> Este será el título de la charla, dentro de la <em>erlounge</em> de mañana, que daré en la <a href="http://www.fi.upm.es/?id=tablon&#038;acciongt=consulta1&#038;idet=1003">Universidad Complutense de Madrid</a>, organizado por el <a href="https://babel.ls.fi.upm.es/cgi-bin/mailman/listinfo/madrid-erlang-users">grupo de usuarios de Erlang de Madrid</a>. Hace tiempo que no doy una charla y la verdad, ya  lo echaba de menos, sobretodo de este tema que me tiene tan motivado últimamente.</p>
<p>Después de la conferencia, como hice con la charla de <a href="/2010/03/16/conferencia-metodologias-agiles-en-la-practica/">Metodologías Ágiles en la Práctica</a>, colgaré la presentación para que pueda ser visionada por todo aquél que lo desee.</p>
<p>A todos los que vayáis&#8230; nos vemos allí&#8230; a los que no, pues nos seguimos viendo por el blog&#8230; ¡a ver si dejáis comentarios! <img src='http://bosqueviejo.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><strong>Actualización 09/03/2012</strong>: aquí dejo las transparencias de la charla:</p>
<div style="width:425px" id="__ss_11939084"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/mrubio166/gestin-de-llamadas-con-erlangotp" title="Gestión de Llamadas con Erlang/OTP">Gestión de Llamadas con Erlang/OTP</a></strong><object id="__sse11939084" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=presentacionerlounge-120309070611-phpapp02&#038;stripped_title=gestin-de-llamadas-con-erlangotp&#038;userName=mrubio166" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><param name="wmode" value="transparent"/><embed name="__sse11939084" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=presentacionerlounge-120309070611-phpapp02&#038;stripped_title=gestin-de-llamadas-con-erlangotp&#038;userName=mrubio166" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="transparent" width="425" height="355"></embed></object>
<div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/mrubio166">Manuel Angel Rubio Jiménez</a>.</div>
</div>
<p><strong>Actualizado 11/03/2012</strong>: después de 5 horas de procesamiento del vídeo de 8 GB con corrección de color, brillo, agregación de información y conversión a FLV para el visor en web (324MB), ya está disponible el vídeo de la charla. Agradecer sobretodo a Guillermo el podérmelo facilitar (y haberlo grabado).</p>
<p><img src="http://bosqueviejo.net/wp-content/plugins/flash-video-player/default_video_player.gif" /></p>
<p>Si alguien quiere tener acceso al vídeo en mejor calidad, puede solicitármelo y le envío el enlace. No lo dejo en abierto porque hay limitación de ancho de banda y el vídeo con mayor calidad es mucho más pesado.</p>
<p>Los comentarios siguen abiertos para lo que queráis preguntar o comentar.</p>
]]></content:encoded>
			<wfw:commentRss>http://bosqueviejo.net/2012/03/07/charla-gestion-de-llamadas-con-erlangotp/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Erlang y OTP en acción</title>
		<link>http://bosqueviejo.net/2012/01/22/erlang-y-otp-en-accion/</link>
		<comments>http://bosqueviejo.net/2012/01/22/erlang-y-otp-en-accion/#comments</comments>
		<pubDate>Sun, 22 Jan 2012 01:02:42 +0000</pubDate>
		<dc:creator>bombadil</dc:creator>
				<category><![CDATA[Libros]]></category>
		<category><![CDATA[eric merritt]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[manning]]></category>
		<category><![CDATA[martin logan]]></category>
		<category><![CDATA[otp]]></category>
		<category><![CDATA[richard carlsson]]></category>

		<guid isPermaLink="false">http://bosqueviejo.net/?p=1215</guid>
		<description><![CDATA[ El pasado lunes estaba camino del dentista cuando, dejando el coche, topé con la librería Cocodrilo Libros. Entré y pregunté por libros de Erlang, y como ya sabía, me mostraron el de O&#8217;Reilly de Francesco Cesarini y el de Pragmatic Programmers de Joe Armstrong&#8230; pero además, una editorial de la que aún no había leído ningún libro, Manning, tenía un libro con el título Erlang and OTP in action, la curiosidad me pudo y lo compré.
Con este título nos encontramos un libro bastante curioso sobre esta tecnología, y digo tecnología, porque no solo cubre el lenguaje de programación funcional Erlang, sino también el framework de desarrollo OTP. El libro se estructura de forma que la introducción al lenguaje es efímera pero clara, y nos plantean, casi desde el principio, la creación de un proyecto de caché, al que van agregando los elementos de OTP, hasta culminar en un proyecto completo, funcional, y que contiene, desde la práctica, todos y cada uno de los elementos que podemos encontrar en el framework OTP.
Da un recorrido por las herramientas de Erlang, de monitorización, de depuración y los profilers, así como Mnesia (la base de datos que trae consigo Erlang) y los mecanismos [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://bosqueviejo.net/wp-content/uploads/logan_cover150-150x150.jpg" alt="" title="logan_cover150" width="150" height="150" class="alignleft size-thumbnail wp-image-1216" /> El pasado lunes estaba camino del dentista cuando, dejando el coche, topé con la librería <a href="http://www.cocodrilolibros.com/">Cocodrilo Libros</a>. Entré y pregunté por libros de Erlang, y como ya sabía, me mostraron el de O&#8217;Reilly de Francesco Cesarini y el de Pragmatic Programmers de Joe Armstrong&#8230; pero además, una editorial de la que aún no había leído ningún libro, Manning, tenía un libro con el título <em>Erlang and OTP in action</em>, la curiosidad me pudo y lo compré.</p>
<p>Con este título nos encontramos un libro bastante curioso sobre esta tecnología, y digo tecnología, porque no solo cubre el lenguaje de programación funcional Erlang, sino también el framework de desarrollo OTP. El libro se estructura de forma que la introducción al lenguaje es efímera pero clara, y nos plantean, casi desde el principio, la creación de un proyecto de caché, al que van agregando los elementos de OTP, hasta culminar en un proyecto completo, funcional, y que contiene, desde la práctica, todos y cada uno de los elementos que podemos encontrar en el framework OTP.</p>
<p>Da un recorrido por las herramientas de Erlang, de monitorización, de depuración y los profilers, así como Mnesia (la base de datos que trae consigo Erlang) y los mecanismos para crear, publicar y actualizar en caliente aplicaciones en Erlang.</p>
<p>Sus autores, entusiastas de Erlang, trabajan en el proyecto <a href="http://erlware.com/">Erlware</a>, además de mantener el libro. Estos son Martin Logan, Eric Merritt y Richard Carlsson. El prólogo está escrito por Ulf Wiger, CTO de Erlang Solutions.</p>
<p>Comentar, simplemente, que el libro me ha gustado mucho por su carácter directo. Muestra un proyecto en proceso de creación con código completo y explicando, no solo la historia de cada uno de los elementos y el porqué funcionan y se comportan como se comportan, sino también mostrando la utilidad práctica y para el proyecto de cada elemento, siendo como ejemplo de uso de los elementos de que dispone Erlang/OTP.</p>
<p>Su redacción es amena y para nada pesada y, aún siendo una temática muy densa, se desarrolla con ejemplos, código y gráficos a lo largo de unas 370 páginas, aproximadamente, quedando explicado todo de forma muy concisa y clara. El autor se centra sobretodo en OTP y el desarrollo de soluciones reales más que en la sintaxis y propiedades del lenguaje, con lo que consigue que el texto sea más pragmático y menos académico que el propio libro de Joe Armstrong.</p>
<p>Recomiendo su lectura para todo aquél que desee aprender Erlang/OTP con una curva de aprendizaje más suavizada.</p>
]]></content:encoded>
			<wfw:commentRss>http://bosqueviejo.net/2012/01/22/erlang-y-otp-en-accion/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zotonic: CMS en Erlang</title>
		<link>http://bosqueviejo.net/2011/12/05/zotonic-cms-en-erlang/</link>
		<comments>http://bosqueviejo.net/2011/12/05/zotonic-cms-en-erlang/#comments</comments>
		<pubDate>Mon, 05 Dec 2011 00:25:59 +0000</pubDate>
		<dc:creator>bombadil</dc:creator>
				<category><![CDATA[web]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[dtl]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[zotonic]]></category>

		<guid isPermaLink="false">http://bosqueviejo.net/?p=873</guid>
		<description><![CDATA[ En mi búsqueda de material (software sobre todo) realizado en Erlang para poder aprender mucho más sobre este lenguaje, sus virtudes, carencias y potencias, he topado con otra muy buena pieza de software: Zotonic, un CMS hecho en Erlang.
¿Qué es un CMS exactamente?
Un CMS es un sistema de administración de contenido (Content Management System), básicamente. Zotonic se centra en esto mismo, administrar el contenido de la web que está sirviendo. A diferencia de otros CMS realizados en otros lenguajes, Zotonic tiene la ventaja de ejecutarse en una máquina que permite la ejecución de software fuera de la petición.
Por ejemplo, en otros lenguajes como Ruby, Python, Perl o PHP, cuando una petición HTTP llega al sistema establece el contexto de ejecución (sesión, cookies, datos de la solicitud, etc.) y tras su respuesta, el contexto es liberado (o volcado a la memoria secundaria), con lo que, es imposible mantener una ejecución paralela que dispare el sistema.
Es más, hay herramientas como delayed::job (en Ruby) o DJJob (en PHP), precisamente para paliar un poco esto.
Sin embargo, Zotonic, tiene como ventaja el hecho de que puede disparar la ejecución de un proceso no dependiente de la solicitud que almacene su resultado en una cola [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://bosqueviejo.net/wp-content/uploads/zotonic-150x150.png" alt="" title="zotonic" width="150" height="150" class="alignleft size-thumbnail wp-image-874" /> En mi búsqueda de material (software sobre todo) realizado en Erlang para poder aprender mucho más sobre este lenguaje, sus virtudes, carencias y potencias, he topado con otra muy buena pieza de software: <a href="http://zotonic.com/">Zotonic</a>, un CMS hecho en Erlang.</p>
<h3>¿Qué es un CMS exactamente?</h3>
<p>Un CMS es un sistema de administración de contenido (Content Management System), básicamente. Zotonic se centra en esto mismo, administrar el contenido de la web que está sirviendo. A diferencia de otros CMS realizados en otros lenguajes, Zotonic tiene la ventaja de ejecutarse en una máquina que permite la ejecución de software fuera de la petición.</p>
<p>Por ejemplo, en otros lenguajes como Ruby, Python, Perl o PHP, cuando una petición HTTP llega al sistema establece el contexto de ejecución (sesión, cookies, datos de la solicitud, etc.) y tras su respuesta, el contexto es liberado (o volcado a la memoria secundaria), con lo que, es imposible mantener una ejecución paralela que dispare el sistema.</p>
<p>Es más, hay herramientas como <a href="/2011/12/01/djjob-trabajos-en-background-para-php/">delayed::job</a> (en Ruby) o <a href="/2011/12/01/djjob-trabajos-en-background-para-php/">DJJob</a> (en PHP), precisamente para paliar un poco esto.</p>
<p>Sin embargo, Zotonic, tiene como ventaja el hecho de que puede disparar la ejecución de un proceso no dependiente de la solicitud que almacene su resultado en una cola de mensajes que sea descargada por el sistema AJAX de la vista para mostrarlos en el momento que sea necesario. Esto le da a Zotonic una sensación de rapidez y paralelismo que pocos entornos web tienen hoy en día.</p>
<h3>¿Qué ofrece Zotonic?</h3>
<p>En principio, Zotonic se puede instalar en una máquina o en varias (en clúster) manteniendo una única interfaz de administración y pudiendo balancear entre todas el acceso, de forma fácil y transparente. Además, cada clúster puede administrar varios dominios:</p>
<p><img alt="Ejemplo de gestión de dominios con Zotonic." src="http://zotonic.com/image/2011/8/19/screen_shot_2010_09_07_at_22_36_42-1.png%28450x%29%28lossless%29%2885760C0FD444E8EC70DB3C1035F5EE44%29.png" title="Gestión de dominios" class="alignnone" width="450" height="272" /></p>
<p>Su interfaz es muy parecida a WordPress, y permite igualmente escribir páginas y entradas de modo que se puedan emplear como páginas del propio sitio web. Su editor se ve así:</p>
<p><img alt="Editor de contenido de Zotonic." src="http://zotonic.com/image/2009/11/16/adminedpage.png%28450x%29%28lossless%29%28B56F26782624E16F3BD5B8F236896BA8%29.png" title="Editor de contenido" class="alignnone" width="450" height="292" /></p>
<p>Como base de datos emplea PostgreSQL, y la forma de programar las plantillas es mediante el estándar de Django Template Library (DTL), lo cual facilita la creación de las vistas enormemente. Se puede revisar <a href="http://zotonic.com/documentation">la documentación</a> que, aunque el tema de las plantillas las trata poco (realmente es porque su simpleza no requiere de mayor información) es una sección de la web bastante extensa conteniendo temas como: SSL, Modelo de Datos, información sobre Erlang, PostgreSQL, conexión Ajax con Zotonic, mensajes Growl, etc.</p>
<p>Una lista bastante extensa y detallada de las características puede verse <a href="http://zotonic.com/features">aquí</a> (en inglés).</p>
<h3>Instalando Zotonic</h3>
<p>Se puede descargar en cualquier ruta de nuestro equipo, realmente, con el comando:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">git clone git://github.com/zotonic/zotonic.git</pre></div></div>

<p>Esto nos deja un entorno limpio con el que podemos hacer nuestra primera instalación. Por ejemplo, si ponemos en nuestro fichero <tt>/etc/hosts</tt> al lado de <tt>localhost</tt> la palabra <tt>miblog</tt>, podremos escribir lo siguiente:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">make
bin/zotonic -s blog miblog
./start.sh</pre></div></div>

<p>Ahora, solo tendremos que ir a un navegador, si ponemos la URL <a href="http://localhost:8000">http://localhost:8000</a>, veremos la interfaz de los dominios que tenemos en ejecución. Solo dispondremos, en estos momentos de <em>miblog</em>, por lo que, como lo hemos puesto en nuestro fichero de <tt>hosts</tt>, podemos seguir ese enlace y ver la web de nuestro sitio.</p>
<p>Si accedemos por la URL <a href="http://miblog:8000/admin/">http://miblog:8000/admin/</a>, nos preguntará por el login de acceso y contraseña. Este será, en principio (deberemos de cambiarlo): admin / admin; tras esto, se nos presentan todas las opciones disponibles de Zotonic&#8230; ¡y en castellano!</p>
<p>Todo queda bastante claro y muy fácil de manejar, a excepción de las plantillas, las cuales solo se pueden modificar a través de la edición de los ficheros en el directorio donde se haya creado el dominio. En este caso, como hemos creado el dominio <tt>miblog</tt>, la ruta será: <tt>priv/sites/miblog/templates</tt>.</p>
<h3>Conclusiones</h3>
<p>Zotonic se ha convertido en poco tiempo en un CMS con amplias características y muy usado en el mundo del web, aunque no tanto como otros que llevan más tiempo como por ejemplo Zope, Drupal o Joomla, pero poco a poco, gracias a sus características propias de alta disponibilidad, redundancia y escalabilidad, de seguro comenzará a ser cada vez más popular.</p>
]]></content:encoded>
			<wfw:commentRss>http://bosqueviejo.net/2011/12/05/zotonic-cms-en-erlang/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Demonware: videojuegos y Erlang</title>
		<link>http://bosqueviejo.net/2011/10/07/demonware-videojuegos-y-erlang/</link>
		<comments>http://bosqueviejo.net/2011/10/07/demonware-videojuegos-y-erlang/#comments</comments>
		<pubDate>Fri, 07 Oct 2011 05:00:35 +0000</pubDate>
		<dc:creator>bombadil</dc:creator>
				<category><![CDATA[programación]]></category>
		<category><![CDATA[demonware]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[videojuegos]]></category>

		<guid isPermaLink="false">http://bosqueviejo.net/?p=954</guid>
		<description><![CDATA[ Demonware es una división de Activision y Blizzard, encargada de desarrollar la parte de cliente-servidor para que los jugadores online puedan echar sus partidas con los amigos.
En su presentación en la Erlang Factory de Londres de 2011, Demonware preparó una presentación de Erlang and First-Person Shooters.
En resumen, ya que el documento es bastante gráfico e interesante de ver, Demonware es una empresa que se dedica a dar soporte de servidor a videojuegos multi-jugador de Activision y Blizzard. No solo la parte en sí del juego, sino también el chat y audio/vídeo que se puede activar en algunos juegos, así como sistemas anti-trampas, etc.
Los juegos que mantienen en sus servidores van desde Call of Duty (todas las entregas), pasando por Guitar Hero (y derivados), hasta otros como Blur y Marvel Ultimate Alliance 2.
Para hacernos una idea de su crecimiento y tecnologías:


Año
Tecnología
Usuarios concurrentes


2005
C++/C++/MySQL
80


2006
C++/Python/MySQL
1,000


2007
Erlang/Python/MySQL
20,000


2007+
2,500,000


Según la empresa, si el cambio no se hubiese realizado, la crisis podría haber sido un desastre, ya que el paso de mil a 20 mil usuarios se realizó con una sola salida al mercado, la de Call Of Duty 4: Modern Warfare.
Terminan la presentación, comentando algunas cosas que han aprendido con la práctica, que son bastante interesante, a [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://bosqueviejo.net/wp-content/uploads/DW-Banner-centre.png" alt="" title="demonware logo" width="160" height="160" class="alignleft size-full wp-image-955" /> <a href="http://www.demonware.net/">Demonware</a> es una división de Activision y Blizzard, encargada de desarrollar la parte de cliente-servidor para que los jugadores online puedan <em>echar sus partidas</em> con los amigos.</p>
<p>En su <a href="http://www.erlang-factory.com/upload/presentations/395/ErlangandFirst-PersonShooters.pdf">presentación</a> en la <a href="http://www.erlang-factory.com/conference/London2011">Erlang Factory de Londres de 2011</a>, Demonware preparó una presentación de <em>Erlang and First-Person Shooters</em>.</p>
<p>En resumen, ya que el documento es bastante gráfico e interesante de ver, Demonware es una empresa que se dedica a dar soporte de servidor a videojuegos multi-jugador de Activision y Blizzard. No solo la parte en sí del juego, sino también el chat y audio/vídeo que se puede activar en algunos juegos, así como sistemas anti-trampas, etc.</p>
<p>Los juegos que mantienen en sus servidores van desde <strong>Call of Duty</strong> (todas las entregas), pasando por <strong>Guitar Hero</strong> (y derivados), hasta otros como <strong>Blur</strong> y <strong>Marvel Ultimate Alliance 2</strong>.</p>
<p>Para hacernos una idea de su crecimiento y tecnologías:</p>
<table>
<tr>
<th>Año</th>
<th>Tecnología</th>
<th>Usuarios concurrentes</th>
</tr>
<tr>
<td>2005</td>
<td>C++/C++/MySQL</td>
<td>80</td>
</tr>
<tr>
<td>2006</td>
<td>C++/Python/MySQL</td>
<td>1,000</td>
</tr>
<tr>
<td>2007</td>
<td rowspan="2">Erlang/Python/MySQL</td>
<td>20,000</td>
</tr>
<tr>
<td>2007+</td>
<td>2,500,000</td>
</tr>
</table>
<p>Según la empresa, si el cambio no se hubiese realizado, la crisis podría haber sido un desastre, ya que el paso de mil a 20 mil usuarios se realizó con una sola salida al mercado, la de <strong>Call Of Duty 4: Modern Warfare</strong>.</p>
<p>Terminan la presentación, comentando algunas cosas que han aprendido con la práctica, que son bastante interesante, a la par que útiles. Nada, lo dicho, recomiendo su visualización.</p>
]]></content:encoded>
			<wfw:commentRss>http://bosqueviejo.net/2011/10/07/demonware-videojuegos-y-erlang/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Riak: base de datos sin SPOF</title>
		<link>http://bosqueviejo.net/2011/09/14/riak-base-de-datos-sin-spof/</link>
		<comments>http://bosqueviejo.net/2011/09/14/riak-base-de-datos-sin-spof/#comments</comments>
		<pubDate>Wed, 14 Sep 2011 11:07:41 +0000</pubDate>
		<dc:creator>bombadil</dc:creator>
				<category><![CDATA[Base de Datos]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[basho]]></category>
		<category><![CDATA[dynamo]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[gossip protocol]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[riak]]></category>

		<guid isPermaLink="false">http://bosqueviejo.net/?p=837</guid>
		<description><![CDATA[ Dando una vuelta por Internet, buscando información sobre base de datos NoSQL, topé con una (u otra) hecha en Erlang/OTP, al igual que CouchDB, pero que se basa en las mismas directrices para lo que fue desarrollado Erlang/OTP. Esta base de datos es Riak.
Actualización 16/09/2011: se me olvidó comentar que SPOF significa, según sus siglas, Single Point Of Failure, algo así como el punto único de fallo. Se refiere a cuando un sistema, aún teniendo bastante redundancia, tiene un punto único, en la red, en el software o en alguna parte del sistema que, fallando, deja sin servicio a todo.
Como la mayoría de software realizado por empresas y que se adentran en el software libre, Riak tiene dos versiones, una Open Source (que es completa y funcional) y otra Enterprise (que agrega commodities -o facilidades- tales como una interfaz de administración).
La base de datos Riak está basada en el documento escrito por Amazon sobre el sistema de almacenamiento Dynamo, el cual se basa en un sistema de alta disponibilidad, con estructura de almacenamiento del par clave-valor y distribuido. Este documento ha sido seguido, además, por Cassandra (la base de datos de Facebook, liberada y acogida en el seno de [...]]]></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" /> Dando una vuelta por Internet, buscando información sobre base de datos <a href="http://bosqueviejo.net/2010/05/04/nosql/">NoSQL</a>, topé con una (u otra) hecha en <a href="http://bosqueviejo.net/2008/10/08/erlang-concurrente-distribuido-y-en-tiempo-real/">Erlang/OTP</a>, al igual que <a href="http://bosqueviejo.net/2009/03/05/couchdb-rest-y-base-de-datos-documental/">CouchDB</a>, pero que se basa en las mismas directrices para lo que fue desarrollado Erlang/OTP. Esta base de datos es <a href="http://wiki.basho.com/Riak.html">Riak</a>.</p>
<p><strong>Actualización 16/09/2011</strong>: se me olvidó comentar que <a href="http://es.wikipedia.org/wiki/Single_point_of_failure">SPOF</a> significa, según sus siglas, <em>Single Point Of Failure</em>, algo así como el punto único de fallo. Se refiere a cuando un sistema, aún teniendo bastante redundancia, tiene un punto único, en la red, en el software o en alguna parte del sistema que, fallando, deja sin servicio a todo.</p>
<p>Como la mayoría de software realizado por empresas y que se adentran en el software libre, Riak tiene dos versiones, una Open Source (que es completa y funcional) y otra Enterprise (que agrega <em>commodities</em> -o facilidades- tales como una interfaz de administración).</p>
<p>La base de datos Riak está basada en el documento escrito por Amazon sobre el sistema de almacenamiento <a href="http://en.wikipedia.org/wiki/Dynamo_(storage_system)">Dynamo</a>, el cual se basa en un sistema de alta disponibilidad, con estructura de almacenamiento del par clave-valor y distribuido. Este documento ha sido seguido, además, por <a href="http://cassandra.apache.org/">Cassandra</a> (la base de datos de Facebook, liberada y acogida en el seno de la Fundación Apache, y que ha sido implementada desde entonces por Digg, Twitter, Reddit, Rackspace, etc.) y por <a href="http://project-voldemort.com/">Voldemort</a> (la base de datos de LinkedIn).</p>
<h3>Características principales</h3>
<p>Riak, además de seguir las bases de Dynamo, ha agregado otras características propias a la lista, quedando (visto en su <a href="http://www.basho.com/products_architecture.php">página web oficial</a>) la siguiente lista de características a destacar:</p>
<ul>
<li><strong>Escalabilidad</strong>: la escalabilidad con Riak es lineal, predecible y de coste efectivo. Agregar nuevas máquinas no significa tener una avalancha de de peticiones que ponga en peligro la efectividad del sistema. Se pueden ir agregando o eliminando máquinas sin mayor problema, y sin que suponga una carga excesiva para el sistema base.</li>
<li><strong>Tolerancia a fallos</strong>: el cluster soporta o admite fallos en nodos aislados, o incluso en partes del cluster, está preparado para no perder datos ante este tipo de fallos. El sistema ha sido diseñado con fallos de máquinas e interrupciones de servicio de red como norma, no como excepción.</li>
<li><strong>Alta disponibilidad</strong>: para alta disponibilidad el sistema debe de estar disponible, no solo para lecturas, sino también para escrituras. La arquitectura de share-nothing (nada compartido) hace que cada nodo en el cluster esté habilitado para realizar lecturas y escrituras, por lo que, la alta disponibilidad está garantizada.</li>
<li><strong>Replicación</strong>: dependiendo de las necesidades, Riak se puede configurar para replicar entre múltiples clusters iguales o diseñar uno o más clusters como solo-lectura o backup. Cada nodo en el cluster puede responder a las peticiones de lecutra/escritura, y el evento de replicación asegura que todos los clusters sean actualizados. Los algoritmos se ejecutan en cada nodo asegurando la consistencia de datos.</li>
</ul>
<p>En base al <a href="http://es.wikipedia.org/wiki/Teorema_CAP">teorema CAP</a> del Dr. Eric Brewer, las tres propiedades deseadas de un sistema distribuido son: consistencia, disponibilidad y partición (tolerancia a fallos). El teorema establece que puedes solo puedes tener dos de las tres propiedades en cada momento. Riak se enfoca en Disponibilidad y Partición. Esta elección pone a Riak en el campo de la consistencia eventual. Sin embargo, la ventana para <em>consistencia eventual</em> es en términos de milisegundos, lo que es suficiente para la mayoría de aplicaciones.</p>
<h3>¿Cómo funciona?</h3>
<p>No me quiero extender mucho, ya que esta información está disponible (aunque en inglés) en la propia web de Riak, en <a href="http://wiki.basho.com/Concepts.html">Concepts</a>, así que resumiré un poco.</p>
<p>El <strong>almacén de datos</strong> se realiza en base a el par clave-valor, es lo que podríamos llamar una base de datos hash. No obstante, la clave se compone de <em>bucket</em> y <em>key</em>, que son como en Erlang el módulo y la función, o en Java el paquete y la clase. El conjunto bucket/key es la unidad de organización única que puede emplearse.</p>
<p>El sistema admite también el uso de <strong>enlaces</strong> (links). Esto quiere decir que el contenido de un bucket/key, puede ser un contenido o un enlace a otro bucket/key que tenga su propio contenido. Algo así como el enlace simbólico en los sistemas de ficheros de Unix/Linux/BSD/&#8230;</p>
<p>Además, el contenido, puede ir estructurado en forma de <strong>metadatos</strong>, es decir, como las cabeceras de los mensajes HTTP, para disponer de arrays asociativos (hash) dentro del contenido.</p>
<p>Uso de diferentes <em>backends</em>. En la versión 0.12, Bitcask se estableció como backend para Riak, pero hay más, aquí ponemos un listado de los disponibles:</p>
<ul>
<li><strong>Bitcask</strong>: simple pero potente almacenaje de pares clave-valor. Es de baja latencia y alto rendimiento.</li>
<li><strong>DETS / ETS</strong>: tablas incorporadas en Erlang para el almacenamiento de información.</li>
<li><strong>Erlang Balanced Trees (gb_trees)</strong>: sistema de árbol balanceado. Rápido para leer, pero algo lento para escribir.</li>
<li><strong>Innostore</strong>: basado en el engine InnoDB de MySQL. Debido a restricciones de licencia, se proporciona por separado.</li>
</ul>
<p>Cada cluster que se configura de Riak, consta de los siguientes elementos:</p>
<ul>
<li><strong>Nodos</strong>: nodos físicos, o máquinas, de las que se compone el cluster.</li>
<li><strong>Nodos Virtuales</strong>: nodos virtuales (o vnodes) que corren en cada máquina. Cada máquina física puede contener uno o varios nodos virtuales.</li>
<li><strong>Particiones</strong>: cada cluster Riak tiene un entero de 160-bits dividido en particiones ecuánimes. Cada vnode reclamará una partición del anillo.</li>
</ul>
<p>Cada nodo en el cluster es responsable del 1/(número total de nodos físicos) del anillo. Puedes determinar el número de vnodes en cada nodo calculando el (número de particiones)/(número de nodos). Por ejemplo, un anillo con 32 particiones, compuesto por cuatro nodos físicos, tendrá aproximadamente ocho vnodos por nodo. Esta configuración es representada por el siguiente diagrama:</p>
<p><a href="http://bosqueviejo.net/wp-content/uploads/riak-ring.png"><img src="http://bosqueviejo.net/wp-content/uploads/riak-ring-300x205.png" alt="" title="riak-ring" width="300" height="205" class="aligncenter size-medium wp-image-866" /></a></p>
<p>Riak está diseñado para ser un sistema distribuido, cuantos más nodos haya en el sistema, más rápido funcionará. </p>
<p>No hay <strong>nodo maestro</strong>, todos los nodos en Riak son iguales. Cada nodo es completamente capaz de servir cualquier petición de cliente. Esto es posible debido a la forma en la que Riak usa la consistencia de hash para distribuir datos a través del cluster, que se realiza a través de un <a href="http://en.wikipedia.org/wiki/Gossip_protocol">gossip protocol</a>.</p>
<h3>Sobre la replicación</h3>
<p>Riak controla tantas réplicas como datos son mantenidos a través de una configuración llamada <em>n-valor</em>. Este valor tiene una configuración por defecto en cada nodo pero puede ser sobreescrito por cada bucket. Los objetos de Riak heredan el n-valor de su bucket padre. Todos los nodos en el mismo cluster deben de acordar y usar el mismo n-valor.</p>
<p>Por ejemplo, aquí hay una representación de que sucede cuando n-valor es 3 (esta es la configuración por defecto). Cuando almacenas el dato en el bucket con un n-valor de tres, el dato se replicará a tres particiones separadas del anillo.</p>
<p><a href="http://bosqueviejo.net/wp-content/uploads/riak-data-distribution.png"><img src="http://bosqueviejo.net/wp-content/uploads/riak-data-distribution-300x157.png" alt="" title="riak-data-distribution" width="300" height="157" class="aligncenter size-medium wp-image-870" /></a></p>
<h3>Y cuando un nodo falla o se agrega otro nodo, ¿qué sucede?</h3>
<p>Riak usa una técnica llamada <strong>hinted handoff</strong>, para compensar el cluster en el momento que un nodo falla. Los vecinos del nodo fallido tomarán relevo y realizarán el trabajo de ese nodo permitiendo al cluster trabajar de forma normal. Esto puede considerarse una forma de auto-curación.</p>
<p>Si se agrega un nodo nuevo, en cambio, se rebalancean los datos.</p>
<h3>Algunas pegas&#8230; siempre las hay</h3>
<p>Primero, los buckets que usan un conjunto de propiedades no estandar forzarán a Riak a enviar vía gossip más datos a través del cluster. Los datos adicionales pueden ralentizar el proceso. Segundo, algunos backends, como Innostore, almacenan cada bucket como una entidad separada. Esto puede causar que nos quedemos sin recursos tales como manejadores de ficheros. Estas restricciones de recursos pueden no impactar al rendimiento, pero representarán otro límite en el máximo número de buckets a gestionar.</p>
<h3>Conclusiones</h3>
<p>A nivel teórico, todo bien, parece. Habrá que realizar un banco de pruebas y ver qué tal va el sistema. De momento, me he quedado sin tiempo (del que había planificado) para escribir este artículo, por lo que, dejo las pruebas para la siguiente parte&#8230; que entraremos de lleno en la práctica.</p>
]]></content:encoded>
			<wfw:commentRss>http://bosqueviejo.net/2011/09/14/riak-base-de-datos-sin-spof/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

