Real-Time Services Talk & Demo Update

At the 2012 Esri Developer Summit, we gave two talks on building real-time apps – the first used Node.js and Socket.io, and persisted the data to a feature service. The second used ASP.NET MVC and SignalR, and stored the data points in a simple SQL table with x,y values.

During the talks we invited the ~100 people in the room to beat up the apps, and here’s what we found.

First – both services withstood the inbound load without issue.

Node.js and Socket.io

Demo site: http://node.dtsagile.com

This was running on an AWS Micro-Instance, and there were no issues handling the load. Over the 4 hours from when we opened it up, 999 points were added to the system.

In the first 10 minutes, 780 points were added, and looking at the timestamps we had several points where there were 10, 12 15 points added per-second. Not bad for a wee little instance! Here’s a screen cap from Brian Noyle’s phone after the session was over. Down to 3 users, but you can see all the points stacked up.

Node loaded

What we did find is that once there were a lot of points, the system hit a snag querying them back out and sending them to the clients. Although we could have had the clients query the ArcGIS Server FeatureService directly, part of the experiment was to do that work in Node, and then push the features to the client. This all worked smoothly except the FeatureService got slower as the number of points went up (we are still looking at why this is), and the timeout in the Node xhr request was set to be 1 second. Thus, the request timed out, and newly connecting clients did not get the “current” crop of points. Newly added points worked just fine.

At this point things are working smoothly again – and that’s because the query only pulls points added in the last 24 hours, and there are very few points added on any given day. I have not had any time to replicate the issue, but I expect that extending the timeout would fix things. A better idea would be to cache the data in something like Redis, and then lazy-write it into a geodatabase or feature service – maybe there would be a second or so lag between the two, but I think the user experience would be better.

code: https://github.com/dtsagile/dmg-express

ASP.NET MVC and SignalR

Demo site: http://signalr.dtsagile.com

This was running on a server in our Fort Collins office, and although overloaded, it’s a pretty powerful box, so there were no issues with the load. Over the first 4 hours, 536 points were added to the system. In the first 10 minutes, 426 were entered, with a peak of 5 per second. We can’t compare this directly to the numbers for node as there is now way to tell if more or less people were entering data. However, we can safely say that the server easily handled this load.

This version of the app simply stored the points in a SQL table with x,y values, and interestingly there was no issue with scaling this up – mainly because there was no xhr in the mix to time out, and because direct sql access is much faster than going through a feature service, which then hits the database.

code: https://github.com/dtsagile.com/dmg-signalr

Videos of the Talks

We recorded screencasts of the talks as we gave them, and they are now up at Vimeo.

Node & Socket.IO:  http://vimeo.com/dtsgis/realtime-node

SignalR & ASP.NET MVC: http://vimeo.com/dtsgis/realtime-signalr

Posted in asp.net mvc, DevSummit, NodeJs | Tagged , , | Leave a comment

HTML5 Webinar April 11th, 2012

HTML5

After years of being told we should use plug-in technologies such as Flex or Silverlight for our web applications, the seemingly sudden switch to HTML5 has left developers and organizations with many questions…

  • What is HTML5?
  • How does Javascript fit into this?
  • When should we stick with plug-ins?
  • When should we use HTML5?
  • What is CSS3 and how can we use that to create amazing interactions?
  • How do we serve different versions of an app to different clients?

On April 11th, 2012, Brian Noyle and I are doing a URISA webinar where we will cover how DTSAgile builds geospatial HTML5 apps that work on desktops, tablets and smart phones. We’ll be covering a lot of ground in this fast-paced talk that is aimed at both developers and managers.

Registration: http://www.urisa.org/URISAConnectGISinMobileEra

 

 

 

 

Posted in HTML5, javascipt | Tagged , , , | 3 Comments

DevSummit Presentations

Just a quick post about the presentations we (DTS) are giving at the 2012 Esri Developer Summit

Talking Tech: Presentation Zen for Everyone

1pm Wednesday, Mojave Learning Center (Dave Bouwman and Brian Noyle)

Let’s face it, most technical presentations leave a bit to be desired. Myself and Brian Noyle will talk about our journey from power-point hell to something better. We’ve got ~100 slides and 30 minutes, so join us for a fun session that will make your next presentation rock.

