Rewrote becoming big and foreword

This commit is contained in:
Armin Ronacher 2010-07-04 19:57:53 +02:00
parent 9e1111c2fb
commit bca1acf1f3
2 changed files with 72 additions and 56 deletions

View file

@ -3,54 +3,74 @@
Becoming Big Becoming Big
============ ============
Your application is becoming more and more complex? Flask is really not Your application is becoming more and more complex? If you suddenly
designed for large scale applications and does not attempt to do so, but realize that Flask does things in a way that does not work out for your
that does not mean you picked the wrong tool in the first place. application there are ways to deal with that.
Flask is powered by Werkzeug and Jinja2, two libraries that are in use at Flask is powered by Werkzeug and Jinja2, two libraries that are in use at
a number of large websites out there and all Flask does is bring those a number of large websites out there and all Flask does is bring those
two together. Being a microframework, Flask is literally a single file. two together. Being a microframework Flask does not do much more than
What that means for large applications is that it's probably a good idea combinding existing libraries - there is not a lot of code involved.
to take the code from Flask and put it into a new module within the What that means for large applications is that it's very easy to take the
applications and expand on that. code from Flask and put it into a new module within the applications and
expand on that.
What Could Be Improved? Flask is designed to be extended and modified in a couple of different
----------------------- ways:
For instance it makes a lot of sense to change the way endpoints (the - Subclassing. The majority of functionality can be changed by creating
names of the functions / URL rules) are handled to also take the module a new subclass of the :class:`~flask.Flask` class and overriding
name into account. Right now the function name is the URL name, but some methods.
imagine you have a large application consisting of multiple components.
In that case, it makes a lot of sense to use dotted names for the URL
endpoints.
Here are some suggestions for how Flask can be modified to better - Flask extensions. For a lot of reusable functionality you can create
accommodate large-scale applications: extensions.
- get rid of the decorator function registering which causes a lot - Forking. If nothing else works out you can just take the Flask
of troubles for applications that have circular dependencies. It codebase at a given point and copy/paste it into your application
also requires that the whole application is imported when the system and change it. Flask is designed with that in mind and makes this
initializes or certain URLs will not be available right away. A incredible easy. You just have to take the package and copy it
better solution would be to have one module with all URLs in there and into your application's code and rename it (for example to
specifying the target functions explicitly or by name and importing `framework`). Then you can start modifying the code in there.
them when needed.
- switch to explicit request object passing. This requires more typing
(because you now have something to pass around) but it makes it a
whole lot easier to debug hairy situations and to test the code.
- integrate the `Babel`_ i18n package or `SQLAlchemy`_ directly into the
core framework.
.. _Babel: http://babel.edgewall.org/ Why consider Forking?
.. _SQLAlchemy: http://www.sqlalchemy.org/ ---------------------
Why does Flask not do all that by Default? The majority of code of Flask is within Werkzeug and Jinja2. These
------------------------------------------ libraries do the majority of the work. Flask is just the paste that glues
those together. For every project there is the point where the underlying
framework gets in the way (due to assumptions the original developers
had). This is natural because if this would not be the case, the
framework would be a very complex system to begin with which causes a
steep learning curve and a lot of user frustration.
There is a huge difference between a small application that only has to This is not unique to Flask. Many people use patched and modified
handle a couple of requests per second and with an overall code complexity versions of their framework to counter shortcomings. This idea is also
of less than 4000 lines of code and something of larger scale. At some reflected in the license of Flask. You don't have to contribute any
point it becomes important to integrate external systems, different changes back if you decide to modify the framework.
storage backends and more.
If Flask was designed with all these contingencies in mind, it would be a The downside of forking is of course that Flask extensions will most
much more complex framework and harder to get started with. likely break because the new framework has a different import name and
because of that forking should be the last resort.
Scaling like a Pro
------------------
For many web applications the complexity of the code is less an issue than
the scaling for the number of users or data entries expected. Flask by
itself is only limited in terms of scaling by your application code, the
data store you want to use and the Python implementation and webserver you
are running on.
Scaling well means for example that if you double the amount of servers
you get about twice the performance. Scaling bad means that if you add a
new server the application won't perform any better or would not even
support a second server.
There is only one limiting factor regarding scaling in Flask which are
the context local proxies. They depend on context which in Flask is
defined as being either a thread or a greenlet. Separate processes are
fine as well. If your server uses some kind of concurrency that is not
based on threads or greenlets, Flask will no longer be able to support
these global proxies. However the majority of servers are using either
threads, greenlets or separate processes to achieve concurrency which are
all methods well supported by the underlying Werkzeug library.

View file

@ -17,24 +17,20 @@ may be necessary in larger or more complex applications.
For example, Flask uses thread-local objects internally so that you don't For example, Flask uses thread-local objects internally so that you don't
have to pass objects around from function to function within a request in have to pass objects around from function to function within a request in
order to stay threadsafe. While this is a really easy approach and saves order to stay threadsafe. While this is a really easy approach and saves
you a lot of time, it also does not scale well to large applications. you a lot of time, it might also cause some troubles for very large
It's especially painful for more complex unittests, and when you suddenly applications because changes on these thread-local objects can happen
have to deal with code being executed outside of the context of a request, anywhere in the same thread.
such as in cron jobs.
Flask provides some tools to deal with the downsides of this approach, but Flask provides some tools to deal with the downsides of this approach but
the core problem remains. Flask is also based on convention over it might be an issue for larger applications. Flask is also based on
configuration, which means that many things are preconfigured and will convention over configuration, which means that many things are
work well for smaller applications but not so well for larger ones. For preconfigured and will work well for smaller applications but not so well
example, by convention, templates and static files are in subdirectories for larger ones. For example, by convention, templates and static files
within the Python source tree of the application. are in subdirectories within the Python source tree of the application.
But don't worry if your application suddenly grows larger However Flask is not much code and built in a very solid foundation and
and you're afraid Flask might not grow with it. Even with with that very easy to adapt for large applications. If you are
larger frameworks, you'll eventually discover that you need interested in that, check out the :ref:`becomingbig` chapter.
something the framework just cannot do for you without modification.
If you are ever in that situation, check out the :ref:`becomingbig`
chapter.
A Framework and an Example A Framework and an Example
-------------------------- --------------------------