<?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>subbu.org</title>
	<atom:link href="http://www.subbu.org/feed" rel="self" type="application/rss+xml" />
	<link>http://www.subbu.org</link>
	<description></description>
	<lastBuildDate>Sat, 28 Jan 2012 18:26:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>ql.io: Consuming HTTP at Scale</title>
		<link>http://www.subbu.org/blog/2012/01/ql-io-consuming-http-at-scale</link>
		<comments>http://www.subbu.org/blog/2012/01/ql-io-consuming-http-at-scale#comments</comments>
		<pubDate>Wed, 25 Jan 2012 01:08:03 +0000</pubDate>
		<dc:creator>Subbu Allamaraju</dc:creator>
				<category><![CDATA[HTTP]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.subbu.org/?p=1719</guid>
		<description><![CDATA[Slides from my workshop on ql.io at the Node Summit. ql.io: Consuming HTTP at Scale View more presentations from Subbu Allamaraju]]></description>
			<content:encoded><![CDATA[<p></p><div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2012%2F01%2Fql-io-consuming-http-at-scale"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2012%2F01%2Fql-io-consuming-http-at-scale&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Slides from my workshop on ql.io at the Node Summit.</p>
<div style="width:425px" id="__ss_11244206"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/sallamar/qlio-consuming-http-at-scale" title="ql.io: Consuming HTTP at Scale " target="_blank">ql.io: Consuming HTTP at Scale </a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/11244206" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/" target="_blank">presentations</a> from <a href="http://www.slideshare.net/sallamar" target="_blank">Subbu Allamaraju</a> </div>
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.subbu.org/blog/2012/01/ql-io-consuming-http-at-scale/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Idempotency Matters</title>
		<link>http://www.subbu.org/blog/2012/01/idempotency-matters</link>
		<comments>http://www.subbu.org/blog/2012/01/idempotency-matters#comments</comments>
		<pubDate>Mon, 16 Jan 2012 09:29:45 +0000</pubDate>
		<dc:creator>Subbu Allamaraju</dc:creator>
				<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.subbu.org/?p=1666</guid>
		<description><![CDATA[Here is an example of how idempotency can save end users a precious second or so. Several weeks ago, one of the teams using ql.io reported that they were seeing random socket hang up errors in server logs. error: { stack: [Getter&#47;Setter], arguments: undefined, type: undefined, message: &#39;socket hang up&#39;, uri: { value: &#39;http:&#47;&#47;clientalerts.ebay.com&#47;...&#39; The [...]]]></description>
			<content:encoded><![CDATA[<p></p><div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2012%2F01%2Fidempotency-matters"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2012%2F01%2Fidempotency-matters&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Here is an example of how idempotency can save end users a precious second or so.</p>
<p><span id="more-1666"></span></p>
<p>Several weeks ago, one of the teams using <a href="http://ql.io">ql.io</a> reported that they were seeing random socket hang up errors in server logs.</p>
<pre><code>error: { stack: [Getter&#47;Setter],
 arguments: undefined,
 type: undefined,
 message: &#39;socket hang up&#39;,
 uri:
  { value: &#39;http:&#47;&#47;clientalerts.ebay.com&#47;...&#39;
</code></pre>
<p>The source of this log was the <code>error</code> handler of the http client</p>
<pre><code>request = http.request(...);
request.on(&#39;error&#39;, function(err) {
    &#47;&#47; log the error
});
</code></pre>
<p>This error was so random that we could not find a reproducer on our dev or testing environments for a while. We then wrote a ql.io script that emulates the production use case, ran that script using <a href="http://www.joedog.org/index/siege-home">siege</a> to emulate the production usage, and captured the traffic using tcpdump. While we were to able to capture a few instances of socket hang up errors with this setup, the tcpdump did not give definite answers as there were too much data to sift through. The client (siege) was making requests in parallel to a cluster of node instances with each instance maintaining its own socket pool. But there were two clues:</p>
<ul>
<li>The origin was closing the connection after some usage by sending a FIN packet, but none of the accompanying HTTP responses included the <code>Connection: close</code> header. This is quite common as connection handling is often done at the reverse proxy tier which may not insert this header in the last response before closing the connection.</li>
<li>The number of new connections opened during the test was a few less than the number of connections closed. This indicates that some requests were being made on closed connections causing the socket hang up errors.</li>
</ul>
<p>This lead us to <a href="https://github.com/joyent/node/issues/1135">Issue 1135</a> &#8211; a timing related issue in node.js where inflight requests made by the client after the FIN packet was sent caused the socket hang up error. The resolution was to retry the request if possible.</p>
<p>HTTP GET, PUT and DELETE requests are retriable in case of such network errors, and the server implementations of these methods are supposed to support such retries.</p>
<p>But here is the rub. There is a lot of bad deployed HTTP server code out in the wild that might choke when a client retries in case of such network errors. Hence, node.js can not retry automatically without some indication from the client application. In the end, we decided to retry the request when an idempotent HTTP request caused by a <a href="http://ql.io/docs/select">select</a> statement encounters network failures such as the above. This helped us save an extra roundtrip from the client to ql.io.</p>
<p>This is a reminder of why idempotency is a necessary promise to keep in HTTP server code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.subbu.org/blog/2012/01/idempotency-matters/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Github and Code Reviews</title>
		<link>http://www.subbu.org/blog/2012/01/github-and-code-reviews</link>
		<comments>http://www.subbu.org/blog/2012/01/github-and-code-reviews#comments</comments>
		<pubDate>Fri, 13 Jan 2012 19:07:27 +0000</pubDate>
		<dc:creator>Subbu Allamaraju</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.subbu.org/?p=1631</guid>
		<description><![CDATA[We all like to do code reviews, but in practice code reviews don&#39;t happen as meticulously as intended. I know of two reasons: Code reviews create extra work. Print outs, folks sitting in meeting rooms in front of laptops, or submitting diffs to a tool are all extra work for the team. Code reviews are [...]]]></description>
			<content:encoded><![CDATA[<p></p><div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2012%2F01%2Fgithub-and-code-reviews"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2012%2F01%2Fgithub-and-code-reviews&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>We all like to do code reviews, but in practice code reviews don&#39;t happen as meticulously as intended. I know of two reasons:</p>
<ol>
<li>Code reviews create extra work. Print outs, folks sitting in meeting rooms in front of laptops, or submitting diffs to a tool are all extra work for the team.</li>
<li>Code reviews are out of band. Though some tools are integrated with source control systems, they are still not part of the commit process. Consequently, they get ignored over time.</li>
</ol>
<p>But since we moved <a href="https://github.com/ql-io/ql.io">our project</a> to github, we have made code reviews a part of the flow without adding extra out-of-band work to anyone in the team.</p>
<p><span id="more-1631"></span></p>
<p>Before we started, code reviews were not our top priority. We had the following goals in stead:</p>
<ol>
<li>Keep the head always stable, tested, and ready for deployment.</li>
<li>Keep the other members in the team abreast of code changes happening. This is particularly needed by newer team members.</li>
<li>Ensure code quality.</li>
<li>KISS and DRY.</li>
</ol>
<p>In order to make these happen, we adopted the following model.</p>
<blockquote>
<p>1. Create repos under an org.</p>
</blockquote>
<p>First create an org in github, and then create a team with with push and pull rights, and add members to the team. </p>
<blockquote>
<p>2. Use forks for development.</p>
</blockquote>
<p>Every member forks the repo, clones the fork, and works against the fork. All code pushes happen in the fork.</p>
<blockquote>
<p>3. Avoid cloning the main repo except for merging purposes.</p>
</blockquote>
<p>Since forks are used for development, there is no need to fork the main repo. To avoid any confusion, if cloning the main repo is required, clone in a temp directory and nuke it after the work is done.</p>
<blockquote>
<p>4. If you make an accidental commit to the master, apologize to the team, and back off your changes.</p>
</blockquote>
<p>This happened early on a couple of times, and we decided that the best course is to back off those changes as soon as possible.</p>
<blockquote>
<p>5. Submit pull requests when ready.</p>
</blockquote>
<p>Once the code is pushed to the fork, submit a pull request.</p>
<blockquote>
<p>6. Let someone else review and merge pull requests</p>
</blockquote>
<p>This is when code reviews happen. Github sends out notifications to the team members when a pull request is made, and someone else in the team reviews and merges the code. Any discussions and comments happen on the pull request page which leave a trace of all discussions for later reference.</p>
<p>Code reviews are an integral part of this flow. We take some additional steps to make code reviews easy and effective.</p>
<ol>
<li>Keep commits and pull requests small. In particular, avoid submitting pull requests that do fix&#47;change more than one thing.</li>
<li>Include tests in each pull request.</li>
<li>In most cases, reject a pull request if there is no test included in it.</li>
</ol>
<p>Large commits usually get less scrutiny due to the mental comprehension load, and the above steps help us pay enough attention to each change.</p>
<p>Thanks to Github!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.subbu.org/blog/2012/01/github-and-code-reviews/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Cluster Example with Node 0.6.x</title>
		<link>http://www.subbu.org/blog/2012/01/cluster-example-with-node-0-6-x</link>
		<comments>http://www.subbu.org/blog/2012/01/cluster-example-with-node-0-6-x#comments</comments>
		<pubDate>Wed, 11 Jan 2012 08:09:02 +0000</pubDate>
		<dc:creator>Subbu Allamaraju</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.subbu.org/?p=1619</guid>
		<description><![CDATA[Here is a quick example to show how to manage an app in a cluster. Node&#8217;s (v0.6.x) cluster API is simple, but it takes a few extra steps to make the cluster management scriptable. The example below shows how. You can then do node cluster-sample.js to start app in a cluster, and then node stop [...]]]></description>
			<content:encoded><![CDATA[<p></p><div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2012%2F01%2Fcluster-example-with-node-0-6-x"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2012%2F01%2Fcluster-example-with-node-0-6-x&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Here is a quick example to show how to manage an app in a cluster. Node&#8217;s (v0.6.x) cluster API is simple, but it takes a few extra steps to make the cluster management scriptable. The example below shows how.</p>
<p><span id="more-1619"></span><br />
<script src="https://gist.github.com/1593337.js"></script></p>
<p>You can then do</p>
<pre>
node cluster-sample.js
</pre>
<p>to start app in a cluster, and then</p>
<pre>
node <app.js> stop
</pre>
<p>to cleanly stop the cluster or</p>
<pre>
node cluster-sample.js shutdown
</pre>
<p>to gracefully shutdown.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.subbu.org/blog/2012/01/cluster-example-with-node-0-6-x/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Announcing ql.io</title>
		<link>http://www.subbu.org/blog/2011/11/announcing-ql-io</link>
		<comments>http://www.subbu.org/blog/2011/11/announcing-ql-io#comments</comments>
		<pubDate>Wed, 30 Nov 2011 17:30:53 +0000</pubDate>
		<dc:creator>Subbu Allamaraju</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.subbu.org/?p=1587</guid>
		<description><![CDATA[I am super-excited for to announce the public release of ql.io today. ql.io is a declarative, evented, data-retrieval and aggregation gateway for HTTP APIs. Simply put, this is our answer to the pain points that I recently described in my APIs are a Pain post. Here are some key points that I want to highlight [...]]]></description>
			<content:encoded><![CDATA[<p></p><div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2011%2F11%2Fannouncing-ql-io"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2011%2F11%2Fannouncing-ql-io&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>I am super-excited for to announce the public release of <a href="http://ql.io">ql.io</a> today.</p>
<p><a href="http://ql.io"><img src="http://66.211.164.71/images/ql.io-large.png"/></a></p>
<p>ql.io is a declarative, evented, data-retrieval and aggregation gateway for HTTP APIs. Simply put, this is our answer to the pain points that I recently described in my <a href="http://www.subbu.org/blog/2011/11/apis-are-a-pain">APIs are a Pain</a> post.</p>
<p><span id="more-1587"></span></p>
<p>Here are some key points that I want to highlight about ql.io.</p>
<p><em>Built on node.js</em></p>
<p>We chose node.js for its evented programming model and a dynamic language. This choice has kept us productive in the last 5-6 months as we built the core from ground up. I would love to share more details about our experience once I have some concrete numbers to show.</p>
<p><em>A SQL and JSON based DSL</em></p>
<p>ql.io uses a SQL and JSON based DSL to write scripts to make HTTP requests. This idea has been tried before, most notably by <a href="http://developer.yahoo.com/yql/">YQL</a>, and in a slightly different context by <a href="http://www.unqlspec.org/display/UnQL/Home">unQL</a>. But ql.io pushes the envelope further by cutting down the coding costs of writing fork-join code. See the <a href="http://ql.io/docs/lang-overview">Language Overview</a> to see how.</p>
<p><em>Procedural style</em></p>
<p>ql.io scripts are procedural looking, but the underlying engine executes them in the best order possible based on a dependency analysis. Consider the script below.</p>
<pre>
a = select a from A;
b = select b from B;
c = select c from C where cparam = "{a.someparam}";
d = select d from D where dparam1 = "{c.someparam}" and dparam2 = "{b.param}";
</pre>
<p>Each statement is scheduled for execution when all its dependencies have been met. This leads to significant reduction in number of lines of code. One of the first apps I built condensed a 300-line Java app into a 10 lines of script.</p>
<p><em>Interoperability</em></p>
<p>My interest in interoperability started with my work at Yahoo! with <a href="https://twitter.com/#!/olympum">Bruno</a>. The challenge was how to ensure that HTTP APIs built by decentralized teams interoperate. The first attempt at this problem was a stick that says &quot;you shall conform to such and such rules, or else &#8230;&quot; But this is not a viable idea. The second attempt involved placing some minimal constraints such as links and identifiers on each API to make them interoperable. While it sounded like a good idea at the time, it has the same problem as the stick.</p>
<p>The challenge with interoperability is how to make the API Web interoperable without introducing new agreements (or protocols) between them. It turns out that we already agreed on some basic protocols such as TCP, HTTP, URIs, XML, JSON and so on on the Web. What if we turn the problem of interoperability from new protocols to software? That is what we tried in ql.io. We made ql.io as a platform that enables interoperability between decentralized HTTP APIs.</p>
<p>ql.io is capable of interacting with any HTTP speaking entity. You got SOAP APIs? Fine! ql.io can speak to it, and mix the response with responses from other APIs that are more conformant to HTTP. Try this <a href="http://ql.io/console?s=keyword%20%3D%20%22ql.io%22%3B%0Aweb%20%3D%20select%20*%20from%20bing.soap.search%20where%20q%20%3D%20%22%7Bkeyword%7D%22%3B%0Atweets%20%3D%20select%20id%20as%20id%2C%20from_user_name%20as%20user_name%2C%20text%20as%20text%0A%20%20from%20twitter.search%20where%20q%20%3D%20%22ql.io%22%3B%0A%20%0Areturn%20%7B%0A%20%20%22keyword%22%3A%20%22%7Bkeyword%7D%22%2C%0A%20%20%22web%22%3A%20%22%7Bweb%7D%22%2C%0A%20%20%22tweets%22%3A%20%22%7Btweets%7D%22%0A%7D">query</a> to find for yourself.</p>
<p>See <a href="http://www.ebaytechblog.com/2011/11/30/announcing-ql-io/">Announcing ql.io</a> for the complete announcement.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.subbu.org/blog/2011/11/announcing-ql-io/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>APIs are a Pain</title>
		<link>http://www.subbu.org/blog/2011/11/apis-are-a-pain</link>
		<comments>http://www.subbu.org/blog/2011/11/apis-are-a-pain#comments</comments>
		<pubDate>Fri, 18 Nov 2011 22:16:16 +0000</pubDate>
		<dc:creator>Subbu Allamaraju</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.subbu.org/?p=1556</guid>
		<description><![CDATA[I don&#8217;t like writing client apps that use APIs. Writing HTTP client code to talk to APIs is verbose, repetitive, chatty and slow. This is in addition to addressing latency and bandwidth constraints and core functionality of the client app &#8211; such as building a snappy UI or supporting some other business use case. First [...]]]></description>
			<content:encoded><![CDATA[<p></p><div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2011%2F11%2Fapis-are-a-pain"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2011%2F11%2Fapis-are-a-pain&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>I don&rsquo;t like writing client apps that use APIs. Writing HTTP client code to talk to APIs is verbose, repetitive, chatty and slow. This is in addition to addressing latency and bandwidth constraints and core functionality of the client app &ndash; such as building a snappy UI or supporting some other business use case.</p>
<p><span id="more-1556"></span></p>
<p><strong>First &ndash; the interface mismatch.</strong> APIs are almost always designed from the producer&rsquo;s point of view. If I&rsquo;m building an API, I would look at my data model, my performance/scalabilty requirements, and design the API to meet the use cases that I think are the most common across all consumers my of my API. That is, my goal would be to maximize the use and reuse of my API. In this process, I am bound to tradeoff special requirements of my consumers and try to stick to a common denominator. This creates a mismatch between what the consumer needs and what I&rsquo;m offering. Here is an example.</p>
<blockquote><p>A client app needs to search a list of products to get their IDs, some details and some user generated content like reviews for each product. There are three APIs that the client needs to interact with to get this data &ndash; one to search products, one to get details for each product, and another to get reviews for each product.</p>
</blockquote>
<p>This is not a made up or hypothetical example. What the client needs is this.</p>
<blockquote><p>A single API, that takes a keyword, and returns certain fields for each product found &ndash; no more or no less.</p>
</blockquote>
<p>What the client got are three APIs that give some data that includes what the client needs plus some more. The API design makes sense for the producers of these APIs &ndash; search folks are focused on indexing and serving low latecny results, the details API wants to serve all the gazillion details that are relevant to products, and the reviews API wants to focus on low latency writes and potentially stale reads. But, for the consumer, an ideal interface is one that gives just the fields it needs with one single request.</p>
<p><strong>Second &ndash; writing client code is slow, repetitive and verbose</strong>. For the above example, here is what the client needs to do:</p>
<ul>
<li>Call the search API to find products, and extract product IDs from the response.</li>
<li>Call the details API <code>n</code> times &ndash; once per product ID &ndash; to get the details, and then extract the fields needed from the response</li>
<li>Call the reviews API <code>n</code> times  &ndash; once per product ID &ndash; to get reviews, and the extract the fields needed from the response</li>
</ul>
<p>Unless you got canned SDKs for these APIs, writing code to make <code>2*n</code> HTTP requests and process the responses can take a while. In one of the Java implementations I looked at, the code was over 300 lines long &ndash; that was after excluding the request making and response parsing code which was already factored into into supporting libraries. If the client needs to implement ten such use cases, you got 3000 lines of code just doing data retrieval.</p>
<p><strong>Third &ndash; Getting enhancements you need from producer teams slows you down</strong>. For my example above, having a bulk API for details and reviews simplifies the client to some extent. But for both good and bad reasons, API changes that the clients need don&rsquo;t happen immediately. They take time, usually some sprints. Sometimes never. The reality is that teams have their own priorities. Getting a single API for the above won&#8217;t likely happen!</p>
<p><strong>Fourth &ndash; requests for use cases like this are chatty.</strong> Three hundred lines of code may not be a big deal, but making so many HTTP requests is. Here is a common evolution of an implementation. To simplify the discussion, let&rsquo;s assume that we have bulk APIs for details and reviews.</p>
<p><em>Take 1:</em> Use blocking IO to make <code>3</code> HTTP requests.</p>
<p><img src="http://www.subbu.org/images/bio.png" alt="BIO" /></p>
<p>Code complexity of this implementation may be low, but it takes <code>sum(t)</code> where <code>t</code> is the time for each API request.</p>
<p><em>Take 2:</em> If latency is a concern, parallelize the requests. After the search API returns product IDs, you can make <code>2</code> requests in parallel and join the responses.</p>
<p><img src="http://www.subbu.org/images/parallel.png" alt="Parallel" /></p>
<p>Code complexity now increases, but it only takes <code>t1 + max(t)</code> for the whole retrieval, where <code>t1</code> is the time taken to search.</p>
<p>Now imagine that the client needs to call yet another API based on review IDs.</p>
<p><em>Take 3:</em> Orchestrate the retrieval based on dependencies.</p>
<p><img src="http://www.subbu.org/images/dance.png" alt="Painful dance" /></p>
<p>In another example I&rsquo;ve seen recently, a native app makes 17 HTTP requests with some dependencies before painting the UI. The code is over 3000 lines long! Of a team of 3 developers, one developer is dedicated to writing and maintaining this code.</p>
<p>Now move the client farther from the API servers. In addition to the code complexity, the client will have to deal with cost of the network. You may want to move all the request dance to some middle tier that is closer to the API servers than the client.</p>
<p><img src="http://www.subbu.org/images/middle.png" alt="Middle tier" /></p>
<p><strong>Fifth &ndash; consistent RESTful APIs don&rsquo;t matter as much as we think.</strong> I would love to see every API to be RESTful, consistent, hypertext driven, and more importantly, interoperable. The reality is that getting consistent APIs is hard &ndash; particularly those that are done by distributed teams. For the record &#8211; I vehemently hate SOAP APIs and the SOAP mindset. I dislike RPC-style operation names tunneled over HTTP. I frown and cringe whenever I see unnecessary custom headers and complicated formats. I wish POST+XML goes away. I wish every API gets rewritten to the modern understanding of HTTP and REST, serving JSON.</p>
<p>But I would rather spend my time enabling interoperability than preaching for consistency.</p>
<p>Hypermedia does not help either. Hypermedia can help navigation among resources, but navigation is not a concern in the above use case. The client app&rsquo;s challenges are aggregation, parallelization, and orchestration of forks and joins.</p>
<p>So, what can we do about it?</p>
<p><img src="http://farm4.static.flickr.com/3208/2884743046_b2e1aafc9f.jpg" width="500" height="334"></p>
<p>Why would I write a long blog post if I have nothing to offer?</p>
<p>I&rsquo;m excited to reveal that, at eBay, my team has been working on a new platform to simplify use cases like the above:</p>
<ul>
<li>Bring down number of lines of code to call APIs</li>
<li>Automatically orchestrate API calls as needed</li>
<li>Create new consumer-centric APIs that wrap existing producer-centric APIs</li>
<li>Cut down bandwitdh usage and latency</li>
</ul>
<p><span style="text-decoration: line-through;">Best of all, this platform will soon be on github. If you are interested in taking a sneak peek and want to provide feedback, please email me (subbu/at/subbu/dot/org) with your github ID.</span> <em>Please see <a href="http://ql.io">ql.io</a> for more info.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.subbu.org/blog/2011/11/apis-are-a-pain/feed</wfw:commentRss>
		<slash:comments>63</slash:comments>
		</item>
		<item>
		<title>WebSocket Fallbacks</title>
		<link>http://www.subbu.org/blog/2011/11/websocket-fallbacks</link>
		<comments>http://www.subbu.org/blog/2011/11/websocket-fallbacks#comments</comments>
		<pubDate>Wed, 16 Nov 2011 14:02:28 +0000</pubDate>
		<dc:creator>Subbu Allamaraju</dc:creator>
				<category><![CDATA[HTTP]]></category>

		<guid isPermaLink="false">http://www.subbu.org/?p=1544</guid>
		<description><![CDATA[For a soon-to-open sourced nodejs based platform that I have been working on since June this year, I needed a way to send some optional telemetry data back to the browser without mixing it with the real data that the client code is interested in. The first thing I looked at was socket.io. Socket.io&#8217;s claim [...]]]></description>
			<content:encoded><![CDATA[<p></p><div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2011%2F11%2Fwebsocket-fallbacks"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2011%2F11%2Fwebsocket-fallbacks&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>For a soon-to-open sourced nodejs based platform that I have been working on since June this year, I needed a way to send some optional telemetry data back to the browser without mixing it with the real data that the client code is interested in. The first thing I looked at was <a href="http://socket.io">socket.io</a>. Socket.io&#8217;s claim to fame is that it aims to &#8220;make real-time apps possible in every browser and mobile device&#8221;. But it comes at certain cost that may not be apparent. Since then I gave up on socket.io and switched to the plain <a href="http://dev.w3.org/html5/websockets/">WebSocket API</a> on the client side and <a href="https://github.com/Worlize/WebSocket-Node">WebSocket-Node</a> on the server. Here is why.</p>
<p>Cross browser WebSocket fallback is a fallacy. Such fallbacks exist because WebSocket support in browsers continues to limp and the spec itself is not done yet. Interoperability among browsers is not yet possible due to lack of protocol parity. For instance, about a month ago, I had to forego supporting Safari in favor of better experience in latest versions of Chrome and Firefox. But what&#8217;s wrong with fallbacks?</p>
<p>WebSocket interactions are bound to a connection &#8211; once the client opens a TCP connection, it can send and receive several messages using the WebSocket API. But with fallback approaches that rely on JSONP, XHR and iframes, clients and servers use HTTP for serializing messages.</p>
<p>Therein lies a key difference. With the WebSocket protocol, you can scope any state for the duration of the connection and remain state free across connections. For instance if you want to send some events as they occur to the browser, you can associate the subscription state with the socket. You don&#8217;t need to replicate that subscription state across all the server nodes that are serving WebSocket traffic. This makes horizontal scalability possible.</p>
<p>Not so with HTTP based fallbacks where every message could potentially come in over a different TCP connection.  To account for this you either need to pin the client to a given node so that the same node handles all connections from a client, or replicate state across all the nodes serving the HTTP traffic. socket.io does the latter by using Redis. Consequently you end up trading off reliability and/or scalability.</p>
<p>This leads to my next point &#8211; if scalability is your concern, graceful degradation may just be sufficient in a lot of use cases. You can use feature detection in browsers to decide whether to use WebSocket protocol or not. Here is a simple approach I now use on the client side.</p>
<p><script src="https://gist.github.com/1370108.js?file=gistfile1.txt"></script></p>
<p>This helps me offer a degraded user experience when WebSocket support is not available, and I don&#8217;t have to introduce shared state on the server.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.subbu.org/blog/2011/11/websocket-fallbacks/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Measuring REST</title>
		<link>http://www.subbu.org/blog/2011/08/measuring-rest-2</link>
		<comments>http://www.subbu.org/blog/2011/08/measuring-rest-2#comments</comments>
		<pubDate>Sun, 21 Aug 2011 16:48:17 +0000</pubDate>
		<dc:creator>Subbu Allamaraju</dc:creator>
				<category><![CDATA[HTTP]]></category>
		<category><![CDATA[REST]]></category>

		<guid isPermaLink="false">http://www.subbu.org/?p=1531</guid>
		<description><![CDATA[These are the slides from my talk yesterday at restfest.]]></description>
			<content:encoded><![CDATA[<p></p><div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2011%2F08%2Fmeasuring-rest-2"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2011%2F08%2Fmeasuring-rest-2&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>These are the slides from my talk yesterday at restfest.</p>
<p><iframe src="http://docs.google.com/viewer?url=https%3A%2F%2Fgithub.com%2Fs3u%2Ftalks%2Fraw%2Fmaster%2Fmeasuring-rest-restfest-2011.pdf&#038;embedded=true" width="600" height="470" style="border: none;"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://www.subbu.org/blog/2011/08/measuring-rest-2/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Awesome Software</title>
		<link>http://www.subbu.org/blog/2011/06/age-of-awesome-software</link>
		<comments>http://www.subbu.org/blog/2011/06/age-of-awesome-software#comments</comments>
		<pubDate>Mon, 13 Jun 2011 04:35:10 +0000</pubDate>
		<dc:creator>Subbu Allamaraju</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.subbu.org/?p=1523</guid>
		<description><![CDATA[Every other new OSS project is now awesome, fast, robust or even battle-hardened. If you really want your OSS project to outlive a swarm of retweets over a day, here is some advice: Think of some concrete scenarios to help us understand what is awesome/fast/robust/whatever about your stuff. Write tests for those scenarios. Publish your [...]]]></description>
			<content:encoded><![CDATA[<p></p><div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2011%2F06%2Fage-of-awesome-software"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2011%2F06%2Fage-of-awesome-software&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Every other new OSS project is now <a href="http://twitter.com/#!/search/awesome%20node">awesome</a>, <a href="http://msgpack.org/">fast</a>, <a href="http://expressjs.com/">robust</a> or even <a href="http://blog.nodejitsu.com/http-proxy-intro">battle-hardened</a>. If you really want your OSS project to outlive a swarm of retweets over a day, here is some advice:</p>
<ul>
<li>Think of some concrete scenarios to help us understand what is awesome/fast/robust/whatever about your stuff.</li>
<li>Write tests for those scenarios.</li>
<li>Publish your results and provide as many details as you can about your tests.</li>
<li>Finally, publish the source code for your tests.</li>
</ul>
<p>I&#8217;m sure that this is hard-work &#8211; but you want us to clone your project, or even fork it &#8211; right?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.subbu.org/blog/2011/06/age-of-awesome-software/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>MessagePack Anyone?</title>
		<link>http://www.subbu.org/blog/2011/06/messagepack-anyone</link>
		<comments>http://www.subbu.org/blog/2011/06/messagepack-anyone#comments</comments>
		<pubDate>Thu, 09 Jun 2011 22:33:30 +0000</pubDate>
		<dc:creator>Subbu Allamaraju</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.subbu.org/?p=1508</guid>
		<description><![CDATA[I came across MessagePack from multiple sources in recent weeks. MessagePack claims to be a &#34;binary-based efficient object serialization library&#34;. The bar chart on MessagePack&#8217;s site claims that MessagePack is four timers faster than JSON serialization and deserialization. Really? If true, it is able to optimize for both speed and space at the same time. [...]]]></description>
			<content:encoded><![CDATA[<p></p><div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2011%2F06%2Fmessagepack-anyone"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.subbu.org%2Fblog%2F2011%2F06%2Fmessagepack-anyone&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>I came across <a href="http://msgpack.org/">MessagePack</a> from multiple sources in recent weeks. MessagePack claims to be a &quot;binary-based efficient object serialization library&quot;. The bar chart on MessagePack&#8217;s site claims that MessagePack is four timers faster than JSON serialization and deserialization. </p>
<p>Really? If true, it is able to optimize for both speed and space at the same time. I needed to find out. I did a quick test using <a href="http://twitter.com/#!/pgriess">@pgriess</a>&apos;s <a href="https://github.com/pgriess/node-msgpack">node-msgpack</a> implementation for Node (if you&#8217;re using recent versions of Node, use the fork <a href="https://github.com/jmars/node-msgpack">https://github.com/jmars/node-msgpack</a> in stead). Here are the numbers for 18k of JSON for a total of 10000 test runs on Node v0.4.8 on Ubuntu.</p>
<pre>
msgpack pack:   12705 ms
msgpack unpack: 1668 ms
json    pack:   1575 ms
json    unpack: 1271 ms
</pre>
<p>For this size, MessagePack&#8217;s serialization is roughly 8 times slower than v8&#8242;s JSON serialization. Here are the results of a very small piece of data (48 bytes &#8211; same as the one used by Peter&#8217;s <a href="https://github.com/pgriess/node-msgpack/blob/master/bench.js">bench.js</a>) for 10000 runs.</p>
<pre>
msgpack pack:   108 ms
msgpack unpack: 69 ms
json    pack:   31 ms
json    unpack: 19 ms
</pre>
<p>In other words, I&#8217;m unable to reproduce <a href="https://github.com/pgriess/node-msgpack">Peter&#8217;s numbers</a>. The differences are likely due to changes in Node and v8 since the time Peter did his tests. You can try it out yourself by doing the following:</p>
<pre>
git clone https://github.com/jmars/node-msgpack
make
# before the next step, edit bench.js to require lib/msgpack
node bench.js
</pre>
<p>This is no good. There are other features that concern me as well. It is not clear why the developers of MessagePack chose to bundle together RPC (an application issue), pipelining (a protocol level issue), connection pooling (again an application issue) etc with a format design.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.subbu.org/blog/2011/06/messagepack-anyone/feed</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
	</channel>
</rss>