Zen peek2

 

Have a Little BackboneJS

4:30pm, Wednesday, Mojave Learning Center (Brian Noyle and Mike Juniper)

This fast paced talk will introduce the GIS community to the Backbone.js framework in the context of existing ESRI web technologies.  We’ll start with some MVC and HTML 5 love and explain the Backbone.js code structure and implementation pattern with a focus on maintainability and unit testing.  We’ll take a few ESRI examples from the JavaScript API and show developers how to implement them using Backbone.js. We’ll also look at a large and complex development initiative and illustrate how Backbone.js has made our lives easier.

 

Getting Real-Time Part -1: Node.js and Socket.io

10:15am Thursday, Mesquite B (Dave Bouwman)

Some scenarios (i.e. zombie flash mobs) require the ability to keep all users view of the data in sync, in real-time, without requiring an update or page refresh. In this talk we will look at a simple demo application the DTSAgile team created to investigate real-time technologies. This Damage Assessment demo app uses real-time communication to allow users (desktop or mobile) to share real-time “state” as different types of assessments are completed. The idea being that when an “injury” is reported, appropriate medical teams can be dispatched to the location.

Node peek

In this part, we will show a simple node.js app that uses socket.io to send notifications between clients and the server, as well as sending the point locations to an ArcGIS Server feature service. Bring your notebook/iPhone/iPad/Android devices and let’s see how many sessions we can run on an AWS micro instance before we crash the wireless network, or overload the server!

Code: http://github.com/dtsagile/dmg-express

 

Getting Real-Time Part -2: ASP.NET MVC and SignalR

11:00am Thursday, Mesquite B (Mike Juniper)

In this session, Mike Juniper will show how to implement the same Damage Assessment demo app, but this time, working on the Microsoft platform, using ASP.NET MVC and the fast evolving SignalR library.  Finish out the Dev Summit with a bang and go back home armed with ideas on how to easily add real-time capabilities to your existing apps.

Code: https://github.com/dtsagile/dmg-signalr (coming soon!)

 

Posted in Conferences, DevSummit, Esri, javascipt, NodeJs | Tagged , | Leave a comment

Server Side Clustering: Why you need it

It’s been almost 4 years since I posted about using server side clustering to make point maps wicked fast, and we’ve used this same technique on 4 or 5 projects since then. Today, as I was catching up on actually reading the tweets I’d favorite-ed over the last few weeks, I came across a site that really shows a scenario where this technique would massively help.

Before I get into this – I’m not trying to point fingers and call anyone out on this, I’m simply trying to show a technique that can really help make your maps fast.

Ok – the site is “Climate Change and African Political Stability” and it’s at http://ccaps.aiddata.org/ . I got to it from a blog post titled “Crisis Mapping Climate Change, Conflict and Aid in Africa”, and when I first saw the screen cap in the blog post, I thought it looked like something by DevelopmentSeed or Vizzuality. So, yeah, the site looks good. Here’s the screen cap on first load…

Initial Load

Cool! So it’s using the Esri Javasctipt API, and some fancy client-side clustering. What I could not get in the screen cap is that the little clusters have fly-out “octopus” arms depicting how many items are in the cluster. Very cool.

The intent of the app is to have the users manipulate the slider at the bottom to look at changes over time. So, when the app first loads, we are looking at data for 2010.

Whenever I see clustered data like this, I’m curious to see what’s on the wire… so a quick peek into Firebug tells another part of the development story…

Fb 1

The line I high-lighted is a little hard to see, but the key things are POST, 343k and 3.6 seconds. First off the POST is kinda hokey, to say nothing of turing the stomach of every RESTafarian around. Why? Because POST is meant to CREATE or UPDATE data… queries should be done with GET my friend. And, no one else can POST to that url, to get the data. Maybe that’s by design – I’m not sure. The next two numbers are really performance indicators, and really not too bad, but let’s look at what’s actually coming down.

Fb 2

The actual object does not see to have a much extraneous info, which is good, and 343k is not far off the size of a map tile, so it’s all good right?

So, here’s where I’m gonna start making suggestions… using long property names is wasteful. Being a nerd, I grabbed the response data, stuffed it into an editor, and started hacking. Changing the properties to be much more concise (lat,lng,did,et,ed,a1,a2,c,l corresponding to the items in the order shown above) drops almost 1/3 of the file size – down to 260K.

