cherrypy as a gevent-socketio server - python

I have just started using gevent-socketio and it's great!
But I have been using the default socketioserver and socketio_manage from the chat tutorial and was wondering how to integrate socketio with cherrypy.
essentially, how do I turn this:
class MyNamespace(BaseNamespace):...
def application(environ, start_response):
if environ['PATH_INFO'].startswith('/socket.io'):
return socketio_manage(environ, { '/app': MyNamespace})
else:
return serve_file(environ, start_response)
def serve_file(...):...
sio_server = SocketIOServer(
('', 8080), application,
policy_server=False) sio_server.serve_forever()
into a normal cherrypy server?

Gevent-socketio is based on Gevent, and Gevent's web server. There are two implementations: pywsgi, which is pure python, and wsgi, which uses libevent's http implementation.
See the paragraph starting with "The difference between pywsgi.WSGIServer and wsgi.WSGIServer" over here:
http://www.gevent.org/servers.html
Only those servers are "green", in the sense that they yield the control to the Gevent loop.. so you can only use those servers afaik. The reason for this is that the server is present at the very beginning of the request, and will know how to handle the "Upgrade" and websockets protocol negotiations, and it will pass values inside the "environ" that the next layer (SocketIO) will expect and know how to handle.
You will also need to use the gevent-websocket package.. because it is green (and gevent-socketio is based on that one). You can't just swap the websocket stack.
Hope this helps.

CherryPy doesn't implement the socket.io protocol, nor does it support WebSocket as a built-in. However, there is an extension to CherryPy, called ws4py, that implements only the bare WebSocket protocol on top of its stack. You could start there probably.

Related

Starting and stopping flask on demand

