Jekyll2023-02-24T07:11:32+00:00https://serdardogruyol.com/feed.xmlSerdar DoğruyolSerdar Dogruyol's official blog. About Ruby, Crystal, Kemal, Open Source Software, Programming languages and other software development related topics.Serdar DoğruyolBenchmarking and Scaling WebSockets: Handling 60000 concurrent connections with Kemal2016-11-13T22:03:00+00:002016-11-13T22:03:00+00:00https://serdardogruyol.com/benchmarking-and-scaling-websockets-handling-60000-concurrent-connections-with-kemal<p>I am the author of <a href="http://kemalcr.com">Kemal</a>. Fast, Effective and Simple Web Framework written in amazing <a href="http://crystal-lang.org">Crystal</a> programming language.</p>
<p>I love benchmarks but unfortunately</p>
<blockquote>
<p>Benchmarking is hard..</p>
</blockquote>
<p>There are lots of good tools for benchmarking an HTTP server. Such as <code class="language-plaintext highlighter-rouge">ab</code>, <code class="language-plaintext highlighter-rouge">wrk</code>, <code class="language-plaintext highlighter-rouge">siege</code>.</p>
<p>My personal favorite is <code class="language-plaintext highlighter-rouge">wrk</code>. It’s quite handy and simple to use for HTTP benchmarking.</p>
<h2 id="benchmarking-websockets">Benchmarking Websockets?</h2>
<p>Back to original topic, my goal was:</p>
<blockquote>
<p>Benchmark how many concurrent WebSocket connections can a single <a href="http://kemalcr.com">Kemal</a> application handle?</p>
</blockquote>
<p>Unfortunately when you want to benchmark a WebSocket server there are actually nearly no resources / tools.</p>
<blockquote>
<p>There aren’t many tools to benchmark WebSockets.</p>
</blockquote>
<p>I actually asked this on Twitter and also got no response.</p>
<blockquote class="twitter-tweet" data-lang="tr"><p lang="en" dir="ltr">Anyone know a fully featured tool for load testing / benchmarking WebSocket based web applications? <a href="https://twitter.com/hashtag/web?src=hash">#web</a> <a href="https://twitter.com/hashtag/benchmark?src=hash">#benchmark</a> <a href="https://twitter.com/hashtag/websocket?src=hash">#websocket</a></p>— Serdar Dogruyol セド (@sdogruyol) <a href="https://twitter.com/sdogruyol/status/797718960523382784">13 Kasım 2016</a></blockquote>
<script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>Googling ‘Benchmarking Websockets’ gave me some results but most of them obsolete or not working anymore.</p>
<p>When i was just losing the hope, this post from <a href="http://www.phoenixframework.org/blog/the-road-to-2-million-websocket-connections">Elixir Phoenix Blog</a> saved my day.</p>
<h2 id="setup">Setup</h2>
<h3 id="kemal-server">Kemal Server</h3>
<p>A Kemal application implementing a simple chat server is just great for this benchmark. Luckily we have <a href="https://github.com/sdogruyol/kemal-chat">kemal-chat</a>. There’s just one minor difference for this benchmark. Just turn off logging with</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># src/kemal_chat.cr
logging false
</code></pre></div></div>
<p>You need to have Crystal <code class="language-plaintext highlighter-rouge">0.19.4</code> installed to build and run the server. Check <a href="https://crystal-lang.org/docs/installation/index.html">Crystal Installation Guide</a> for more info.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/sdogruyol/kemal-chat
cd kemal-chat
crystal build --release src/kemal-chat.cr -o app
./app
</code></pre></div></div>
<p>Now go to your <code class="language-plaintext highlighter-rouge">IP_ADDRESS:3000/</code> and you should see something like this.</p>
<p><img src="/images/kemal_chat.png" alt="Kemal Chat" /></p>
<h3 id="tsung">Tsung</h3>
<p><a href="http://tsung.erlang-projects.org/">Tsung</a> is an open-source multi-protocol distributed load testing tool. It’s written in <a href="http://www.erlang.org/">Erlang</a>.</p>
<p>Tsung also supports benchmarking WebSocket protocol. Tsung configuration and scenarios are written in <code class="language-plaintext highlighter-rouge">XML</code> (i know it’s scary).</p>
<p><img src="/images/you_said_xml.jpg" alt="You Said XML" /></p>
<p>Installing <code class="language-plaintext highlighter-rouge">Tsung</code> is straightforward but there’s a pitfall. Be sure to use <code class="language-plaintext highlighter-rouge">Ubuntu 16.04</code>.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt-get update
sudo apt-get install tsung
tsung -v
1.5.1
</code></pre></div></div>
<p>Now that we have Tsung installed and ready to engage we need a configuration file. Like i said the configuration is in XML.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?xml version="1.0"?></span>
<span class="cp"><!DOCTYPE tsung SYSTEM "/user/share/tsung/tsung-1.0.dtd"></span>
<span class="nt"><tsung</span> <span class="na">loglevel=</span><span class="s">"notice"</span> <span class="na">version=</span><span class="s">"1.0"</span><span class="nt">></span>
<span class="nt"><clients></span>
<span class="nt"><client</span> <span class="na">host=</span><span class="s">"tsung-machine"</span> <span class="na">use_controller_vm=</span><span class="s">"false"</span> <span class="na">maxusers=</span><span class="s">"64000"</span> <span class="nt">/></span>
<span class="nt"><client</span> <span class="na">host=</span><span class="s">"tsung-machine-2"</span> <span class="na">use_controller_vm=</span><span class="s">"false"</span> <span class="na">maxusers=</span><span class="s">"64000"</span> <span class="nt">/></span>
<span class="nt"></clients></span>
<span class="nt"><servers></span>
<span class="nt"><server</span> <span class="na">host=</span><span class="s">"KEMAL_HOST_IP"</span> <span class="na">port=</span><span class="s">"3000"</span> <span class="na">type=</span><span class="s">"tcp"</span> <span class="nt">/></span>
<span class="nt"></servers></span>
<span class="nt"><load></span>
<span class="nt"><arrivalphase</span> <span class="na">phase=</span><span class="s">"1"</span> <span class="na">duration=</span><span class="s">"100"</span> <span class="na">unit=</span><span class="s">"second"</span><span class="nt">></span>
<span class="nt"><users</span> <span class="na">maxnumber=</span><span class="s">"100000"</span> <span class="na">arrivalrate=</span><span class="s">"1000"</span> <span class="na">unit=</span><span class="s">"second"</span> <span class="nt">/></span>
<span class="nt"></arrivalphase></span>
<span class="nt"></load></span>
<span class="nt"><sessions></span>
<span class="nt"><session</span> <span class="na">name=</span><span class="s">"websocket"</span> <span class="na">probability=</span><span class="s">"100"</span> <span class="na">type=</span><span class="s">"ts_websocket"</span><span class="nt">></span>
<span class="nt"><request></span>
<span class="nt"><websocket</span> <span class="na">type=</span><span class="s">"connect"</span> <span class="na">path=</span><span class="s">"/"</span><span class="nt">></websocket></span>
<span class="nt"></request></span>
<span class="nt"><request</span> <span class="na">subst=</span><span class="s">"true"</span><span class="nt">></span>
<span class="nt"><websocket</span> <span class="na">type=</span><span class="s">"message"</span><span class="nt">></span>{"name":"Kemal"}<span class="nt"></websocket></span>
<span class="nt"></request></span>
<span class="nt"><for</span> <span class="na">var=</span><span class="s">"i"</span> <span class="na">from=</span><span class="s">"1"</span> <span class="na">to=</span><span class="s">"100"</span> <span class="na">incr=</span><span class="s">"1"</span><span class="nt">></span>
<span class="nt"><thinktime</span> <span class="na">value=</span><span class="s">"10"</span><span class="nt">/></span>
<span class="nt"></for></span>
<span class="nt"></session></span>
<span class="nt"></sessions></span>
<span class="nt"></tsung></span>
</code></pre></div></div>
<p>This XML configuration seems a bit complicated. Here are the important things that you should be aware of.</p>
<ul>
<li><code class="language-plaintext highlighter-rouge"><client></code> is a Tsung machine. If you are running Tsung in a distributed mode (multiple Tsung servers) you need to edit your <code class="language-plaintext highlighter-rouge">/etc/hosts</code> and add your Tsung servers like this.</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tsung-machine 34.55.199.22
tsung-machine-2 34.55.199.23
</code></pre></div></div>
<p>Tsung uses SSH authentication to access workers. That’s why you need to generate a public key in your Tsung master machine in this case <code class="language-plaintext highlighter-rouge">tsung-machine</code> and add it to <code class="language-plaintext highlighter-rouge">tsung-machine-2</code>’s <code class="language-plaintext highlighter-rouge">.ssh/authorized_keys</code>.</p>
<p>On <code class="language-plaintext highlighter-rouge">tsung-machine</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/tsung-machine/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/tsung-machine/.ssh/id_rsa.
Your public key has been saved in /home/tsung-machine/.ssh/id_rsa.pub.
cat id-rsa.pub
</code></pre></div></div>
<p>Copy the output of <code class="language-plaintext highlighter-rouge">cat</code>. On <code class="language-plaintext highlighter-rouge">tsung-machine-2</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vim .ssh/authorized_keys
</code></pre></div></div>
<p>And paste <code class="language-plaintext highlighter-rouge">tsung-machine</code>’s <code class="language-plaintext highlighter-rouge">id-rsa.pub</code>.</p>
<p>Now try to SSH into <code class="language-plaintext highlighter-rouge">tsung-machine-2</code> from <code class="language-plaintext highlighter-rouge">tsung-machine</code>.</p>
<p>Congrats, now you have a distributed <code class="language-plaintext highlighter-rouge">Tsung</code> cluster.</p>
<ul>
<li><code class="language-plaintext highlighter-rouge"><server></code> is your application. In this case it’s our <code class="language-plaintext highlighter-rouge">Kemal</code> application.</li>
<li><code class="language-plaintext highlighter-rouge"><load></code> specifies our load configuration. In this case we are going with 1000 users per second up to 100000 users for 100 seconds.</li>
<li><code class="language-plaintext highlighter-rouge"><session></code> specifies your session scenario for each scenario. In this case we are going to open a <strong><em>WebSocket</em></strong> connection on <code class="language-plaintext highlighter-rouge">/</code> send a message with <code class="language-plaintext highlighter-rouge">{"name":"Kemal"}</code> body then hold the connection open for 1000 seconds(which is longer enough for our whole test).</li>
</ul>
<p>Here is how our server cluster looks like.</p>
<p><img src="/images/go_change_the_world.png" alt="Go change the world" /></p>
<h2 id="benchmark">Benchmark</h2>
<p>We got everything setup for our benchmark. Assuming that the configuration file is <code class="language-plaintext highlighter-rouge">websocket.xml</code>
here’s what you need to run.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tsung -f websocket.xml start
</code></pre></div></div>
<h3 id="the-first-try">The first try</h3>
<p>The first try actually didn’t go well. I couldn’t get Tsung to put enough load to push <code class="language-plaintext highlighter-rouge">Kemal</code> and just got 1k connections. Seemed like the default <code class="language-plaintext highlighter-rouge">Operating System</code> configurations were not enough.</p>
<h3 id="configuring-os-for-high-load">Configuring OS for high load</h3>
<p>A quick research on how to make <code class="language-plaintext highlighter-rouge">Ubuntu 16.04</code> suitable for high connection / high load handed me these.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sysctl -w fs.file-max=1000000
sysctl -w fs.nr_open=1000000
ulimit -n 1000000
sysctl -w net.ipv4.tcp_mem='10000000 10000000 10000000'
sysctl -w net.ipv4.tcp_rmem='1024 4096 16384'
sysctl -w net.ipv4.tcp_wmem='1024 4096 16384'
sysctl -w net.core.rmem_max=16384
sysctl -w net.core.wmem_max=16384
</code></pre></div></div>
<p>I’m not going into details for but this configuration will allow Tsung to generate as much as load as possible.</p>
<h3 id="again">Again!</h3>
<p>This time Tsung generated enough load to actually push Kemal to the limit.</p>
<blockquote class="twitter-tweet" data-lang="tr"><p lang="en" dir="ltr">Kemal handles 28231 concurrent WebSocket connections on a 512 MB / 1 CPU <a href="https://twitter.com/digitalocean">@digitalocean</a> droplet <a href="https://t.co/nUnetmqgh4">pic.twitter.com/nUnetmqgh4</a></p>— Serdar Dogruyol セド (@sdogruyol) <a href="https://twitter.com/sdogruyol/status/797750500288499712">13 Kasım 2016</a></blockquote>
<script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<h3 id="time-to-upgrade-kemal-server">Time to upgrade Kemal server</h3>
<p>Kemal server was a 1 CPU / 512 MB DigitalOcean droplet. Naturally i upgraded it to 2 CPU / 2 GB.</p>
<p>Running Tsung again gave me a surprise because i couldn’t see any significant difference.</p>
<blockquote class="twitter-tweet" data-lang="tr"><p lang="en" dir="ltr">My app instance running Kemal gets stuck at 29238 concurrent connections, it has more ram / cpu to spare. It's on Ubuntu 14.04. Any ideas?</p>— Serdar Dogruyol セド (@sdogruyol) <a href="https://twitter.com/sdogruyol/status/797784963508801537">13 Kasım 2016</a></blockquote>
<script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>After some googling i found out that the default port ranges on <code class="language-plaintext highlighter-rouge">Ubuntu</code> was the limit.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sysctl -w net.ipv4.ip_local_port_range="1024 64000"
</code></pre></div></div>
<p>did the trick.</p>
<h3 id="final-results">Final results</h3>
<p>Now that the OS is not the bottleneck Tsung
servers pushed the limits again :)</p>
<blockquote class="twitter-tweet" data-lang="tr"><p lang="en" dir="ltr">Kemal handling 61189 concurrent WebSocket connections on a 2 GB server. This is not the limit but benchmarking is hard <a href="https://twitter.com/CrystalLanguage">@CrystalLanguage</a> <a href="https://t.co/y2GDow3J6e">pic.twitter.com/y2GDow3J6e</a></p>— Serdar Dogruyol セド (@sdogruyol) <a href="https://twitter.com/sdogruyol/status/797835943864573952">13 Kasım 2016</a></blockquote>
<script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>Kemal Handling <strong><em>61189</em></strong> concurrent WebSocket connections :) It’s not the limit but the end for now.</p>
<p>Happy Crystalling <3</p>
<p>P.S: If you like this, please follow <a href="https://twitter.com/crystalkemal">Kemal</a> on Twitter for updates and blog posts like this.</p>Serdar DoğruyolI am the author of Kemal. Fast, Effective and Simple Web Framework written in amazing Crystal programming language.Building a realtime Chat application with Crystal and Kemal2015-12-20T16:27:00+00:002015-12-20T16:27:00+00:00https://serdardogruyol.com/building-a-realtime-chat-app-with-crystal-and-kemal<p>As we all know that the web is getting bigger and the information is being consumed really fast. Most of the web applications are in need of realtime updates to supply this demand. To achieve this <strong><em>WebSocket</em></strong> technology is a great fit.</p>
<p>In this blog post we are going to build a realtime chat application with <strong><em><a href="http://crystal-lang.org/">Crystal</a></em></strong> programming language and <strong><em><a href="https://github.com/sdogruyol/kemal">Kemal</a></em></strong>. You’ll see that <strong><em>how powerful yet easy</em></strong> it is. To learn more about <strong><em>Crystal</em></strong> you can read my <a href="http://serdardogruyol.com/why-crystal/">previous post</a>.</p>
<h1 id="the-application">The application</h1>
<p>The application will receive messages from a client and publish it back to all registered clients. The communication is bi-directional meaning a client can send a message to server and vice versa the server can push a message to a client / clients.</p>
<h2 id="the-web-framework">The web framework</h2>
<p>To build our application we are going to use <a href="https://github.com/sdogruyol/kemal">Kemal</a>. Make sure you have <a href="http://crystal-lang.org/docs/installation/index.html">Crystal 0.9.1</a> installed.</p>
<p>First we are going to create our project named <code class="language-plaintext highlighter-rouge">kemal-chat</code>.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>crystal init app kemal-chat
cd kemal-chat
</code></pre></div></div>
<p>Now we are going to edit our <code class="language-plaintext highlighter-rouge">shard.yml</code>file to add <code class="language-plaintext highlighter-rouge">Kemal</code>as a dependency.</p>
<p><code class="language-plaintext highlighter-rouge">shard.yml</code></p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">name</span><span class="pi">:</span> <span class="s">kemal-chat</span>
<span class="na">version</span><span class="pi">:</span> <span class="s">0.1.0</span>
<span class="na">dependencies</span><span class="pi">:</span>
<span class="na">kemal</span><span class="pi">:</span>
<span class="na">github</span><span class="pi">:</span> <span class="s">sdogruyol/kemal</span>
<span class="na">branch</span><span class="pi">:</span> <span class="s">master</span>
<span class="na">authors</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">Sdogruyol <dogruyolserdar@gmail.com></span>
<span class="na">license</span><span class="pi">:</span> <span class="s">MIT</span>
</code></pre></div></div>
<p>To get the dependencies</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>shards install
</code></pre></div></div>
<p>Now we can use <code class="language-plaintext highlighter-rouge">Kemal</code>in our application.</p>
<p>To do so let’s open up <code class="language-plaintext highlighter-rouge">src/kemal_chat.cr</code>.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">require</span> <span class="s2">"kemal"</span>
<span class="n">get</span> <span class="s2">"/"</span> <span class="k">do</span>
<span class="n">render</span> <span class="s2">"views/index.ecr"</span>
<span class="k">end</span>
</code></pre></div></div>
<p>Our first route renders the <code class="language-plaintext highlighter-rouge">html</code> needed for our application.</p>
<p><code class="language-plaintext highlighter-rouge">views/index.ecr</code></p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o"><!</span><span class="n">doctype</span> <span class="n">html</span><span class="o">></span>
<span class="o"><</span><span class="n">html</span><span class="o">></span>
<span class="o"><</span><span class="n">head</span><span class="o">></span>
<span class="o"><</span><span class="n">title</span><span class="o">></span><span class="no">Kemal</span> <span class="no">Chat</span><span class="o"><</span><span class="sr">/title>
</</span><span class="n">head</span><span class="o">></span>
<span class="o"><</span><span class="n">body</span><span class="o">></span>
<span class="o"><</span><span class="n">pre</span> <span class="nb">id</span><span class="o">=</span><span class="s1">'chat'</span><span class="o">><</span><span class="sr">/pre>
<form>
<input id='msg' placeholder='message...' /</span><span class="o">></span>
<span class="o"><</span><span class="n">input</span> <span class="n">type</span><span class="o">=</span><span class="s2">"submit"</span> <span class="n">value</span><span class="o">=</span><span class="s2">"Send"</span><span class="o">></span>
<span class="o"><</span><span class="sr">/form>
</</span><span class="n">body</span><span class="o">></span>
<span class="o"><</span><span class="sr">/html>
</span></code></pre></div></div>
<p>Now that we have our interface ready let’s see it.</p>
<p><code class="language-plaintext highlighter-rouge">crystal run src/kemal_chat.cr</code></p>
<p>And point your browser to <code class="language-plaintext highlighter-rouge">http://localhost:3000/</code></p>
<p><img src="/images/kemal-chat1.png" alt="Kemal Chat 1" /></p>
<h2 id="adding-websocket-support">Adding WebSocket support</h2>
<p>Now that we got our view served let’s add the <code class="language-plaintext highlighter-rouge">WebSocket</code> support. With Kemal using WebSocket is super easy.</p>
<p>First we start from the backend and add a <code class="language-plaintext highlighter-rouge">chat</code> route. This route is different from an HTTP route.</p>
<p><code class="language-plaintext highlighter-rouge">src/kemal_chat.cr</code></p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">SOCKETS</span> <span class="o">=</span> <span class="p">[]</span> <span class="n">of</span> <span class="no">HTTP</span><span class="o">::</span><span class="no">WebSocket</span>
<span class="n">ws</span> <span class="s2">"/chat"</span> <span class="k">do</span> <span class="o">|</span><span class="n">socket</span><span class="o">|</span>
<span class="c1"># Add the client to SOCKETS list</span>
<span class="no">SOCKETS</span> <span class="o"><<</span> <span class="n">socket</span>
<span class="c1"># Broadcast each message to all clients</span>
<span class="n">socket</span><span class="p">.</span><span class="nf">on_message</span> <span class="k">do</span> <span class="o">|</span><span class="n">message</span><span class="o">|</span>
<span class="no">SOCKETS</span><span class="p">.</span><span class="nf">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">socket</span><span class="o">|</span> <span class="n">socket</span><span class="p">.</span><span class="nf">send</span> <span class="n">message</span><span class="p">}</span>
<span class="k">end</span>
<span class="c1"># Remove clients from the list when it's closed</span>
<span class="n">socket</span><span class="p">.</span><span class="nf">on_close</span> <span class="k">do</span>
<span class="no">SOCKETS</span><span class="p">.</span><span class="nf">delete</span> <span class="n">socket</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>
<p>You can easily notice that the <code class="language-plaintext highlighter-rouge">WebSocket</code> route is defined with <code class="language-plaintext highlighter-rouge">ws</code> keyword which creates an endpoint for <code class="language-plaintext highlighter-rouge">ws://localhost:3000/chat</code>.</p>
<ul>
<li>We also create an aray called <code class="language-plaintext highlighter-rouge">SOCKETS</code> to add all clients into.</li>
<li>Once a client opens a connection it’s added to <code class="language-plaintext highlighter-rouge">SOCKETS</code>.</li>
<li>When a message is received it fires the <code class="language-plaintext highlighter-rouge">on_message</code> event and the message is broadcasted to each client via <code class="language-plaintext highlighter-rouge">SOCKETS.each { |socket| socket.send message}</code>.</li>
<li>When a client closes the connection the <code class="language-plaintext highlighter-rouge">on_close</code> event is fired the <code class="language-plaintext highlighter-rouge">socket</code> is removed from the <code class="language-plaintext highlighter-rouge">SOCKETS</code> list.</li>
</ul>
<p>Now that we got our backend ready. Let’s implement the corresponding <code class="language-plaintext highlighter-rouge">Javascript</code> code to view.</p>
<p>To do so we edit <code class="language-plaintext highlighter-rouge">views/index.ecr</code> like below.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o"><!</span><span class="n">doctype</span> <span class="n">html</span><span class="o">></span>
<span class="o"><</span><span class="n">html</span><span class="o">></span>
<span class="o"><</span><span class="n">head</span><span class="o">></span>
<span class="o"><</span><span class="n">title</span><span class="o">></span><span class="no">Kemal</span> <span class="no">Chat</span><span class="o"><</span><span class="sr">/title>
<script src="https:/</span><span class="o">/</span><span class="n">code</span><span class="p">.</span><span class="nf">jquery</span><span class="p">.</span><span class="nf">com</span><span class="o">/</span><span class="n">jquery</span><span class="o">-</span><span class="mf">1.11</span><span class="o">.</span><span class="mi">3</span><span class="p">.</span><span class="nf">js</span><span class="s2">"></script>
<script>
$(document).ready(function() {
// Open WebSocket connection
var ws = new WebSocket("</span><span class="n">ws</span><span class="ss">:/</span><span class="o">/</span><span class="s2">" + location.host + "</span><span class="o">/</span><span class="n">chat</span><span class="s2">");
// Append each message
ws.onmessage = function(e) { $('#chat').append(e.data + "</span><span class="p">\</span><span class="n">n</span><span class="s2">") };
$("</span><span class="n">form</span><span class="s2">").bind('submit', function(e) {
var message = $('#msg').val();
ws.send(message);
$('#msg').val(''); $('#msg').focus();
e.preventDefault();
});
});
</script>
</head>
<body>
<pre id='chat'></pre>
<form>
<input id='msg' placeholder='message...' />
<input type="</span><span class="n">submit</span><span class="s2">" value="</span><span class="no">Send</span><span class="s2">">
</form>
</body>
</html>
</span></code></pre></div></div>
<p>Between the <code class="language-plaintext highlighter-rouge"><script></script></code> tags</p>
<ul>
<li>We open a WebSocket connection to the server</li>
<li>Register for <code class="language-plaintext highlighter-rouge">message</code> event and then append each message to our list.</li>
<li>Bind our <code class="language-plaintext highlighter-rouge">form</code> to send our message to server with <code class="language-plaintext highlighter-rouge">ws.send</code>.</li>
</ul>
<p>This is it! Now we have a simple but fully functional chat application. To see it in action let’s rerun our code.</p>
<p><code class="language-plaintext highlighter-rouge">crystal src/kemal_chat.cr</code></p>
<p>Open at least 2 browsers pointing to <code class="language-plaintext highlighter-rouge">http://localhost:3000/</code>.</p>
<p>Let’s see it in action :)</p>
<p><img src="/images/kemal-chat.gif" alt="Kemal Chat Gif" /></p>
<h2 id="closing-thoughts">Closing Thoughts</h2>
<p>That was easy! In 5 minutes we did build a realtime chat application using WebSockets. I really think that <strong><em>Crystal</em></strong> and <strong><em>Kemal</em></strong> are awesome and so powerful.</p>
<p>To see what i mean you can check <a href="https://gist.github.com/sdogruyol/bdd400a6eac13e26228e">Crystal vs Node.js WebSocket benchmark</a>.</p>
<p>P.S: You can check the source code of this post at <a href="https://github.com/sdogruyol/kemal-chat">Github</a>.</p>
<p>Update: You can check out this <a href="http://kemal-react-chat.herokuapp.com/">realtime chat demo</a> built with Kemal + React.</p>
<p>Happy Crystaling <3</p>Serdar DoğruyolAs we all know that the web is getting bigger and the information is being consumed really fast. Most of the web applications are in need of realtime updates to supply this demand. To achieve this WebSocket technology is a great fit.Why Crystal?2015-12-13T13:42:00+00:002015-12-13T13:42:00+00:00https://serdardogruyol.com/why-crystal<p><strong>Spoiler</strong>: This is an opinionated post about programming languages.</p>
<p>I’m a Rubyist, i love Ruby, the community, the productivity and lots more.
For more than 4 years i professionally write Ruby to get paid and i really like to keep it that way but
i’m also aware that languages/tools are destined to be replaced.</p>
<p>In 2015 we’ve seen lots of blog posts starting like ‘How we moved from Ruby to X ..’ . Well that’s the living
proof of people looking for better alternatives. We shouldn’t take these as ‘Ruby is not good’. Quite the contrary we should be aware
of that ‘X’.</p>
<p>In most of those the ‘X’ is Go, Rust, Elixir etc.. <strong><em>I hereby claim that:</em></strong> As a Rubyist that that ‘X’ should be nothing else than <strong><em><a href="http://crystal-lang.org">Crystal</a></em></strong>.</p>
<p>You’d ask. Well Serdar:</p>
<blockquote>
<p>Why Crystal?</p>
</blockquote>
<p>And i’d answer with something like:</p>
<blockquote>
<p>Learning a language takes days but becoming proficient and productive enough takes years.</p>
</blockquote>
<p>Crystal is %90 Ruby with</p>
<ul>
<li>Similar syntax</li>
<li>Same idioms</li>
</ul>
<p><strong>Plus</strong></p>
<ul>
<li>Compiled</li>
<li>Native code</li>
<li>Superb performance</li>
</ul>
<p>and much more.</p>
<h2 id="enter-crystal">Enter Crystal</h2>
<p>Let’s start with an example</p>
<p><code class="language-plaintext highlighter-rouge">fib.rb</code></p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">fibonacci</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="k">return</span> <span class="n">n</span> <span class="k">if</span> <span class="n">n</span> <span class="o"><=</span> <span class="mi">1</span>
<span class="n">fibonacci</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="n">fibonacci</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span>
<span class="k">end</span>
<span class="nb">puts</span> <span class="n">fibonacci</span> <span class="mi">40</span>
</code></pre></div></div>
<p>This is how you’d do <strong><em>fibonacci</em></strong> (without memoization) in Crystal. Did you notice that the file extension <code class="language-plaintext highlighter-rouge">.rb</code>? Well at the same time this is Ruby code :)</p>
<p>Let’s run to see it working on Ruby and Crystal.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ruby fib.rb
102334155
crystal fib.rb
102334155
</code></pre></div></div>
<p>Awesome. Let’s take a look at the time taken.</p>
<p><strong>Ruby</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>time ruby fib.rb
ruby fib.rb 16.62s user 0.08s system 99% cpu 16.805 total
</code></pre></div></div>
<p><strong>Crystal</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>time crystal fib.rb
crystal fib.rb 0.85s user 0.18s system 118% cpu 0.870 total
</code></pre></div></div>
<p>Wow! That’s pretty awesome. We practically did nothing and gained <strong>20x</strong> performance.</p>
<p>But wait what if we turn on <strong><a href="http://llvm.org/">LLVM</a></strong> optimizations</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>crystal build --release fib.rb
time ./fib
./fib 0.67s user 0.00s system 99% cpu 0.678 total
</code></pre></div></div>
<p><strong><em><a href="https://en.wikipedia.org/wiki/Machine_code">Native code</a></em></strong> rocks. We build the Crystal program with all the LLVM optimizations and
run the generated native code in this case <code class="language-plaintext highlighter-rouge">./fib</code> and now we are nearly <strong>25x</strong> faster than Ruby :)</p>
<p>That’s a really simple demonstration and a big reason of why that <strong><em>‘X’</em></strong> should be <strong><em>Crystal</em></strong>.</p>
<p>As a web developer i was pretty curious to see how a web framework similar to <strong>Sinatra</strong> would benefit from this
performance. So i created <strong><a href="http://www.github.com/sdogruyol/kemal">Kemal</a></strong>.</p>
<h2 id="enter-kemal">Enter Kemal</h2>
<p>To understand the true potential of <strong><a href="http://crystal-lang.org">Crystal</a></strong> and make something useful i thought that something like <strong><a href="http://www.sinatrarb.com">Sinatra</a></strong> would be awesome
thus <strong><a href="http://www.github.com/sdogruyol/kemal">Kemal</a></strong> is born.</p>
<p>It’s literally as simple as Sinatra.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">require</span> <span class="s2">"kemal"</span>
<span class="n">get</span> <span class="s2">"/"</span> <span class="k">do</span>
<span class="s2">"Hello World!"</span>
<span class="k">end</span>
</code></pre></div></div>
<p>but with a big performance difference :)</p>
<p><code class="language-plaintext highlighter-rouge">wrk -c 100 -d 20 http://localhost:3000</code></p>
<ul>
<li>Kemal (Production) - <strong>64986 requests per second</strong> with an average time of <strong>170μs</strong></li>
<li>Sinatra (Thin) - <strong>2274 requests per second</strong> with an average time of <strong>43.82ms</strong></li>
</ul>
<p>Currently Kemal is under development and is not yet feature complete but has the following</p>
<ul>
<li>Support all REST verbs</li>
<li>Request/Response context, easy parameter handling</li>
<li>Middlewares</li>
<li>Built-in JSON support</li>
<li>Built-in static file serving</li>
<li>Built-in view templating via <code class="language-plaintext highlighter-rouge">ecr</code></li>
</ul>
<p>To see what you can build with <strong><a href="http://www.github.com/sdogruyol/kemal">Kemal</a></strong> you better check <strong><a href="http://github.com/f/kamber">Kamber</a></strong></p>
<h2 id="current-status">Current status</h2>
<p>Crystal is in alpha stage and the latest stable version is <strong>0.9.1</strong>.</p>
<p>Most of the standard library is complete and stable. It’s not yet production-ready but
you can use Crystal today.</p>
<p>A big thumbs up for Crystal is that it’s written in Crystal. You can easily read the source
code of <strong><a href="https://github.com/manastech/crystal">Crystal</a></strong> and contribute back it by opening pull requests / issues.</p>
<h2 id="community">Community</h2>
<p>The community is really nice :) It follows the roots of <strong><a href="https://en.wikipedia.org/wiki/MINASWAN">MINASWAN</a></strong> and currently
has an irc channel (#crystal-lang on freenode) and <a href="https://groups.google.com/forum/?fromgroups#!forum/crystal-lang">a mailing group</a>.</p>
<h2 id="closing-thoughts">Closing Thoughts</h2>
<p>If you’re reading this far then i’m thankful for your time :) I really hope that you enjoy using <strong>Crystal</strong> soon. You can ask me any
questions and reach me at <a href="http://twitter.com/sdogruyol">@sdogruyol</a></p>
<p>Happy Crystaling <3</p>
<p><strong>P.S:</strong> You can support <strong>Crystal</strong> development with this <a href="https://www.bountysource.com/teams/crystal-lang/fundraiser">fundraiser</a>.</p>Serdar DoğruyolSpoiler: This is an opinionated post about programming languages.Rust vs Ruby: Building an API2015-04-09T19:49:13+00:002015-04-09T19:49:13+00:00https://serdardogruyol.com/rust-vs-ruby-building-an-api<p>I’ve been itching to write this blog post for a while. Now that Rust is 1.0.0-beta
the time has come.</p>
<p>Recently i’m trying to learn Rust and dealing with lots of compile-time errors :)
As a Rubyist i felt very overwhelmed when i first saw the Rust syntax. But as i started
to understand the concepts all the overwhelming feeling is gone and now i’m pretty in love
with Rust.</p>
<p>As i’m experimenting with Rust i’d like to try something useful. Building a simple API and
seeing how it performs against Ruby. Our simple API will return a JSON response like</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>{"first_name": "Hello", "last_name": "World"}
</code></pre></div></div>
<p>Let’s get dirty :)</p>
<h2 id="details">Details</h2>
<p>For both examples i don’t want too much framework overhead that’s why i’m gonna use microframeworks which are pretty close to metal.</p>
<ul>
<li>Rust: <strong><em><a href="https://github.com/nickel-org/nickel.rs/">nickel.rs</a></em></strong></li>
<li>Ruby: <strong><em><a href="https://github.com/soveran/cuba">cuba</a></em></strong>
<ul>
<li>Ruby: Thin</li>
<li>JRuby: Puma</li>
</ul>
</li>
</ul>
<p>First we gonna start with Rust</p>
<h3 id="rust-application">Rust Application</h3>
<p>For Rust implementation we gonna use <strong><em><a href="https://github.com/nickel-org/nickel.rs/">nickel.rs</a></em></strong></p>
<p>Let’s start with creating our project. Since this is not a library we gonna use –bin option.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cargo new rust-json-api --bin
cd rust-json-api
</code></pre></div></div>
<p>To use nickel we need to modify our <strong><em>Cargo.toml</em></strong> file like below.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[package]
name = "rust-json"
version = "0.0.1"
authors = ["Sdogruyol <dogruyolserdar@gmail.com>"]
[dependencies.nickel]
git = "https://github.com/nickel-org/nickel.rs.git"
[dependencies.nickel_macros]
git = "https://github.com/nickel-org/nickel.rs.git"
[dependencies]
rustc-serialize = "*"
</code></pre></div></div>
<p>And to implement our api here’s our <strong><em>src/main.rs</em></strong> file</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">#[macro_use]</span> <span class="k">extern</span> <span class="n">crate</span> <span class="n">nickel_macros</span><span class="p">;</span>
<span class="k">extern</span> <span class="n">crate</span> <span class="n">rustc_serialize</span><span class="p">;</span>
<span class="k">extern</span> <span class="n">crate</span> <span class="n">nickel</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">collections</span><span class="p">::</span><span class="n">BTreeMap</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">nickel</span><span class="p">::{</span><span class="n">Nickel</span><span class="p">,</span><span class="n">HttpRouter</span><span class="p">};</span>
<span class="k">use</span> <span class="nn">rustc_serialize</span><span class="p">::</span><span class="nn">json</span><span class="p">::{</span><span class="n">Json</span><span class="p">,</span> <span class="n">ToJson</span><span class="p">};</span>
<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">server</span> <span class="o">=</span> <span class="nn">Nickel</span><span class="p">::</span><span class="nf">new</span><span class="p">();</span>
<span class="n">server</span><span class="nf">.utilize</span><span class="p">(</span><span class="nd">router!</span> <span class="p">{</span>
<span class="n">get</span> <span class="s">"**"</span> <span class="k">=></span> <span class="p">|</span><span class="mi">_</span><span class="n">req</span><span class="p">,</span> <span class="mi">_</span><span class="n">res</span><span class="p">|</span> <span class="p">{</span>
<span class="k">let</span> <span class="n">person</span> <span class="o">=</span> <span class="n">Person</span><span class="p">{</span>
<span class="n">first_name</span><span class="p">:</span> <span class="s">"Hello"</span><span class="nf">.to_string</span><span class="p">(),</span>
<span class="n">last_name</span><span class="p">:</span> <span class="s">"World"</span><span class="nf">.to_string</span><span class="p">()</span>
<span class="p">};</span>
<span class="n">person</span><span class="nf">.to_json</span><span class="p">()</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="n">server</span><span class="nf">.listen</span><span class="p">(</span><span class="s">"127.0.0.1:9292"</span><span class="p">);</span>
<span class="p">}</span>
<span class="nd">#[derive(RustcDecodable,</span> <span class="nd">RustcEncodable)]</span>
<span class="k">struct</span> <span class="n">Person</span> <span class="p">{</span>
<span class="n">first_name</span><span class="p">:</span> <span class="nb">String</span><span class="p">,</span>
<span class="n">last_name</span><span class="p">:</span> <span class="nb">String</span><span class="p">,</span>
<span class="p">}</span>
<span class="k">impl</span> <span class="n">ToJson</span> <span class="k">for</span> <span class="n">Person</span> <span class="p">{</span>
<span class="k">fn</span> <span class="nf">to_json</span><span class="p">(</span><span class="o">&</span><span class="k">self</span><span class="p">)</span> <span class="k">-></span> <span class="n">Json</span> <span class="p">{</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">map</span> <span class="o">=</span> <span class="nn">BTreeMap</span><span class="p">::</span><span class="nf">new</span><span class="p">();</span>
<span class="n">map</span><span class="nf">.insert</span><span class="p">(</span><span class="s">"first_name"</span><span class="nf">.to_string</span><span class="p">(),</span> <span class="k">self</span><span class="py">.first_name</span><span class="nf">.to_json</span><span class="p">());</span>
<span class="n">map</span><span class="nf">.insert</span><span class="p">(</span><span class="s">"last_name"</span><span class="nf">.to_string</span><span class="p">(),</span> <span class="k">self</span><span class="py">.last_name</span><span class="nf">.to_json</span><span class="p">());</span>
<span class="nn">Json</span><span class="p">::</span><span class="nf">Object</span><span class="p">(</span><span class="n">map</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>I know that you’re pretty much scared after seeing this code :) Well don’t worry this
is a simple JSON API.</p>
<p>To run</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cargo run --release
</code></pre></div></div>
<p>Open your browser and go to <a href="http://localhost:9292">http://localhost:9292</a> to see it yourself :)</p>
<p>That’s it for our Rust implementation.</p>
<h3 id="ruby-application">Ruby Application</h3>
<p>For our Ruby application we gonna use <strong><em><a href="https://github.com/soveran/cuba">cuba</a></em></strong> because it’s pretty close to Rack.</p>
<p>To create our Cuba application we gonna use <strong><em><a href="https://github.com/Sdogruyol/cuba-generator">cuba-generator</a></em></strong>.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gem install cuba-generator
</code></pre></div></div>
<p>Now that we have installed cuba-generator. Let’s create and run our api :)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cuba new ruby-json-api --type api
cd ruby-json-api && rackup
</code></pre></div></div>
<p>I’m not gonna go into the details of Ruby implementation since it’s pretty easy. You can
find the sample application at the links below.</p>
<p>Like the Rust application open your browser and go to <a href="http://localhost:9292">http://localhost:9292</a> to see it in action.</p>
<script src="//www.google.com/jsapi" type="text/javascript"></script>
<script src="/js/chartkick.js" type="text/javascript"></script>
<h2 id="benchmarks">Benchmarks</h2>
<p>I’ve really wondered how Ruby is gonna perform against Rust and that’s why benchmarked the
apps using <strong><em>wrk</em></strong>.</p>
<h4 id="100-connections">100 connections</h4>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>wrk -c 100 http://localhost:9292
</code></pre></div></div>
<div id="chart-100" style="height: 300px;"></div>
<script>
new Chartkick.BarChart("chart-100", [{name: "Request Per Second", data: [["Rust", 69486],["JRuby",27441],["MRI",9483]]}, {name: "Timeout", data: [["MRI", 0],["JRuby", 252],["Rust",271]]}], {max: 100000});
</script>
<h4 id="1000-connections">1000 connections</h4>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>wrk -c 1000 http://localhost:9292
</code></pre></div></div>
<div id="chart-1000" style="height: 300px;"></div>
<script>
new Chartkick.BarChart("chart-1000", [{name: "Request Per Second", data: [["Rust", 63979],["JRuby",26810],["MRI",8913]]}, {name: "Timeout", data: [["MRI", 3314],["JRuby", 2410],["Rust",2982]]}], {max: 100000});
</script>
<h2 id="conclusion">Conclusion</h2>
<p>First of all Rust is really really fast serving nearly <strong><em>70k</em></strong> RPS which is expected given that it’s a compiled language with great performance.</p>
<p>The most surprising thing is that JRuby is really fast when paired with Rack / Cuba serving nearly <strong><em>15k</em></strong> RPS which is a great accomplishment.</p>
<p>Lastly MRI serves around <strong><em>9k</em></strong> RPS on both 100 and 1000 connections. I think the GIL is at fault here.</p>
<p>So Rust or Ruby? Which one do you prefer?</p>
<p>Happy hacking <3</p>
<p><strong><em>P.S:</em></strong> You can find the sample apps on <a href="https://github.com/Sdogruyol/rust-vs-ruby">Github</a></p>
<p><strong><em>Update:</em></strong> I’ve reproduced the Ruby benchmarks with RACK_ENV=production variable and saw more than <strong><em>5x</em></strong> performance increase.</p>Serdar DoğruyolI’ve been itching to write this blog post for a while. Now that Rust is 1.0.0-beta the time has come.Using Cuba to Build Lightweight APIs2015-03-07T09:03:13+00:002015-03-07T09:03:13+00:00https://serdardogruyol.com/using-cuba-to-build-lightweight-apis<p>Nowadays building an API is a really common task. If you’re a Ruby developer chances are really high that you’re already using Rails for an API.</p>
<p>Well using Rails is OK but it’s not your only choice. Also as you may already know Rails is not a perfect solution for a lightweight API. It has lots of dependencies, requires lots of resources e.g.</p>
<p>Luckily there are great alternatives for building lightweight and scalable APIs with Ruby. I’m pretty sure that you’ve already heard about <a href="http://http://www.sinatrarb.com">Sinatra</a> but today i’m gonna be talking about <a href="http://cuba.is">Cuba</a>.</p>
<h2 id="what-is-cuba">What is Cuba?</h2>
<p><strong><em>Cuba is a Ruby microframework for web development.</em></strong></p>
<p>That’s exactly what Cuba is. It’s a really lightweight microframework built upon <strong><em>Rack</em></strong>. The source is less than 500 LOC and pretty easy to grok.</p>
<p>Cuba is simple to use here’s a ‘Hello World’ page</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hello.ru
</code></pre></div></div>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">require</span> <span class="s1">'cuba'</span>
<span class="no">Cuba</span><span class="p">.</span><span class="nf">define</span> <span class="k">do</span>
<span class="n">on</span> <span class="n">get</span> <span class="k">do</span>
<span class="n">on</span> <span class="n">root</span> <span class="k">do</span>
<span class="n">res</span><span class="p">.</span><span class="nf">write</span> <span class="s1">'Hello World!'</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">run</span> <span class="no">Cuba</span>
</code></pre></div></div>
<p>To run</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rackup hello.ru
</code></pre></div></div>
<p>Go to <a href="http://localhost:9292/">http://localhost:9292</a> and see it in action :)</p>
<p>So starting with Cuba is pretty easy no generator, no boilerplate just a simple <strong><em>.ru</em></strong> file and we’re on.</p>
<p>Okay now let’s get to real point.</p>
<h2 id="building-a-json-api">Building a JSON API</h2>
<p>Actually serving JSON is also pretty easy with <strong><em>Cuba</em></strong></p>
<p>Let’s take our first example and modify it a little bit to serve our users as JSON. First of all let’s create a <strong><em>config.ru</em></strong> file for our application so that rackup automatically boots up.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>config.ru ```ruby require './api'
</code></pre></div></div>
<p>run Cuba</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
api.rb
```ruby
require 'cuba'
require 'json'
Cuba.define do
on.get do
on root do
res.write 'Hello World'
end
on 'users.json' do
users = { first_name: 'Serdar', last_name: 'Dogruyol'}
users << { first_name: 'Hakan', last_name: 'Dogruyol'}
res.headers["Content-Type"] = "application/json; charset=utf-8"
res.write users.to_json
end
end
end
</code></pre></div></div>
<p>Now we dont need to specify a file for rackup to boot our application since we created a <strong><em>config.ru</em></strong> file.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rackup
</code></pre></div></div>
<p>Go to <a href="http://localhost:9292/users.json">http://localhost:9292/users.json</a></p>
<p>That’s it now we’re serving our beloved ‘users’ as a JSON API :) Isn’t it awesome ?</p>
<p>You can check the source code of the full sample on <a href="https://github.com/Sdogruyol/cuba-datamapper-sample">Github</a>.</p>
<p><strong><em>P.S</em></strong>: To learn more about <strong><em>Cuba</em></strong> read the <a href="http://soveran.github.io/cuba/">Cuba Book</a> and also be sure to check out <a href="https://github.com/rkh/rack-protection">rack-protection</a> to secure your API.</p>
<p>Happy Hacking <3</p>Serdar DoğruyolNowadays building an API is a really common task. If you’re a Ruby developer chances are really high that you’re already using Rails for an API.Customize Rails Generators to Avoid Generating Unnecessary Files2014-09-13T09:03:13+00:002014-09-13T09:03:13+00:00https://serdardogruyol.com/customize-rails-generators-to-avoid-generating-unnecessary-files<p>As you may already know when you a generate a new resource, model or controller there are bunch of other files that are also being generated for you.
Rails has a great way to customize the default generators as you wish. For example let’s assume that we are creating an API for a mobile app. Let call this app <strong>sample_api</strong>
Let’s create a controller for our <strong>sample_api</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rails g controller posts
</code></pre></div></div>
<p><img src="/images/generator_1.png" alt="Rails Generator 1" /></p>
<p>And you can see the files that are generated for you.
Well since this is an API, We don’t need any assets (Javascript and CSS). Normally we delete that folders but when we generate another resource we need to do the same again. Instead let’s customize our generator to disable those for us.
In our <strong><em>config/application.rb</em></strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>config.generators do |g|
g.stylesheets false
g.javascripts false
end
</code></pre></div></div>
<p>Now let’s see the generator in action again.</p>
<p><img src="/images/generator_2.png" alt="Rails Generator 2" /></p>
<p>Voila :) As you can see assets are no longer being generated for us.
Customizing the generators can really improve our workflow. You can disable unwanted test or spec generation, disable assets or whatever you want. Hell, you can even create your own generators.
Happy Hacking <3</p>Serdar DoğruyolAs you may already know when you a generate a new resource, model or controller there are bunch of other files that are also being generated for you. Rails has a great way to customize the default generators as you wish. For example let’s assume that we are creating an API for a mobile app. Let call this app sample_api Let’s create a controller for our sample_apiUsing ActiveSupport StringInquirer for pretty String equality2014-08-28T06:59:58+00:002014-08-28T06:59:58+00:00https://serdardogruyol.com/using-activesupport-stringinquirer-to-for-pretty-string-equality<p>ActiveSupport is pretty awesome. It has really awesome stuff hidden in it.<strong><em>StringInquirer</em></strong> is one of them.</p>
<p>It lets you test <strong><em>String equality</em></strong> in a much more pretty way. Rails also uses StringInquirer for it’s environment check.</p>
<p>You may recognize this</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Rails.env.production?
</code></pre></div></div>
<p>Instead of doing</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Rails.env == 'production'
</code></pre></div></div>
<p>So how can we use StringInquirer for ourselves.</p>
<p>Let’s pretend that we have a String called status.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>status = ActiveSupport::StringInquirer.new 'is_used'
status.is_used? # true
status.is_new? # false
</code></pre></div></div>
<p>Happy hacking <3</p>Serdar DoğruyolActiveSupport is pretty awesome. It has really awesome stuff hidden in it.StringInquirer is one of them.Convert Hash Key to a Method2014-08-10T12:54:32+00:002014-08-10T12:54:32+00:00https://serdardogruyol.com/convert-hash-key-to-a-method<p>Consider you have a Hash like this or you got a method which returns as a result.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hash = { name: 'Serdar', last_name: 'Doğruyol'}
hash.name # undefined method `name' for {:name;"Serdar", :last_name:"Doğruyol"}:Hash
</code></pre></div></div>
<p>Unfortunately when you try to access the hash key as you would in a normal object you get an ‘undefined method’ error.
Luckily we can solve this easily with some Ruby magic :)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>require 'ostruct'
hash = { ad: 'Serdar', soyad: 'Doğruyol'}
hash = OpenStruct.new hash
hash.ad # Serdar
</code></pre></div></div>
<p>Now you can use your hash as an object and access the keys with method calls.</p>
<p>Happy hacking <3</p>Serdar DoğruyolConsider you have a Hash like this or you got a method which returns as a result.Easily Share Your Localhost with Ngrok2014-06-14T14:31:02+00:002014-06-14T14:31:02+00:00https://serdardogruyol.com/easily-share-your-localhost-with-ngrok<p>Sometimes you want to show a prototype web application that is working on your computer to other people.</p>
<p>The problem is that <strong><em>Deployment</em></strong> is <strong><em>not</em></strong> always that easy.
You ask people to check your app on your local development environment. It’s time consuming and maybe sometimes kinda embarassing.
Enter <strong><em>Ngrok</em></strong>. A tool that allows you to share your localhost to anyone on the internet.
<strong><em>Ngrok</em></strong> is a tiny tool which was written in Go programming language. This means it can be executable in any platfrom ( Linux, Mac OS X, Windows ) without any dependency.
To use <strong><em>Ngrok</em></strong> you can <a href="https://ngrok.com/download">Download</a> the zip file or if you are using Mac you can install via Brew.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>brew install ngrok
</code></pre></div></div>
<p>After installing Ngrok you can share your localhost to anyone.
E.g you have a Rails or Node.js working on localhost:3000 . All you have to do is</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ngrok 3000
</code></pre></div></div>
<p>If it succeeds you’ll see something like below.</p>
<p><img src="/images/ngrok_1.png" alt="Ngrok" /></p>
<p>Voila your app is on the internet and anyone can access it by using the HTTP and HTTPS links that Ngrok generates :)</p>
<p>Happy hacking <3</p>Serdar DoğruyolSometimes you want to show a prototype web application that is working on your computer to other people.Using Stylus Mixins To Stay DRY!2014-02-04T08:53:27+00:002014-02-04T08:53:27+00:00https://serdardogruyol.com/using-stylus-mixins-to-stay-dry<p>I’ve been a long time Stylus user since i’ve started playing with Node.js . Until recently i started to understand the real power of Stylus with Mixins.
Basically Mixins in Stylus are reusable code pieces and rulesets that can be applied to avoid code duplication. This leads to a cleaner and easier codebase to maintain.
Let’s take a look at a simple but powerful Mixin.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>border-radius(n)
-webkit-border-radius: n
-moz-border-radius: n
border-radius: n
</code></pre></div></div>
<p>As you can easily understand from the example these Mixin is a shortcut for handling border-radius with vendor prefixes.<br />
To use this we can simply</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>border-radius(5px)
</code></pre></div></div>
<p>Which translates to</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>webkit-border-radius: 5px
-moz-border-radius: 5px
border-radius: 5px
</code></pre></div></div>
<p>So simple yet so powerful, isn’t it ?
Okay let’s move onto a bit more advanced stuff. What if we want to pass multiple values or an expression as an argument to the Mixin ?<br />
Something like shorthand properties for box-shadow.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>box-shadow()
-webkit-box-shadow: arguments
-moz-box-shadow: arguments
box-shadow: arguments
</code></pre></div></div>
<p>Now this looks interesting. We have a local variable called arguments. In Stylus this is a shortcut for accessing all the parameters that has been passed to the function. Also be aware that we are not using any argument placeholders when defining our Mixin.
For example we can call this Mixin with something like this</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>box-shadow(0 0 2px rgba(51, 51, 51, 0.51))
</code></pre></div></div>
<p>Which translates to</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-webkit-box-shadow: 0 0 2px rgba(51, 51, 51, 0.51)
-moz-box-shadow: 0 0 2px rgba(51, 51, 51, 0.51)
box-shadow: 0 0 2px rgba(51, 51, 51, 0.51)
</code></pre></div></div>
<p>Voila ! We now have two useful Mixins. Pretty enlightening isn’t it? To learn more about Mixins in Stylus. Take a look at the official documentation below.<br />
<a href="http://learnboost.github.io/stylus/docs/mixins.html">Stylus Mixin Documentation</a></p>
<p>Happy hacking <3</p>Serdar DoğruyolI’ve been a long time Stylus user since i’ve started playing with Node.js . Until recently i started to understand the real power of Stylus with Mixins. Basically Mixins in Stylus are reusable code pieces and rulesets that can be applied to avoid code duplication. This leads to a cleaner and easier codebase to maintain. Let’s take a look at a simple but powerful Mixin.