But really, there is another way to shrink that down that’s much much more effective. You see, there are 1418 data points coming down in that package. To show then effectively on the map, they have to be clustered, or the map would be a total schear of points, and be impossible to make sense of. Looking at the map, we are seeing *maybe* 30 points total? So that means that we have an extra 1388 data points on the wire. We could make exactly the same map, with roughly 0.03% of the data on the wire. And you know what that means? The app will be monstrously faster.

“But Dave, a few seconds when the page loads – who cares?” Ah, yes, but let’s get back to the point of the app – to look at this data over time. And not just at different points in time, but aggregated over time. What say we slide that date back to 2003 shall we? Go ahead, try this… I’ll wait…

Impatient? Ok, here’s what you’ll see if it finishes loading…

Ccaid 2

Kinda similar eh? I moved the map a bit for this screen cap, but really we see pretty much the same thing – approximately 30 points. Except for that heinous lag while it loaded, the map is pretty much the same. And what does Firebug tell us? Yeah – that huge lag was what happens when you jam 5MB of JSON down the wire. That little hack using short property names to save 30% doesn’t look so stupid now does it ;-)

Fb 3

And the load time on that? 1 minute, 18 seconds. Firebug did not even JSONify the payload, but swaging is based on file-size, this is somewhere around  25,000 points. And in the end the map shows 30 points? Right.

A Better Way…

Server-side clustering is the solution here. Based on the Url’s we are seeing in FireBug, I’m guessing that this data is stored in a simple tabular database, which makes things even easier. But first a demo…

Conveniently, we launched a site last week which shows server-side clustering in action. Check it out at http://maps.saferoutesinfo.org. Basically it’s a map of the projects which have been funded by Safe Routes to School – if there are no projects in your area, contact your school board and congress person.  Anyhow, the data covers 6 years, and has roughly of 13,000 data points.

Srts 1

What’s great about this clustering solution is that the payload on the wire is small, and stays small. We load the map with the “worst case scenario” – all types of awards, for all years, for the entire country. Payload is close to the other app, at 211Kb, 1.4 seconds and we are showing 450 points. If you go poking into the JSON, you’ll see that we were under a time-crunch to get this live, so it’s not optimized – we could likely save another 20% by dropping extra / unused attributes. Speaking of Url, this is a simple REST service so you can run this same query using this link.

The idea here is to store the data in a normal SQL table, send in the bounding box and use that in a simple SQL query to get all the points currently in the map. We then cluster the points, JSON that up and shoot it back. The only downside here is that we need to re-fetch the points every time we pan or zoom. But given the fact that the points are often rendered before the map tiles come down, this does not seem to be a performance issue.

The clustering is based on a 22 pixel square at the current zoom resolution, so we never get back any more than 1 point for every 20×20 pixels of map space.

What’s more, we can do some interesting stuff – in this app, we have 3 types of funding “awards” – School Awards, District Awards and State-wide Awards. If a cluster contains only schools, we use the green cluster icon. If it has 1 or more District Awards, it gets the blue cluster icon, and if there is a State-wide award in there, we show the gold icon. I’m mentioning this because the gist I posted has this logic in there – if you just want to show points, you’ll need to rip out that extra logic.

Since  I’m running on the el-cheapo WordPress.com hosting, I can’t embed the gist of the code, but you can get it here: https://gist.github.com/2188210

Summary

I hope this shows why server side clustering is a killer way to build really fast web apps. In the end, you can have great design, great data, a great story, but if the app is slow, all that work is lost.

Also – if you are the developer/project manager/benevolent overlord/in-any-way-associated with the Climate Change and African Political Stability App, I encourage you to get in touch – although it looks like you are not using ASP.NET, I am more than willing to help you work through converting the C# over to whatever you are using. The site tells an important story, and it deserves to be told well.

Posted in ArcGIS Server, C#, Uncategorized | Tagged , | 3 Comments

Changing Gears for 2012: Getting Real with Rails