I am writing an application, which can expose a simple RPC interface implemented with flask. However I want it to be possible to activate and deactivate that interface. Also it should be possible to have multiple instances of the application running in the same python interpreter, which each have their own RPC interface.
The service is only exposed to localhost and this is a prototype, so I am not worried about security. I am looking for a small and easy solution.
The obvious way here seems to use the flask development server, however I can't find a way to shut it down.
I have created a flask blueprint for the functionality I want to expose and now I am trying to write a class to wrap the RPC interface similar to this:
class RPCInterface:
def __init__(self, creating_app, config):
self.flask_app = Flask(__name__)
self.flask_app.config.update(config)
self.flask_app.my_app = creating_app
self.flask_app.register_blueprint(my_blueprint)
self.flask_thread = Thread(target=Flask.run, args=(self.flask_app,),
name='flask_thread', daemon=True)
def shutdown(self):
# Seems impossible with the flask server
raise NotImplemented()
I am using the variable my_app of the current app to pass the instance of my application this RPC interface is working with into the context of the requests.
It can be shut down from inside a request (as described here http://flask.pocoo.org/snippets/67/), so one solution would be to create a shutdown endpoint and send a request with the test client to initiate a shutdown. However that requires a flask endpoint just for this purpose. This is far from clean.
I looked into the source code of flask and werkzeug and figured out the important part (Context at https://github.com/pallets/werkzeug/blob/master/werkzeug/serving.py#L688) looks like this:
def inner():
try:
fd = int(os.environ['WERKZEUG_SERVER_FD'])
except (LookupError, ValueError):
fd = None
srv = make_server(hostname, port, application, threaded,
processes, request_handler,
passthrough_errors, ssl_context,
fd=fd)
if fd is None:
log_startup(srv.socket)
srv.serve_forever()
make_server returns an instance of werkzeugs server class, which inherits from pythons http.server class. This in turn is a python BaseSocketServer, which exposes a shutdown method. The problem is that the server created here is just a local variable and thus not accessible from anywhere.
This is where I ran into a dead end. So my question is:
Does anybody have another idea how to shut down this server easily?
Is there any other simple server to run flask on? Something which does not require an external process and can just be started and stopped in a few lines of code? Everything listed in the flask doc seems to have a complex setup.
Answering my own question in case this ever happens again to anyone.
The first solution involved switching from flask to klein. Klein is basically flask with less features, but running on top of the twisted reactor. This way the integration is very simple. Basically it works like this:
from klein import Klein
from twisted.internet import reactor
app = Klein()
#app.route('/')
def home(request):
return 'Some website'
endpoint = serverFromString(reactor, endpoint_string)
endpoint.listen(Site(app.resource()))
reactor.run()
Now all the twisted tools can be used to start and stop the server as needed.
The second solution I switched to further down the road was to get rid of HTTP as a transport protocol. I switched to JSONRPC on top of twisted's LineReceiver protocol. This way everything got even simpler and I didn't use any of the HTTP stuff anyway.
This is a terrible, horrendous hack that nobody should ever use for any purpose whatsoever... except maybe if you're trying to write an integration test suite. There are probably better approaches - but if you're trying to do exactly what the question is asking, here goes...
import sys
from socketserver import BaseSocketServer
# implementing the shutdown() method above
def shutdown(self):
for frame in sys._current_frames().values():
while frame is not None:
if 'srv' in frame.f_locals and isinstance(frame.f_locals['srv'], BaseSocketServer):
frame.f_locals['srv'].shutdown()
break
else:
continue
break
self.flask_thread.join()

How is Bottle's built-in WSGI server different from the standard Python wsgiref server module?

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
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!

WSGI compliant component with web socket client?

I'm trying to integrate a RESTful responder in a Crossbar application, for which the best fit seems to be a WSGI service. This service ideally should be part of the rest of the pub/sub infrastructure, being able to receive WAMP events on the one hand and answer HTTP requests on the other.
The difficulty is to run an event loop which allows asynchronous web socket events and additionally offer a WSGI compliant component. It seems to me that Pulsar should be able to do that, but I have not been able to figure out how to set it up, none of the available samples demonstrate exactly this use case.
value = None
class Foo(ApplicationSession):
def onJoin(self, details):
yield self.subscribe(self.bar, 'bar')
def bar(self, data):
value = data
app = Flask(__name__)
#app.route('/')
def baz():
return value
if __name__ == '__main__':
runner = ApplicationRunner('ws://127.0.0.1:8080', 'test')
runner.run(Foo, start_reactor=False)
# now what?
The above demonstrates the two parts, an Autobahn WAMP client and a Flask WSGI component. How do I run both of these in parallel, allowing one thread to receive events both via HTTP and web socket? I don't particularly care about the version of Python nor underlying library (Twisted, asyncio, Pulsar, Flask), I'd just like to get this running somehow.
WSGI is an inherently synchronous API. I don't know about Pulsar, but I would be surprised if it could somehow magically work around this fact.
The way Crossbar.io integrates with classic Web (and synchronous) stacks is via a REST-bridge. Currently, we have the WAMP "Publisher" role covered today (2015/02): that is, you can publish an WAMP event by doing a simple HTTP/POST http://crossbar.io/docs/HTTP-Pusher-Service/. This REST bridge in Crossbar.io will be extended to cover all 4 WAMP roles in the near future.
If you take a step back, and primarily care about something do create a REST API in your app, and which integrates directly with WAMP and asynchronous stuff, I'd have a look a Twisted Klein. Twisted Klein is essentially modeled after Flask, but at the source level. We have a blog post that covers exactly this: Mixing Web and WAMP code with Twisted Klein

HTTP Streaming with Apache mod_wsgi

I've got an ubuntu-server where I am running multiple web-apps.
All of them are hosted by Apache using named VirtualHosts.
One of them is a Flask app, which is running via mod_wsgi.
This app is serving continuous, unlimited HTTP streams.
Does this eventually block my app/server/apache worker, if enough clients are connecting to the streaming endpoint?
And if yes, are there alternatives?
Other non-blocking wsgi-servers that play nicely with VirtualHosts, a different http-streaming paradigm, or some magic apache mod_wsgi settings?
The core of it looks like:
#app.route('/stream')
def get_stream():
def endless():
while True:
yield get_stuff_from_redis()
time.sleep(1)
return Response(endless(), mimetype='application/json')
If the clients never disconnect, yes, you will eventually run out of processes/threads to handle more requests.
You are more than likely better off using a async framework such as Tornado or Twisted for this specific type of application. Doing async programming can be tricky if you aren't used to that concept.
Some people use coroutine system such as gevent/eventlet, but they also have their own problems you have to watch out for.

Python HTTP Server available for Multiple Requests

I have been doing a lot of studying of the BaseHTTPServer and found that its not that good for multiple requests. I went through this article
http://metachris.org/2011/01/scaling-python-servers-with-worker-processes-and-socket-duplication/#python
and I wanted to know what is the best way for building a HTTP Server for multiple requests
->
My requirements for the HTTP Server are simple -
- support multiple requests (where each request may run a LONG Python Script)
Till now I have following options ->
- BaseHTTPServer (with thread is not good)
- Mod_Python (Apache intergration)
- CherryPy?
- Any other?
I have had very good luck with the CherryPy web server, one of the oldest and most solid of the pure-Python web servers. Just write your application as a WSGI callable and it should be easy to run under CherryPy's multi-threaded server.
http://www.cherrypy.org/
Indeed, the the HTTP servers provided with the standard python library are meant only for light duty use; For moderate scaling (100's of concurrent connections), mod_wsgi in apache is a great choice.
If your needs are greater than that(10,000's of concurrent connections), You'll want to look at an asynchronous framework, such as Twisted or Tornado. The general structure of an asynchronous application is quite different, so if you think you're likely to need to go down that route, you should definitely start your project in one of those frameworks from the start
Tornado is a really good and easy-to-use asynchronous event-loop / webserver developed by FriendFeed/Facebook. I've personally had very good experiences with it. You can use the HTTP classes as in the example below, or only the io-loop to multiplex plain TCP connections.
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
application = tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.current().start()

Categories

Resources