Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SignalR polling database for updates

I'm hoping to use SignalR to provide updates to the client, the updates are going to come from a message table which is updated when things happen across the application..

My problem is that the application will have around 500-600 concurrent users and I cant have all them having a connection to the database and constantly polling against the table..

What id like to do is have a single thing{?} polling the table and then updating the hubs rather than each connection polling.. I was thinking of using a singleton for this? so maybe when the application starts something is created that will then do all the work really..

My question is - say I had a singleton that had an event which was fired every time there was an update.. what would the performance be like for say 500 controllers subscribing to this event?

Also.. if there is a better way to do this then pleases say.. this is my first and only idea sadly!

any help would be fantastic!

EDIT: the data is bring provided by a legacy application and I have no control over how the data is entered so database polling will be needed.

ste.

like image 412
Steoates Avatar asked Jan 14 '13 13:01

Steoates


1 Answers

I'd rather not to poll the database as it would be wasteful. I would approach this problem by opening only one single point of entry for my data (an HTTP API, etc) and then broadcast the update to all connected clients through the SignalR Hub. Brad Wilson has a super cool presentation which demonstrate this approach:

Brad Wilson - Microsoft’s Modern Web Stack, Starring ASP.NET Web API

Here is a code sample for this approach which uses ASP.NET Web API technology for data entry. It uses in-memory dictionary for data store but the data storage technique is not the concern here:

// This hub has no inbound APIs, since all inbound communication is done
// via the HTTP API. It's here for clients which want to get continuous
// notification of changes to the ToDo database.
[HubName("todo")]
public class ToDoHub : Hub { }

public abstract class ApiControllerWithHub<THub> : ApiController
    where THub : IHub {

    Lazy<IHubContext> hub = new Lazy<IHubContext>(
        () => GlobalHost.ConnectionManager.GetHubContext<THub>()
    );

    protected IHubContext Hub {

        get { return hub.Value; }
    }
}

public class ToDoController : ApiControllerWithHub<ToDoHub> {

    private static List<ToDoItem> db = new List<ToDoItem> {

        new ToDoItem { ID = 0, Title = "Do a silly demo on-stage at NDC" },
        new ToDoItem { ID = 1, Title = "Wash the car" },
        new ToDoItem { ID = 2, Title = "Get a haircut", Finished = true }
    };
    private static int lastId = db.Max(tdi => tdi.ID);

    // Lines removed for brevity

    public HttpResponseMessage PostNewToDoItem(ToDoItem item) {

        lock (db) {

            // Add item to the "database"
            item.ID = Interlocked.Increment(ref lastId);
            db.Add(item);

            // Notify the connected clients
            Hub.Clients.addItem(item);

            // Return the new item, inside a 201 response
            var response = Request.CreateResponse(HttpStatusCode.Created, item);
            string link = Url.Link("apiRoute", new { controller = "todo", id = item.ID });
            response.Headers.Location = new Uri(link);
            return response;
        }
    }

    // Lines removed for brevity
}

The full source code for the application which Brad demoed is also available: https://github.com/bradwilson/ndc2012.

The other option, which you don't prefer, is make your database to fire notifications as soon as data is changed. Then, you can pick that up and broadcast it through SignalR. Here is an example:

Database Change Notifications in ASP.NET using SignalR and SqlDependency

like image 71
tugberk Avatar answered Nov 03 '22 23:11

tugberk