How can I fix number of concurrent sessions allowed at app level?
Basically I want a limit to how many concurrent requests to this url to keep the server from getting congested.
I guess some middleware hack?
Thanks.
Don't do this in django, but in Apache / nginx / whatever webserver you have in front of Django. They have specific modules exactly for such tasks.
A possible solution for Apache would be: mod_limitipconn2 - http://dominia.org/djao/limitipconn2.html
Django stores session information in the database by default. You could use a middleware, which checks the number of rows (coarsly speaking) in that table. Keep in mind that django won't purge expired sessions from the DB automatically.
On clearing the session table:
http://docs.djangoproject.com/en/dev/topics/http/sessions/#clearing-the-session-table
You're not asking about sessions, you're asking about requests. What you want is known as throttling. However, it would be quite difficult to do it inside the app, because Apache manages multiple processes and threads, so you'd need some external process to keep track of these in order to enable the throttling.
Basically, this sort of thing is best done within Apache itself, by something like mod_throttle.
Related
So, I am currently working on a django project hosted at pythonanywhere, which includes a feature for notifications, while also receiving data externally from sensors through AWS. I have been thinking of the best practice in order to implement this.
I currently have a simple implementation which is a view that checks all notifications and does the actions as needed if required, with an always-on task (which simply means a script that is running independently) sending a REST request to the server every minute.
Server side:
views.py:
def checkNotifications(request):
notificationsObject = notifications.objects.order_by('thing').values_list('thing').distinct()
thingsList = list(notificationsObject)
for thing in thingsList:
valuesDic = returnAllField(thing)
thingNotifications = notifications.objects.filter(thing=thing)
#Do stuff for each notification
urls:
path('notifications/',views.checkNotifications,name="checkNotification")
and the client just sents a GET request to my URL/notifications/. which works.
Now, while researching I saw some other options such as the ones discussed here with django background tasks and/or celery:
How to initialize repeating tasks using Django Background Tasks?
Celery task best practices in Django/Python
as well as some other options.
My question is: Is there a benefit to moving from my first implementation to this one? The only benefit I can see directly is avoid abuse from another service trying to hit my URl to check notifications too often, but I can/have a required authentication to avoid that. And, is there a certain "best practice" with regards to this, considering that I am checking with this repeating task quite so often, it almost feels like there should be a more proper/cleaner solution. For one, I am not sure if running a repeating task is the best option with pythonanywhere.
(https://help.pythonanywhere.com/pages/AsyncInWebApps/ suggests using always-on tasks, but it also mentions django background tasks)
Thank you
To use Django background tasks on PythonAnywhere you need to run it using an always-on task, so it is not an alternative, but just the other use of always-on tasks.
You can also access your Django code in your always-on task directly with some kind of long-running management command, so you do not need to hit your web app with a special request.
What would be the best practice in this scenario?
I have an App Engine Python app, with multiple cron jobs. Instantiated by user requests and cron jobs, push notifications might be sent. This could easily scale up to a total of +- 100 pushes per minute.
Setting up and tearing down a connection to APNs for every batch is not what I want. Neither is Apple advising to do this. So I would like to keep the connection alive, even when user requests finish or when a cron finishes. Possibly with a timeout (2 minutes no pushes, then close then connection).
Reading the GAE documentation, I couldn't figure out if there even is such a thing available. Also, I might need this to be available in different apps and/or modules.
You can put the messages in a pull taskqueue and have a backend instance (or a cron job) to process the tasks
First, please take a look at Google Cloud Messaging. It's cool and you can use it easier than APNS's protocol.
If you can not use GCM (because of code refactoring, etc ...), I think AppEngine Managed VM is suitable for your situation now. Managed VM is something that stands between AppEngine and Compute Engine.
You can use the datastore (eventually shadowed by memcache for performance) to persist all the necessary APN (or any other) connection/protocol status/context info such that multiple related requests can share the same connection as if your app would be a long-living one.
Maybe not trivial, but definitely feasible.
Some requests may need to be postponed temporarily, depending on the shared connection status/context, that's true.
Not sure of the customs for people who release production django apps but I'd assume there is some kind of protection mechanism against people who spam a view or so?
If a view did not implement caching and a user just spams the url a bunch of times wouldn't that be a bad thing?
I want some mechanism to block people by IP address or whatnot if they are repeatedly calling a view at a high rate.
I tried to use this app: http://django-ratelimit.readthedocs.org/en/latest/install.html
But it promptly does not work, or perhaps my setup is wrong (has anyone used it?).
Thanks.
Typically this kind of security would happen at the web server level, i.e. in Nginx or whatever you're using to serve your app. Think about the fact that in order to block someone's IP in your app after a certain number of attempts you'd need to record their IP somewhere and then check incoming requests against that. If it were to go in your app then this kind of functionality would best fit at a middleware level.
If you were to do this at an application level for the purpose of protecting individual views then I would probably do it by means of a decorator.
You should have a mechanism in place for this anyway, as what you've described can also be a Denial of Service attack in the right context. Some web hosts have hardware-level protection for this, so ask your host about that too.
Generally in production you have some kind of frontend server. If your application logic not coupled to the number of requests, better do this work on frontend. For example Nginx has limit_req module:
http://nginx.org/en/docs/http/ngx_http_limit_req_module.html
What is the best way to share the SQLAlchemy session between my Pyramid application and Celery tasks while only instantiating the database engine once? I looked at this answer here, however, I don't want to have to create a another engine (that also happens to be global) since this is not very DRY. Also, during the Pyramid application startup the application .ini settings are passed into the main function so I would like to be able to configure the engine from this method but also have it available to all Celery tasks. Perhaps I am going about things the wrong way when it comes to Celery integration with Pyramid? Thanks for your help!
A major motivation behind using a message broker (celery) in the first place is that your web app and workers do not operate in the same process. Because of this, I'm going to suggest that you back up a bit and think of your system as separate processes that are not sharing the same database connection.
My Flask applications has to do quite a large calculation to fetch a certain page. While Flask is doing that function, another user cannot access the website, because Flask is busy with the large calculation.
Is there any way that I can make my Flask application accept requests from multiple users?
Yes, deploy your application on a different WSGI server, see the Flask deployment options documentation.
The server component that comes with Flask is really only meant for when you are developing your application; even though it can be configured to handle concurrent requests with app.run(threaded=True) (as of Flask 1.0 this is the default). The above document lists several options for servers that can handle concurrent requests and are far more robust and tuneable.
For requests that take a long time, you might want to consider starting a background job for them.