I am working on a vendor portal. An owner of a shop will login and in the navigation bar (similar to facebook) I would like the number of items sold to appear INSTANTLY, WITHOUT ANY REFRESH. In facebook, new notifications pop up immediately. I am using sql azure as my database. Is it possible to note a change in the database and INSTANTLY INFORM the user?
Part 2 of my project will consist of a mobile phone app for the vendor. In this app I, too , would like to have the same notification mechanism. In this case, would I be correct if I search on push notifications and apply them?
At the moment my main aim is to solve the problem in paragraph 1. I am able to retrieve the number of notifications, but how on earth is it possible to show the changes INSTANTLY? thank you very much
First you need to define what INSTANT means to you. For some, it means within a second 90% of the time. For others, they would be happy to have a 10-20 second gap on average. And more importantly, you need to understand the implications of your requirements; in other words, is it worth it to have near zero wait time for your business? The more relaxed your requirements, the cheaper it will be to build and the easier it will be to maintain.
You should know that having near-time notification can be very expensive in terms of computing and locking resources. The more you refresh, the more web roundtrips are needed (even if they are minimal in this case). Having data fresh to the second can also be costly to the database because you are potentially creating a high volume of requests, which in turn could affect otherwise good performing requests. For example, if your website runs with 1000 users logged on, you may need 1000 database requests per second (assuming that's your definition of INSTANT), which could in turn create a throttling condition in SQL Azure if not designed properly.
An approach I used in the past, for a similar requirement (although the precision wasn't to the second; more like to the minute) was to load all records from a table in memory in the local website cache. A background thread was locking and refreshing the in memory data for all records in one shot. This allowed us to reduce the database traffic by a factor of a thousand since the data presented on the screen was coming from the local cache and a single database connection was needed to refresh the cache (per web server). Because we had multiple web servers, and we needed the data to be exactly the same on all web servers within a second of each other, we synchronized the requests of all the web servers to refresh the cache every minute. Putting this together took many hours, but it allowed us to build a system that was highly scalable.
The above technique may not work for your requirements, but my point is that the higher the need for fresh data, the more design/engineering work you will need to make sure your system isn't too impacted by the freshness requirement.
Hope this helps.
Related
I am developing an Android app which basically does this: On the landing(home) page it shows a couple of words. These words need to be updated on daily basis. Secondly, there is an 'experiences' tab in which a list of user experiences (around 500) shows up with their profile pic, description,etc.
This basic app is expected to get around 1 million users daily who will open the app daily at least once to see those couple of words. Many may occasionally open up the experiences section.
Thirdly, the app needs to have a push notification feature.
I am planning to purchase a managed wordpress hosting, set up a website, and add a post each day with those couple of words, use the JSON-API to extract those words and display them on app's home page. Similarly for the experiences, I will add each as a wordpress post and extract them from the Wordpress database. The reason I am choosing wordpress is that it has ready made interfaces for data entry which will save my time and effort.
But I am stuck on this: will the wordpress DB be able to handle such large amount of queries ? With such a large userbase and spiky traffic, I suspect I might cross the max. concurrent connections limit.
What's the best strategy in my case ? Should I use WP, or use firebase or any other service ? I need to make sure the scheme is cost effective also.
My app is basically very similar to this one:
https://play.google.com/store/apps/details?id=com.ekaum.ekaum
For push notifications, I am planning to use third party services.
Kindly suggest the best strategy I should go with for designing the back end of this app.
Thanks to everyone out there in advance who are willing to help me in this.
I have never used Wordpress, so I don't know if or how it could handle that load.
You can still use WP for data entry, and write a scheduled function that would use WP's JSON API to copy that data into Firebase.
RTDB-vs-Firestore scalability states that RTDB can handle 200 thousand concurrent connections and Firestore 1 million concurrent connections.
However, if I get it right, your app doesn't need connections to be active (i.e. receive real-time updates). You can get your data once, then close the connection.
For RTDB, Enabling Offline Capabilities on Android states that
On Android, Firebase automatically manages connection state to reduce bandwidth and battery usage. When a client has no active listeners, no pending write or onDisconnect operations, and is not explicitly disconnected by the goOffline method, Firebase closes the connection after 60 seconds of inactivity.
So the connection should close by itself after 1 minute, if you remove your listeners, or you can force close it earlier using goOffline.
For Firestore, I don't know if it happens automatically, but you can do it manually.
In Firebase Pricing you can see that 100K Firestore document reads is $0.06. 1M reads (for the two words) should cost $0.6 plus some network traffic. In RTDB, the cost has to do with data bulk, so it requires some calculations, but it shouldn't be much. I am not familiar with the pricing small details, so you should do some more research.
In the app you mentioned, the experiences don't seem to change very often. You might want to try to build your own caching manually, and add the required versioning info in the daily data.
Edit:
It would possibly be more efficient and less costly if you used Firebase Hosting, instead of RTDB/Firestore directly. See Serve dynamic content and host microservices with Cloud Functions and Manage cache behavior.
In short, you create a HTTP function that reads your database and returns the data you need. You configure hosting to call that function, and configure the cache such that subsequent requests are served the cached result via hosting (without extra function invocations).
I've read quite a few posts (including the firebase.com website) on Firebase connections. The website says that one connection is equivalent to approximately 1400 visiting users per month. And this makes sense to me given a scenario where the client makes a quick connection to the Firebase server, pulls down some data, and then closes the connection. However, if I'm using angular bindings (via angularfire), wouldn't each client visit (in the event the user stays on the site for a period of time) be a connection? In this example having 100 users (each of which is making use of firebase angular bindings) connecting to the site at the same time would be 100 connections. If I opted not to use angular bindings, that number could be (in a theoretical sense) 0 if all the clients already made their requests for data and were just idling.
Do I understand this properly?
AngularFire is built on top of Firebase's regular JavaScript/Web SDK. The connection count is fundamentally the same between them: if a 100 users are using your application at the same time and you are synchronizing data for each of them, you will have 100 concurrent connections at that time.
The statement that one concurrent connection is the equivalent of about 1400 visits per month is based on the extensive experience that the Firebase people have with how long the average connection lasts. As Andrew Lee stated in this answer: most developers vastly over-estimate the number of concurrent connections they will have.
As said: AngularFire fundamentally behaves the same as Firebase's JavaScript API (because it is built on top of that). Both libraries keep an open connection for a user, so that they can synchronize any changes that occur between the connected users. You can manually drop such a connection by calling goOffLine and then re-instate it with goOnline. Whether that is a good approach is largely dependent on the type of application you're building.
Two examples:
There recently was someone who was building a word game. He used Firebase to store the final score for each game. In his case explicitly managing the connections makes sense, because the connection is only needed for a relatively short time when compared to the time the application is active.
The "hello world" for Firebase programming is a chat application. In such an application it doesn't make a lot of sense to manage the connections yourself. So briefly connect every 15 seconds and then disconnect again. If you do this, you're essentially reverting to polling for updates. Doing so will lose you one of the bigger benefits of using Firebase: it automatically synchronizes data to connected clients.
So only you can decide whether explicit connection management is best for you application. I'd recommend starting without it (it's simpler) and first testing your application on a smaller scale to see how actual usage holds up to your expectation.
I am building a web site for a sports club. The club is not interested in moving their hosting to a different web host, so I'm stuck with the current host. I deployed the new web application to the host, but after a few hours of testing it became obvious something was acting weird with regards to logins and the session state.
Whenever I spent more than 10 minutes idle, all of a sudden my MVC Verification Tokens would stop decrypting. I went into IIS and set the machine key to a static value, and this problem went away, but it became obvious that they had the ASP.NET idle timeout setting set to 10 minutes. Which means that every 10 minutes InProc session data would be destroyed if there was no activity on the site. I filed a support ticket with the host, but they are unwilling to change that setting for me on my app pool, stating "The setting can't be changed on the server at this time as increasing this could affect the performance off(sic) the server".
The club is somewhat small, at most 500 members of the club and very few of the members will be accessing the site often, so I can pretty much guarantee that the 10 minute timeout will be happening multiple times a day, and I have session timeouts set to 60 minutes, so it won't be a good idea to have the site clear sessions if the sole user of the site at a given time is idle for 10 minutes.
My first thought was to use SQL session storage. I've never used it, but I know it exists. However, one caveat that exists is that we are limited to 350mb of SQL storage. While this is probably more than the site will need right now, I imagine down the line we might come close to hitting the limit. I don't anticipate storing much data in the session, only a few things when interacting with paypal and shopping carts (maybe a system message here or there as well), so perhaps this isn't a huge concern?
We do have unlimited disk space, so another alternative I thought about was to perhaps write a custom disk-based session storage solution. Is there any reason this might not be a better idea than SQL?
And finally, I had a totally off-the-wall "oh god I can't believe I'm thinking about doing this" idea, which would be to have an AJAX call on every page periodically (say, every 8 minutes) "ping" a non-cached lightweight MVC action just to keep the server alive. This would probably work, I think, except for the one scenario where someone:
goes to the shopping page and creates a cart
gets transferred to paypal
spends 10+ minutes on the paypal screen for whatever reason while nobody else is on the site
comes back to see their cart disappear.
In this instance I might just move carts to the database anyway.
So... thoughts, comments, suggestions? I'm really frustrated about the host not letting me change this setting and my first instinct would be to find another host, but as I said before, the club has some strange attachment to the host and doesn't want to move somewhere else.
Thanks in advance!
A few thoughts:
On the problem: It's common for sessions to be 'lost' on Load Balancing systems. This could possibly be fixed by moving to a single designated server (if the hosting company isn't doing this now and provides the option
Cookie sessions: If you're using .Net Membership, you can change the login process to use cookies. This comes with the obvious some users dont allow cookies pitfall. Again, a consideration. Currently working on a school site where they want users to remain logged in.
** With Cookies your Login is stable, but your sessions will not be any better kept. So you're out of luck carrying much to count on in the Session State.
The end result is that you can track users by IP or Cookie, but unless this is a fixable Load Balancing problem, you're heading toward a Session-less application.
I am working on a web app in ASP.NET/C# which needs to be scalable to handle the high user load (will probably run in a web farm). Since it will cater to a high number of users, around 1 Million plus, but number of online users would be around 30K-50K. I plan to use caching (provider based), and was wondering:
Is it a good idea to cache ALL users for performance? I plan to cache all other generic data, like settings etc, but how efficient would it be to cache ALL users in memory? If a user changes his/her profile, I will reload only that particular user in cache (having a collection of all the users). Any suggestions on this approach?
Do I need to worry about locking when using this above users cache? Only one editing the profile would be the user himself, that would be one atomic operation, though there will be multiple read oeprations in different threads. So while fetching users from cache, or updating a particualr user, should I use lock?
Thanks
Asif
Putting anything in Global Cache that is only useful to a single user is usually a bad idea and a performance killer. Optimize your database queries, and you will be in much better shape.
As a general rule of thumb you should only keep things in cache that are expensive to get from the database, and more than one user will want to see that information at once. Such as a list of the top 100 products or something. Small amounts of data that are relatively cheap to grab from the database, and that are only useful to a single person should stay where they are.
Caching increases complexity tremendously, and even more so in a web farm. Don't introduce needless complexity unless you absolutely have to. Wait until you have an actual performance problem before trying to solve it.
Caching users is probably a good idea. But it depends on how much data you are going to cache for each user, and the cost of retrieving that data from wherever it is stored.
For locking - can anyone else edit a user's profile (like an admininstrator)? Would that be a common occurrence? If so, you may want to do some locking. Otherwise, if only the user can edit their own stuff, I wouldn't bother.
There are 6 techniques to manage states in ASP.NET 3.5 (as far as I know).
(1) View State
(2) Cross Page Posting
(3) Query String
(4) Session State
(5) Application State
(6) Cookies
Can anyone give me some appropriate examples of situations where I should use these techniques?
For example:
(*) Session State: Personalization, Buy Cart, etc.
(*) Cookies: Saving User Credentials, etc.
There's a lot of factors that can influence this, so I won't comment on all of them. But here are a few pointers:
ViewState - This is useful when you'll be posting back to the same page frequently (something you're practically forced into doing by ASP.Net Webforms). How useful it is exactly changes depending on what kind of app you're building. For public internet sites, it should be used very sparingly. You may even want to turn it off by default. For local intranet sites, it's a great tool — especially for the fewer, heavier, webforms pages.
Query String - Use this to store state that you need to allow the user to bookmark a page or process and come back to much later. Even then, you might want to keep it down to some kind of hash that you can use as a key in a database lookup to avoid a really huge url (though hashes have their own problems). Also, a lot of users like to fiddle with your query string directly, so it can be dangerous to put too much here. It's easy to accidentally expose data to users who aren't supposed to see it this way.
Application State - Remember that this is shared by all users, so use appropriately. Things like view counts can go here.
Cookies - Don't use cookies to store user credentials. They're just plain unencrypted text files. Use cookies to store a key into the session (even here you can and should now use cookie-less sessions) and simple personalization settings that will be specific to that user and browser. For example, my monitor size at work is different from home, and so putting display size/layout settings into a cookie is nice because the settings stick for each computer, but it isn't going to compromise my security any if someone else reads that information.
Now I want to highlight this concept from the "Query String" section:
you might want to keep it down to some kind of hash that you can use as a key in a database lookup
Again, hashes have their own problems, but I want to point out that several items on my list talk (including Query String) about uploading data from the client web browser to the web server: ViewState, Query String, Cookie, and Cross-Page Post. You want to minimize the data that you move from client to server. This concept applies to all of these, and for several reasons:
Pulling data from the client is slow for public internet sites. Even broadband connections typically cripple the bandwidth available for upload. 512Kpbs (still a typical broadband upload rate in many areas) is nothing when compared to the Gigabit Ethernet (or faster) connection that likely sits between your database and your web server. As much as you might think of a database query as slow (and it is), it's still likely a much better way to go than waiting for the same data to arrive from the client.
Keeping the data on the server is cheaper, because you don't pay for the bandwidth required to push it to or from the client, and bandwidth often costs as much or more than your server hardware.
It's more secure, because if done right even when a client's computer or connection is compromised all the hacker has access to initially is a hash key that likely expires by the time he can decrypt it. Of course, if done wrong he can use that key directly immediately, so you still need to be careful.
So for most things, what I recommend is to start out by keeping a database key in the Session and then have code to easily pull what you need from a database based on that key. As you experience bottlenecks, profile to find out where they are and start caching those pages or controls, or keep that data/query result in the session directly.
State management option
View state:
Use when you need to store small amounts of information for a page that will post back to itself. Using the ViewState property provides functionality with basic security.
Control state:
Use when you need to store small amounts of state information for a control between round trips to the server.
Hidden fields:
Use when you need to store small amounts of information for a page that will post back to itself or to another page, and when security is not an issue.
You can use a hidden field only on pages that are submitted to the server.
Cookies:
Use when you need to store small amounts of information on the client and security is not an issue.
Query string:
Use when you are transferring small amounts of information from one page to another and security is not an issue.
You can use query strings only if you are requesting the same page, or another page via a link.
Server Side Management Options
Application state
Use when you are storing infrequently changed, global information that is used by many users, and security is not an issue. Do not store large quantities of information in application state.
Session state
Use when you are storing short-lived information that is specific to an individual session and security is an issue. Do not store large quantities of information in session state. Be aware that a session-state object will be created and maintained for the lifetime of every session in your application. In applications hosting many users, this can occupy significant server resources and affect scalability.
Profile properties
Use when you are storing user-specific information that needs to be persisted after the user session is expired and needs to be retrieved again on subsequent visits to your application.
Database support
Use when you are storing large amounts of information, managing transactions, or the information must survive application and session restarts. Data mining is a concern, and security is an issue.
Not sure if you mean the Cache object by Application State.
The Cache object is a great way to manage application wide state, e.g. to record source and count access to your website (to prevent DDOS attacks for example).
(3) Query String
(4) Session State
(5) Application State
(6) Cookies
1. Viewstate
Disclaimer: Use as little as possible. Good point is to always have each state reachable by an url, if possible.
F.e. Paging should use the URL (so /url/?p=2 instead of storing the page in Viewstate)
Use to persist control state between page-cycles.
F.e. Store the selected item in a checkbox, so you can determine whether it has changed.
2. Cross Page Posting
Don't. See the disclaimer for viewstate. Use the URL for this, or store the data in a session / cookie / profile if loads of properties need to be kept around.
Major downside of CPP is that the user cannot use the 'Back' and 'Forward' buttons in it's webbrowser. When a user clicks the back button it wants to undo everything on that page and retry the last one. When using CPP to click them through a wizard; this behavior is not possible without a lot of 'Are you sure you want to resend blablablabl'.
3. Query String
Use alot. Every visible state that a page could reach should be accessible by URL. People with screenreaders will thank you for this. And by using the query string there is no need to use javascript-only solutions.
/url/?page=2 // when doing paging, don't use postback for this
/url/?tab=advanced-search // when having tabs on top of your page
etc.
4. Session state
Use this for short-living objects, that only make sense this time the visitor visits your site. For example:
Which step of a certain wizard was reached
Pages a user had visited before
Small objects you want to put in cache, but that are user-bound
Don't use sessions but profiles for things like:
Preferences
Selected language
Because those things also make sense the next time the user visits your site.
5. Application state
Never. Use ASP.NET cache, or memcached, or any caching framework for this.
6. Cookies
Session ID, Profile ID for authenticated users; user preferences for anonymous users (everything listed in the second list under 4.).