views:

147

answers:

2

Tornado advertises itself as "a relatively simple, non-blocking web server framework" and was designed to solve the C10k problem. However, looking at their database wrapper, which wraps MySQLdb, I came across the following piece of code:

def _execute(self, cursor, query, parameters):
    try:
        return cursor.execute(query, parameters)
    except OperationalError:
        logging.error("Error connecting to MySQL on %s", self.host)
        self.close()
        raise

As far as I know calls to the MySQLdb, which is built on top of libmysqlclient, are blocking. Am I right in thinking that a long-running query would render the entire Tornado server unresponsive until it finishes or is there magic on the code?

A: 

Yes, absent other measures, the server will wait for the query to finish executing. That does not mean Tornado is not a non-blocking web server.

A "non-blocking web server" doesn't block on network I/O (and may have some provision for disk I/O if it does static file serving). That does not mean you get instant, causality-violating instruction execution in your application.

Doing a database call takes time, just like reading files, formatting strings, processing templates, etc. takes time. Doing any of these things in the same thread as the server's main event loop will prevent the loop from moving on until you're done.

Nicholas Knight
Thanks for the quick reply. I take non-blocking to mean that while one request is waiting to be processed, another one is being processed since the web server's operations are asynchronous. In this case though, if 9,999 users are requesting a semi-static page, and one requests a long-running query page, the 9,999 users will have to wait for the one user.
ipartola
+1  A: 

Yes; this is not a fully non-blocking web server at all.

A non-blocking webserver doesn't block, using non-blocking APIs for file I/O, database access, and so on, to ensure that one request that has to wait for something to finish doesn't prevent other requests from being processed. This applies to everything that might block the server, including database access.

There's nothing as silly as "causality violation" in having non-blocking database access; it makes perfect sense to run a non-blocking query related to one request, and to process other requests while that's still running. In practice, this will usually mean making multiple connections to the database backend.

Note that if you're trying to run ten thousand concurrent requests, be careful: most database backends can't cope with this. If you have more than a few dozen database requests to run in parallel, you probably want something like a connection pooler, to allow the web server to make lots of database connections without swamping the backend. This will cause requests to block, waiting in a queue to get database access, but doing it this way means it's not blocking the whole server--just the requests that need the database.

Glenn Maynard
You're addressing something you don't fully understand. The Tornado webserver is non-blocking. If you choose to use the Tornado _framework_'s optional thin wrapper around MySQLdb, you can injure the benefits of a non-blocking webserver, but that says absolutely nothing about the webserver itself, which the database module is not a part of.
Nicholas Knight
@Nicholas Knight: No, I fully understand what a "non-blocking web server framework" (re-read the OP) means; obviously, you do not.
Glenn Maynard