For the last few years, I’ve occasionally “dabbled” with Ruby on Rails, even spoken about it at conferences, but never really stuck with it to any real extent. I’d always be catching glimpses of the supposed unicorns and rainbows, but would then get tripped up on some trivial syntax thing, and spend and hour Googling, and then bail and revert to .NET because it was just easier.

Given that I’d likely have an aneurysm if I paid any attention to the electoral insanity of the next 11 months, I’m opting to spend my evenings and weekends getting real with Rails. And I’ll be  blogging about my adventures along the way.

What about .NET and Esri? Are you going all FOSS?

In a word no. DTS is and will remain a .NET shop, and we’ll still be cooking ASP.NET MVC apps backed with  Esri technology, and I’ll still be blogging and speaking about that stack (some cool stuff is coming at 10.1 but can’t talk about it yet!). My interest in Rails is mainly to get another perspective on web development, and to see how well it works. I’ve got a few non-spatial ideas kicking around, and I want to use them as a platform for learning Rails. There may come a time when we start doing project work on Rails, but that will be a ways out.

That said, if I could avoid the hell that is the Microsoft Volume Licensing site, I’d be more than a little happy ;-)

“Getting Started With Rails” Resources

There are a ton of resources out there to get you going – here are some that I found useful:

Glenn Goodrich (@ruprictgeek) has an on-going series at RubySource.com – I literally got my Mac setup with Rails using this post on RVM. His series continues and is integrating Backbone.js and some geospatial flair using leaflet, but I had to take a side journey into Ruby 101 and Rails.

The day after I got RVM setup, Rob Conery tweeted about $100 off an annual subscription to Tekpub.com. I love love love the This Developers Life podcast which Rob edits, and I knew that Tekpub had a Rails 3 series ($28 if you just want that series), so it was an easy sale. Over the break I managed to watch 9 of the 11 videos in that series, and I have to say they are really good in terms of giving you a mix of theory and practice. Rob shows how to use scaffolders, and then how to do it “better”. There is quite a bit on testing in here, using the built in test tools as well as rspec. Other goodies covered include generators, haml, factory_girl, cheat, devise and autotest. Rob also mixes it up doing some episodes using VIM, others in Textmate, and others in RubyMine. Some on Linux and some on Mac. Quality work sir!

I really enjoyed a NetTuts video called “The Intro to Rails Screencast I Wish I Had” and is presented by Jeffery Way. Once you have a general understanding of Rails 3, this is a great 45 minute overview of how it all goes together, doing TDD and not using any scaffolding. It also goes into Capybara, which is wicked slick if you’ve ever tried to do any front-end testing. I’m definitely going to check out more NetTuts Rails stuff.

I also got the Kindle version of “The Ruby Programming Language” book for the whopping sum of $5.98. I’ve been reading this in chunks mainly as a means to get my mind into reading ruby code, and thus “knowing” how to express my intent in the language.

While I strive to be “all digital”, having cheat-sheets lying around is always helpful, so I’m compiling a list of useful ones that I’ll post sometime soon.

So that’s it for now. I’ve got a lot of ideas on things I want to built, and at this point I merely have an idea of how much I don’t know (linux, nginx, postgres), but I think it’s gonna be a fun journey!

Posted in Rails | Tagged | 5 Comments

Handling Circular References ASP.NET MVC Json Serialization

I love the Entity Framework CodeFirst stuff, combined with scaffolding, it makes development go so fast. Fast that is until you drop an API into the mix and want that to serve Json.

Here’s my EF Model. Lots of lovely navigation properties allowing me to get from any entity to any other one. Handy-dandy in .NET land…

models

But no-bueno when serializing using the out of the box Json serializer…

[HttpGet]
public JsonResult Get(int id)
{
    return Json(itemcategoryRepository.Find(id), 
        JsonRequestBehavior.AllowGet);
}

Now, this sucks because how awesomely elegant is that code? What you get is an error like this:

A circular reference was detected while serializing an object of type ‘System.Data.Entity.DynamicProxies.ItemCategory_A79…’.

Json Serialization Options

There are a few ways to go here – you could use ViewModels everywhere and sloppy-copy properties across as needed. Even with Automapper to take the drugery out of this, it rubs me the wrong way – what’s the point of using EF if I still have to have a separate set of Poco ViewModels?

Another option is to add a .ToJson method to the EF classes, and emit strings. Lots of control, but… meh.

