In many of the examples I've seen, such as the StockTicker app, it's assumed that all clients would be interested in the updates to all stock prices...
I'm trying to determine a best practice for when a client only cares about a subset of updates...
Would I:
broadcast all updates to all clients, and let the clients determine
"if they care" in the client method?
register with each client connection the "items of
interest" and maintain a client connection table somewhere,
broadcasting iteratively to all clients which have expressed that
interest?
Create a SignalR Group for every stock (for example), and
register clients to each particular stock-group "of interest" and
broadcast only to a particular group during an update of the related
stock?
something else I'm missing...
In an effort to make this question less subjective, what are the pitfalls of each of the above scenarios (rather than "which do you like better?")?
Thanks gang.
"Would I:"
"broadcast all updates to all clients, and let the clients determine "if they care" in the client method?"
This solution is probably the simplest to implement and reason about. Unfortunately, this solution also creates the most network traffic. It also may be considered insecure in some scenarios where the messages being sent are sensitive and should be hidden from some clients.
"register with each client connection the "items of interest" and maintain a client connection table somewhere, broadcasting iteratively to all clients which have expressed that interest?"
This seems fairly similar to SignalR groups in concept, but broadcast iteratively to individual clients typically isn't as efficient as broadcasting to a group. This is primarily because SignalR only has to publish one message to its bus per group broadcast.
Still, you might want to maintain a "client connection table" containing the "items of interest" for each client even if you end up using the built-in SignalR groups functionality. SignalR only allows you to add/remove clients to/from a group and broadcast to a group, so if you want to find out who's currently in a group you are going to have to track that yourself.
If you do maintain your own table, you can avoid sending messages you know no client is currently interested in. You could also automatically resubscribe clients to their items of interest when they leave and come back.
"Create a SignalR Group for every stock (for example), and register clients to each particular stock-group "of interest" and broadcast only to a particular group during an update of the related stock?"
This would be my choice. Groups align naturally to "items of interest". Given your scenario, I don't see much of a downside, particularly if you also maintain your own "client connection table" as well.
"something else I'm missing..."
I think you covered the three basic options.
Related
This is a theoretical question.
imagine an aspnet website. by clicking a button site sends mail.now:
I can send mail async with code
I can send mail using QueueBackgroundWorkItem
I can call a ONEWAY webservice located in same website
I can call a ONEWAY webservice located in ANOTHER website (or another subdomain)
none of above solutions wait for mail operation to be completed.so they are fine.
my question is why I should use service solution instead of other solutions. is there an advantage ?
4th solution adds additional tcpip traffic to use service its not efficient right ?
if so, using service under same web site (3rd solution) also generates additional traffic. is that correct ?
I need to understand why people using services under same website ? Is there any reason besides make something available to ajax calls ?
any information would be great. I really need to get opinions.
best
The most appropriate architecture will depend on several factors:
the volume of emails that needs to be sent
the need to reuse the email sending capability beyond the use case described
the simplicity of implementation, deployment, and maintenance of the code
Separating out the sending of emails in a service either in the same or another web application will make it available to other applications and from client side code. It also adds some complexity to the code calling the service as it will need to deal with the case when the service is not available and handle errors that may occur when placing the call.
Using a separate web application for the service is useful if the volume of emails sent is really large as it allows to offload the work to one or servers if needed. Given the use case given (user clicks on a button), this seems rather unlikely, unless the web site will have really large traffic. Creating a separate web application adds significant development, deployment and maintenance work, initially and over time.
Unless the volume of emails to be sent is really large (millions per day) or there is a need to reuse the email capability in other systems, creating the email sending function within the same web application (first two options listed in the question) is almost certainly the best way to go. It will result in the least amount of initial work, is easy to deploy, and (perhaps most importantly) will be the easiest to maintain.
An important concern to pay significant attention to when implementing an email sending function is the issue of robustness. Robustness can be achieved with any of the possible architectures and is somewhat of an different concern as the one emphasized by the question. However, it is important to consider the proper course of action needed if (1) the receiving SMTP refuses the take the message (e.g., mailbox full; non-existent account; rejection as spam) and (2) an NDR is generated after the message is sent (e.g., rejection as spam). Depending on the kind of email sent, it may be OK to ignore these errors or some corrective action may be needed (e.g., retry sending, alert the user at the origination of the emails, ...)
We currently evaluating solutions for implementing server-sent events (not neccecarily using the Server-Sent Events EventSource Transport).
Our use case is actually quite similar to Stackoverflow. We've got a custom CMS implemented as SPA that supports collaborative editing. As first step we want the server inform all clients on the same page when another user has modified it.
The obvious choice would be chosing SignalR for this but this statement on XSockets's comparison page got me thinking:
If a framework broadcasts data to all clients connected we have just
inverted the AJAX issue and now we have a server hammering clients
with information they do not want.
Is this still true with SignalR 2? I mean wouldn't broadcasting to all clients regardless of group membership make groups totally useless in the first place?
Some Stats:
> 10000 active users
> 10000 pages
A message sent to a group in signalr will only arrive at the clients in that group. So there is no need to worry about broadcasting if you use groups.
Groups are smart until you you have to do something like #Lars Höppner describes, groups are not dynamic and they are really just a very simple subscription. It is just like having pub/sub where you say that you are subscribing to a topic "A" but in SignalR you are a member of a group "A" instead.
If you do not use groups signalr will broadcast, that can be ok but consider this.
You have 2 pages "A" and "B", they both connect to the Hub "MyHub".
When you send a message to all clients from "MyHub" to the method "MyMessage" and only the page "A" has implemented a client-side method for "MyMessage" the clients on page "B" will still get that message sent to the browser if you look in the frames tab (in chrome)
So messages will arrive at clients not interested in the message, not a big deal until you get a lot of clients or send sensitive data.
If you never connect to the same hub from 2 different pages you will be fine. And if you always use groups you will also be fine. Otherwise you will have to think about where the messages will arrive!
Of topic:
- My favorite thing about signalr is the nice transports!
- The worst thing about signalr is that they have transports due to the fact that they have desgined it thinking that websockets is a OS feature (win8 2012 server to get websockets)
When you send messages to a group, the clients that aren't in the group don't receive the message. This is based on a pub/sub model on the server (so when you use groups, it's not the client that decides whether it's interested in the message), so there is no "hammering all clients" going on in that case.
I think what the XSockets team is talking about in this paragraph is that with XSockets, you have more fine-grained control over who to send messages to. So instead of sending to a group with a specific name (which you have to create first), you can send to clients with certain properties (sort of like a dynamic group):
But what happens if you want to send to all clients within the range
of x km from y? Or if you want to target only males between 25 - 30
yrs that has red hair
You'd have to write your own code to do that in SignalR. This could, for example, be done on top of the code that maps users to connections. A simple solution (not necessarily the best) could use LINQ to select the appropriate users depending on the properties you're interested in, then get all corresponding connection ids from the ConnectionMapping instance to send to.
In SignalR you can subscribe to a topic (group) and get messages only for the topics you are subscribed, and global messages.
Working with groups.
I am not completely sure about what that paragraph want to mean.
When considering a service in NServiceBus at what point do you start questioning how many messages handled by a service is too much and start to break these into a new service?
Consider the following: I have a sales service which can currently be broken into a few distinct business components, these are sales order validation, sales order processing, purchase order validation and purchase order processing.
There are currently about 20 message handlers and 2 sagas used within this service. My concern is that during high volume traffic from my website this can cause an initial spike in the messages to jump into the hundreds. Considering that the messages need to be processed in the order they are taken off the queue this can cause a delay for the last in the queue ( depending on what processing each message does).
When separating concerns within a service into smaller business components I find this makes things a little easier. Sure, it's a logical separation, but it seems to provide a layer of clarity and understanding. To me it seems it seems an easier option to do this than creating new services where in the end the more services I have the more maintenance I need to do.
Does anyone have any similar concerns to this?
I think you have actually answered you own question :)
As soon as the message volume reaches a point where the lag becomes an issue you could look to instance your endpoint. You do not necessarily need to reduce the number of handlers. You could simply install the service a number of times and have specific message types sent to the relevant endpoint by mapping.
So it becomes a matter of a simple instance installation and some config changes. So you can then either split messages on sending so that messages from a particular source end up on a particular endpoint (maybe priority) or on message type.
I happened to do the same thing on a previous project (not using NServiecBus though) where we needed document conversion messages coming from the UI to be processed ASAP. We simply installed the conversion service again with its own set of queues and changed the UI configuration to send the conversion messages to the new endpoint. The background conversion messages were still going to the previous endpoint. So here the source determined the separation.
I am looking over SignalR as a possible way to manage messaging between clients on a web application. The scenario would be that one person would create a session/room, and a few other people would join it. Then everyone within that room would send messages to each other. A lot like a chat room however they would be sending variable update messages etc.
Now I keep seeing it said that static variables should not be used, which I completely agree with, but if it creates a new Hub (I am planning to use a hub due to the different types of messages) each request, how does it store the group each client is in?
I suggest you review the project's source code here. This project has been very good as you wanted.
https://github.com/davidfowl/JabbR
https://github.com/davidfowl/JabbR/blob/master/JabbR/Hubs/Chat.cs
Also you can look at here the title "Calling methods on specific clients or groups".
https://github.com/SignalR/SignalR/wiki/Hubs
Recently, I've been reading up on the IRC protocol (RFCs 1459, 2810-2813), and I was thinking of implementing my own server.
I'm not necessarily looking into adhering religiously to the IRC protocol (I'm doing this for fun, after all), but one of the things I do like about it is that a network can consist of multiple servers transparently.
There are a number of things I don't like about the protocol or the IRC specification. The first is that nicknames aren't owned. While services like NickServ exist, they're not part of the official protocol. On the other hand, implementing something like NickServ properly kind of defeats the purpose of distribution (i.e. there'd be one place where NickServ is running, and one data store for it).
I was hoping there'd be a way to manage nicknames on a per-server basis. The problem with this is that if you have two servers that have some registered nicknames, and they then link up, you can have collisions.
Is there a way to avoid this, without using one central data store? That is: is it possible to keep the servers loosely connected (such that they each exist as an independent entity, but can also connect to one another) and maintain uniqueness amongst nicknames?
I realize this question is vague, but I can't think of a better way of wording it. I'm looking more for suggestions than I am for actual yes/no answers. So if anyone has any ideas as to how to accomplish nickname uniqueness in a network while still maintaining server independence, I'd be interested in hearing it. Note that adhering strictly to the IRC protocol isn't at all necessary; I've got no problem changing things to suit my purposes. :)
There's a simple solution if you don't care about strictly implementing an IRC server, but rather implementing a distributed message system that's like IRC, but not exactly IRC.
The simple solution is to use nicknames in the form "nick#host", much like email. So instead of merely being "mipadi", my nickname could be "mipadi#free-memorys-server.net". So I register with just your server, but when your server links up with others to form another a big ole' chat network, you can easily union all the usernames together. There might be a "mipadi" on otherserver.net, but then our nicknames become "mipadi#free-memorys-server.net" and "mipadi#otherserver.net", and everything is cool.
Of course, this deviates a good deal from IRC. :)
They have to be aware of each other. If not, you cannot prevent the sharing of nicknames. If they are, you simply need to transfer updates on the back-end. To prevent simultaneous registrations, you need a transaction system that blocks, requests permission from all other servers, and responds.
To prevent simultaneous registrations during outages, you have no choice but to timestamp the registration, and remove all but the last (or a random for truly simultaneous) registered copy of the nick.
It's not very pretty considering these servers aren't initially merged in the first place.
You could still implement nick ownership without a central instance, if your server instances trust each other.
When a user registers a nick, it is registered with the current server he's connected with
When a server receives a registration that it didn't know of, it forwards that information to all other servers that don't know it yet (might need a smart algorithm to avoid spamming the network)
When a server re-connects to another server then it tries to synchronize the list of registered nicks and which server handles which nick
If there is a collision during that sync, then the older registration is used, and the newer one marked as invalid
If you can't trust your servers, then it'll get a lot harder, as a servers could easily claim every username and even claim the oldest registration for each one.
Since you are trying to come up with something new, the idea that springs to mind, is simply including something unique about the server as part of the nick name when communicating outside of the server. So if you want to message a user on a different server you might have something like user#server
If you don't need them to be completely separate you might want to consider creating some kind of multiple-master replicated database of accounts. Where each server stores a complete copy of the account database, and each server can create new accounts which will be replicated to other servers as possible. You'll probably still have to deal with collisions on occasion though.
While services like NickServ exist, they're not part of the official protocol.
Services are not part of the official protocol because they've nothing to do with the protocol. They're bots with permissions. There's no reason why you couldn't have one running on each server but it does make them harder to maintain.
If you were to go down that path, I would probably suggest the commonly used "multiple master" database replication technique. If one receives a write (in your case, a new user is created or updated, etc) it sends the data to all the other nodes. You'll have to be careful though. If one node is offline when the others get an update, it will need to know to resync on reconnection.
Another technique would be as above but in reverse. Data is only exchanged between nodes when it's needed. Eg if a user tries to log in on a node where there's no data for it, it'll query the others and issue a move order to get all the data to that one node. This is potentially less painful than the replication version but there could be severe problems in netsplits if somebody signs up on a node disconnected from the pack for a duplicate nick.
One technique to nullify the problems of netsplits would be to make chat nodes and their bots netsplit-aware. When they're split, they probably shouldn't allow any write actions... But this could impact on your network if you're splitting lots.
You've also got to ask how secure this might or might not be. IRC network nodes are distributed for performance but they're not "secure". Because of this, service bots are usually run centrally to keep ultimate control over their running. If you distributed the bots and remote node got hacked, they'd potentially have access to the whole user database (depending on the model).