I currently have my web application hosted on AWS, and I use two ELB instances, one to load balance the frontend requests to the app servers, and a second to load balance the backend requests FROM the app servers TO the API servers, like so (sorry for the crappy ascii diagram):
/-->APP1--\ /-->API1
User-->ELB1 ELB2
\-->APP2--/ \-->API2
In other words, the API requests that the APP servers make are load balanced evenly across the two backend API servers.
But, because I'm caching responses on the API servers, and use a cache invalidation mechanism which is NOT shared between the API servers, I'd like for a user's session to be stuck to one backend API server.
I already have the user's session stuck to one APP server, using the normal ELB load balancer-generated cookie stickiness, but is there any way to get the backend ELB stuck to a session? Of course, those requests are not coming from a browser, so there's nothing to manage cookies, and it seems that ELB's can only manage stickiness with cookies. Can I emulate the necessary cookies my backend requests?
To close off this question, yes, this is fairly easy to achieve by simply capturing the 'Set-Cookie' response header from the ELB, and then passing the cookie back in subsequent requests. But, see my caveat below.
I don't believe it would be possible to achieve stickiness between your App servers and API servers without doing a whole load of messy work. I could be wrong, and am very open to correction but I don't believe there is an easy solution, unless the language you're using for your App Server logic has something to offer.
Regardless, the best solution here would be to decouple your App Servers and your Cache. It would make more sense to have a single cache shared between the API servers that is served by separate servers. This will increase your infrastructure's fault tolerance and give you better quality data in your cache (especially as you scale up). You could use the ElastiCache service to do this for you and avoid any heavy lifting.
Related
I am developing an app that's going to have two capabilities. First of all, it has to be able to ingest a huge load of events (think millions per minute). It's also going to have a typical REST frontend/backend where I'll have the classic authentication flows, some dashboard based on an analysis of the ingested events, etc. For the REST portion of the app, I'm using Django + Postgres and React on Docker. For the event-driven backend, since Django is too slow to handle clients sending me millions of requests, I was thinking of using Kafka + a streaming database like Materialize.
However, I'm still unclear on how I would route requests to these different endpoints. Do I need to write an endpoint in something fast like Golang/Rust to send client payloads to Kafka? Or do clients communicate with Kafka directly? Is something like Nginx the right way to route these requests? I would still need to have some sort of reference to the the Postgres DB in order to verify the API Key used in the client request is valid.
be able to ingest a huge load of events (think millions per minute).
Through HTTP, or Kafka? If Kafka, then you can use Kafka Connect to directly write into the database without needing any frontend web server.
Django is too slow to handle clients sending me millions of requests
Based on your own benchmarks? Using how many instances?
Do I need to write an endpoint in something fast like Golang/Rust to send client payloads to Kafka?
Python can send producer requests to Kafka. There's nothing preventing you from using Kafka libraries in Django, although none of your question seems very specific to Kafka vs other message queues, especially when you've only referenced needing one or two databases.
If you're going to pick a different "service worker" language, you may as well write your HTTP server using those as well...
Or do clients communicate with Kafka directly?
Web clients? No, at least not without an HTTP proxy.
Is something like Nginx the right way to route these requests?
Unclear what you mean by "requests" here. Kafka requests - no, database requests - probably not, load balancing of HTTP requests - yes.
have some sort of reference to the Postgres DB in order to verify the API Key used in the client request is valid
Okay fine, use a Postgres client in your backend code.
I need to purchase a domain and hosting for my backend heroku rails server, so that I can implement SSL. (I could use heroku's SSL endpoint, but then I can't pin the certificate to my iOS app).
My question is... should I have my landing page and all my server side endpoints on the same domain?
For example... www.myexampledomain.com might be my landing page. Whereas www.myexampledomain.com/api/v1/things might be an endpoint returning json to my iOS client.
Should these be separate? Should I use subdomains for my json server returns? (I was hoping to use a single domain to save money on the SSL certificate)
Until you're server huge amounts of traffic, there really isn't any harm on having them on the same server. Even then, there are other ways of dealing with the traffic requirements other than separating the front-facing website from the API.
The pattern you showed is very common, and you shouldn't have any huge issues with keeping them together.
My iOS app uses a single hard-code URL api.xyz.com to find our REST service. At the moment there are just two servers running this service, and we use Amazon Route 53 DNS. But I've found that the timeout of an hour (or more) is too long incase one of our servers fails; don't want to leave users in the dark that long.
The alternative would be to implement a failover mechanism in the app. To be honest, I don't like the idea of pulling this low level DNS-related logic in the app, but I don't see another solution at the moment.
So my question is: How do I implement such a failover mechanism on iOS? I'm using AFNetworking for my REST API.
Or, are there better alternatives on server side? At the moment the servers are individually rented ones, so no Amazon, Google, ... cloud service.
I'm currently building a mobile application (iOS at first), which needs a backend web service to communicate with.
Since this service will be exposing data that I only want to be accessed by my mobile clients, I would like to restrict the access to the service.
However I'm in a bit of a doubt as to how this should be implemented. Since my app doesn't require authentication, I can't just authenticate against the service with these credentials. Somehow I need to be able to identify if the request is coming from a trusted client (i.e. my app), and this of course leads to the thought that one could just use certificates. But couldn't this certificate just be extracted from the app and hence misused?
Currently my app is based on iOS, but later on android and WP will come as well.
The web service I'm expecting to develop in nodejs, though this is not a final decision - it will however be a RESTful service.
Any advice on best practice is appreciated!
Simple answer: You cannot prevent just anybody from acecssing your web site from a non-mobile client. You can, however, make it harder.
Easy:
Send a nonstandard HTTP header
Set some unique query parameter
Send an interesting (or subtly non-interesting) User Agent string
(you can probably think of a few more)
Difficult:
Implement a challenge/response protocol to identify your client
(Ab)use HTTP as a transport for your own encrypted content
(you can probably think of a few more)
Of course anybody could extract the data, decompile your code, replay your HTTP requests, and whatnot. But at some point, being able to access a free Web application wouldn't be worth the effort that'd be required to reverse-engineer your app.
There's a more basic question here, however. What would be the harm of accessing your site with some other client? You haven't said; and without that information it's basically impossible to recommend an appropriate solution.
I'm trying to create a ruby on rails ecommerce application, where potential customers will be able to place an order and the store owner will be able to receive the order in real-time.
The finalized order will be recorded into the database (at the moment SQLite), and the storeowner will have a browser window open, where the new orders will appear just after the order is finalized.
(Application info: I'm using the HOBO rails framework, and planning to host the app in Heroku)
I'm now considering the best technology to implement this, as the application is expected to have a lot of users sending in a lot of orders:
1) Each browser window refreshes the page every X minutes, polling the server continuously for new records (new orders). Of course, this puts a heavy load on the server.
2) As above, but poll the server with some kind of AJAX framework.
3) Use some kind of server push technology, like 'comet' asynchronous messaging. Found Juggernaut, only problem is that it is using Flash and custom ports, and this could be a problem as my app should be accessible behind corporate firewalls and NAT.
4) I'm also checking node.js framework, seems to be efficient for this kind of asynchronous messaging, though it is not supported in Heroku.
Which is the most efficient way to implement this kind of functionality? Is there perhaps another method that I have not thought of?
Thank you for your time and help!
Node.js would probably be a nice fit - it's fast, loves realtime and has great comet support. Only downside is that you are introducing another technology into your solution. It's pretty fun to program in tho and a lot of the libraries have been inspired by rails and sinatra.
I know heroku has been running a node.js beta for a while and people were using it as part of the recent nodeknockout competition. See this blog post. If that's not an option, you could definitely host it elsewhere. If you host it at heroku, you might be able to proxy requests. Otherwise, you could happily run it off a sub domain so you can share cookies.
Also checkout socket.io. It does a great job of choosing the best way to do comet based on the browser's capabilities.
To share data between node and rails, you could share cookies and then store the session data in your database where both applications can get to it. A more involved architecture might involve using Redis to publish messages between them. Or you might be able to get away with passing everything you need in the http requests.
In HTTP, requests can only come from the client. Thus the best options are what you already mentioned (polling and HTTP streaming).
Polling is the easier to implement option; it will use quite a bit of bandwidth though. That's why you should keep the requests and responses as small as possible, so you should definitely use XHR (Ajax) for this.
Your other option is HTTP streaming (Comet); it will require more work on the set up, but you might find it worth the effort. You can give Realtime on Rails a shot. For more information and tips on how to reduce bandwidth usage, see:
http://ajaxpatterns.org/Periodic_Refresh
http://ajaxpatterns.org/HTTP_Streaming
Actually, if you have your storeowner run Chrome (other browsers will follow soon), you can use WebSockets (just for the storeowner's notification though), which allows you to have a constant connection open, and you can send data to the browser without the browser requesting anything.
There are a few websocket libraries for node.js, but i believe you can do it easily yourself using just a regular tcp connection.