1

What is Bottle doing in its wsgiref server implementation that the built in Python WSGIref simple server is not? When I look at Bottle, for example, it adheres to the WSGI standard and the documentation states:

1.5.1 Server Options The built-in default server is based on wsgiref WSGIServer. This non-threading HTTP server is perfectly fine for development and early production, but may become a performance bottleneck when server load increases.
There are three ways to eliminate this bottleneck:

  • • Use a different server that is either multi-threaded or asynchronous.
  • • Start multiple server processes and spread the load with a load-balancer.
  • • Do both [emphasis mine]

Yet, everything I have read says to not use the Python wsgrief server for anything production.

What does Bottle do with wsgrief that the built in Python wsgiref does not? I'm not really questioning the wisdom of using asynch servers or "bigger" more "scalable" WSGI servers. But, I'd like to know what Bottle is doing with the wsgiref server that makes it okay for "early Production," the regular library does not.

My application would serve less than 20 people hitting a PostgreSQL or MySQL database, CRUD operations. I guess you could ask a similar question with Flask.

For reference,

http://bottlepy.org/docs/dev/bottle-docs.pdf [pdf] https://docs.python.org/2/library/wsgiref.html#module-wsgiref.simple_server https://github.com/bottlepy/bottle/blob/master/bottle.py

This is Bottle's implementation, at least for opening the port:

class WSGIRefServer(ServerAdapter):
    def run(self, app):  # pragma: no cover
        from wsgiref.simple_server import make_server
        from wsgiref.simple_server import WSGIRequestHandler, WSGIServer
        import socket

        class FixedHandler(WSGIRequestHandler):
            def address_string(self):  # Prevent reverse DNS lookups please.
                return self.client_address[0]

            def log_request(*args, **kw):
                if not self.quiet:
                    return WSGIRequestHandler.log_request(*args, **kw)

        handler_cls = self.options.get('handler_class', FixedHandler)
        server_cls = self.options.get('server_class', WSGIServer)

        if ':' in self.host:  # Fix wsgiref for IPv6 addresses.
            if getattr(server_cls, 'address_family') == socket.AF_INET:

                class server_cls(server_cls):
                    address_family = socket.AF_INET6

        self.srv = make_server(self.host, self.port, app, server_cls,
                               handler_cls)
        self.port = self.srv.server_port  # update port actual port (0 means random)
        try:
            self.srv.serve_forever()
        except KeyboardInterrupt:
            self.srv.server_close()  # Prevent ResourceWarning: unclosed socket
            raise
johnny
  • 19,272
  • 52
  • 157
  • 259
  • Not sure I totally get your point. Are you hung up on the words "early production?" (They don't mean anything.) – ron rothman Jan 27 '16 at 14:14
  • @ron.rothman Yeah, because it says "early" as if you really could use the built-in for some level of production. – johnny Jan 27 '16 at 16:17
  • 1
    Well, at least [one entry on the Python bug tracker](https://bugs.python.org/issue26005) is noting that the Python built-in doesn't perform a lot of necessary security checks (e.g. in this case, to prevent simple DoS attacks). No idea if Bottle addresses that. I suspect it doesn't, and their claim that it's "early production" grade is invalid. – ShadowRanger Jan 27 '16 at 18:10

1 Answers1

3

EDIT:

What is Bottle doing in its wsgiref server implementation that the built in Python WSGIref simple server is not?

What does Bottle do with wsgrief that the built in Python wsgiref does not?

Nothing (of substance).


Not sure I understand your question, but I'll take a stab at helping.

The reason for my confusion is: the code snippet you posted precisely answers [what I think is] your question. Bottle's WSGIRefServer class does nothing substantial except wrap wsgiref.simple_server. (I'm calling the logging and the IPv6 tweaks unsubstantial because they're not related to "production-readiness," which I gather is at the heart of your question.)

Is it possible that you misinterpreted the docs? I'm thinking perhaps yes, because you say:

I'd like to know what Bottle is doing with the wsgiref server that makes it okay for "early Production," the regular library does not.

but the Bottle docs are making the point that Bottle's WSGIRefServer should not be used to handle high throughput loads.

In other words, WSGIRefServer is the same as wsgiref, whereas I think you interpreted the docs as saying that the former is somehow improved over the latter. (It's not.)

Hope this helps!

Community
  • 1
  • 1
ron rothman
  • 17,348
  • 7
  • 41
  • 43
  • I wasn't sure because it seemed they were saying you could use wsgrief for some level of production. Small maybe, but some level. – johnny Jan 27 '16 at 16:18
  • 1
    Okay, then to answer your question, think of it this way: `WSGIRefServer` is precisely as production-capable as `wsgiref`. Does that help clarify the docs? – ron rothman Jan 27 '16 at 16:56
  • The docs are clear. I'm questioning the validity of the docs compared to the rest of the Python community. – johnny Jan 27 '16 at 17:55
  • 1
    Okay, I've edited my answer to directly answer your actual questions. I hope that makes it clear, because I'm not sure how to more plainly state it. – ron rothman Jan 27 '16 at 18:01