Using Json.net comes up a lot, but it’s also labor intensive.

What I ended up doing is using Linq to project the EF object graph into an anonymous object graph. Here’s an example that serializes two levels of objects (a list of ItemCategories, each of which can contain a list of Items – see the object model above)

[HttpGet]
public JsonResult List()
{           
    var data = itemcategoryRepository
        .AllIncluding(itemcategory => itemcategory.Items);
    //Project into anonymous objects because Serializers
    //can't handle circular refs in the EF magic
    var collection = data.Select(x => new
    {
        id = x.Id,
        name = x.Name,
        items = x.Items.Select(item => new
        {
            id=item.Id,
            name = item.Name
        })
    });
    return Json(collection, 
        JsonRequestBehavior.AllowGet);
}

I like this solution because I have control of the Json in the controller, rather than forcing an object to always serialize the same way in all cases (sometimes I want the Item to serialize it’s Entries, but only when I’m getting a single Item).

Posted in Uncategorized | 8 Comments

ASP.NET MVC3 and 404’s for Area Controllers

So I’m a big fan of ASP.NET MVC, and the general idea of convention over configuration, but I spent a few hours late last night fighting with something, and the Google was no help, so hopefully this helps someone else…

The situation:

I have ASP.NET MVC3 project, and I created an Area for my json API.  In my area I create a simple controller called CategoriesController, and I registered some routes in my AreaRegistration…

//handles get for a list of all categories
context.MapRoute(
    "ListCategories",
    "API/Categories",
    new { controller = "Categories", action = "List" }
);

I used the very awesome MvcRouteUnitTester (on Nuget) to write unit tests to make sure this route was working. All systems go!

Before I started writing tests against the actual controller, I used a browser to hit http://localhost/myapp/API/Categories – which should match this route, and spit back some “hello world” json. I get a 404.

Even with the unit tests, I decided to pull in the RouteDebugger NuGet package, just to make sure that the routes were working, and that showed that all was good

routes

So, I’m stumped. No Exceptions, everything seems to line up, but still a 404.

After about 15 minutes of useless Googling, I remember that I’ve got logging setup in this project, and that’s in my Global.asax.cs and tied into Application_Error…

protected void Application_Error()
{
    Exception lastException = Server.GetLastError();
    var logger = DependencyResolver.Current.GetService<ILogger>();
    logger.Fatal(lastException);
}

SO I look in the log… and find this error

The controller for path ‘/statsme/API/Categories/List’ was not found or does not implement IController.

(full trace because this will help Google index this when others go lookin)…

Message :The controller for path '/statsme/API/Categories/List' was not found or does not implement IController.
Source :System.Web.Mvc
Stack Trace :   at System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType)
   at System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName)
   at System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory)
   at System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<BeginProcessRequest>b__2()
   at System.Web.Mvc.SecurityUtil.<>c__DisplayClassb`1.<ProcessInApplicationTrust>b__a()
   at System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust[TResult](Func`1 func)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
TargetSite :System.Web.Mvc.IController GetControllerInstance(System.Web.Routing.RequestContext, System.Type)

Ok, WTF? CategoriesController inherits from a BaseController which inherits from Controller, so we’re clear on the IController bit. I know the class is there… what is going on?

Google… Google… more Google. Random hacking… cursing… Ah HA!

The issue was the namespace on my controller. Turns out that MVC has a convention that the area name is expected to be in the namespace of the controller.

So – I had StatsMe.API.CategoriesController, but MVC was looking for StatsMe.Areas.API.CategoriesController.

What finally tipped me off was some stuff in the RouteDebugger output…

namespaces

Annoying because the error message really could have helped out by saying “Hey – I’m looking for StatsMe.Areas.API.CategoriesController and I can’t find it”, rather than the very generic message it spit out.

Configuration Overriding Convention

As we all know, in MVC where there is a convention, there is a way to override this, and that’s in the route definition… like so…

context.MapRoute(
    "ListCategories",
    "API/Categories",
    new { controller = "Categories", action = "List" },
    new[] { "StatsMe.API.Controllers" } 
);

Viola! Hope this helps someone else avoid a few hours of frustration.

Posted in asp.net mvc | 8 Comments