Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Re-)Implement websocket/socket.io simplates #200

Open
chadwhitacre opened this issue Jun 24, 2013 · 16 comments
Open

(Re-)Implement websocket/socket.io simplates #200

chadwhitacre opened this issue Jun 24, 2013 · 16 comments

Comments

@chadwhitacre
Copy link
Contributor

Right now we just have XHRPolling

@pjz
Copy link
Contributor

pjz commented Aug 10, 2013

WSGI can't support socket.io/websockets.

So to do this we have to:

  1. make the aspen server rock solid as it's going to be the only way to support websockets
  2. either give up WSGI support, or have a switch to disable websockets (automatically turned on if the request comes in via the WSGI API)

@chadwhitacre
Copy link
Contributor Author

Aspen's rock-solidity depends greatly on the networking library used. We support nine, which doesn't lend towards rock-solidity. One strategy, therefore, would be to pick one networking engine, probably gevent or diesel.

@chadwhitacre
Copy link
Contributor Author

@pjz How does websockets relate to fastcgi?

@pjz
Copy link
Contributor

pjz commented Aug 12, 2013

It doesn't. FastCGI and WSGI both allow the webserver to break up multiple requests from a single connection across multiple backend FastCGI or WSGI processes; websockets seems to require that it get full control of the actual connection socket. Thus, I think they're fundamentally incompatible. See also http://stackoverflow.com/questions/13137449/combining-websockets-and-wsgi-in-a-python-app

@chadwhitacre
Copy link
Contributor Author

Lots of conversation on this at @pjz's. Let's spike out using:

http://www.gelens.org/code/gevent-websocket/

Can that support what we need for thread-pooled WSGI as well as the WebSocket upgrade when needed?

@chadwhitacre
Copy link
Contributor Author

WebSockets are important because they're the forerunner of HTTP 2.0, and that's a puck we want to skate ahead of.

@joeyespo
Copy link
Contributor

FWIW Armin Ronacher wrote about adding realtime support to web applications last year in a way that allows you to keep your webserver stateless and using the WSGI protocol. Depending on what you're trying to solve, specifically rewriting for websockets may be the goal, or perhaps it's more general: allow realtime websites.

Basically, you have a public-facing server that handles the persistent connections and adds them to Redis. Your webserver instances and background workers listen for this and process them accordingly. The results are pushed back onto Redis, and the public-facing server can either generate an HTTP response like normal, or push the result to all open connections on a particular channel.

This keeps your website code the same: process a request and generate a response. (Your background workers can still generate broadcasts without a request triggering it, if you need time-based broadcasts instead of request-based.) So it's still WSGI and still stateless. As a bonus, you can upgrade your website without actually closing any connections. Just throwing this out there in case "realtime web" is the underlying reason for websockets. Either way, it's a good read.

@chadwhitacre
Copy link
Contributor Author

Thanks @joeyespo. Sounds like he is recommending two servers?

  • a realtime server that maintains the standing connections and subscribes to redis. The messages that come from redis are then sent to the connected clients that want them. If you want bidirectional communication you can also accept messages from the clients and put them on the queue for Flask to pick up.
  • a regular webserver for exposing your WSGI app to the web. This could be nginx, Apache or whatever floats your boat.

@joeyespo
Copy link
Contributor

I think he means "server" as defined by WSGI, the code that provides environment information and a callback to the application. You could use two ports or subdomains instead of two machines.

My interpretation is, all websocket connections are handled with the realtime "server" so it can generate requests from incoming data, let your WSGI application handle it, and then broadcast the responses. This separates the concerns so you can continue to write "applications" without gevent, etc.

I think you could do this within a single Aspen process. Have a "realtime engine" that does just this so you can continue to write Aspen websites the way you have. You'll break connections on upgrades this way. Though if you expose the engine in the CLI, you could run the engine and your Aspen application in separate processes or even separate machines, you'll get that feature back when it becomes important.

@chadwhitacre
Copy link
Contributor Author

You could use two ports or subdomains instead of two machines.

Right. I was really hoping we could find a way to avoid two ports/subdomains.

@joeyespo
Copy link
Contributor

Well you could use nginx URL-based routing. Or if you want it all in one process, have Aspen route the websocket connection requests to the realtime engine, and web requests sent directly, bypassing the pubsub mechanism.

The realtime engine can still be its own thing, within Aspen. And if it's exposed, you have the choice of using a dedicated machine, scaling up the number of WSGI instances and background workers as-needed and allowing server updates without losing connections. For small projects, these probably aren't a concern yet, so having the code in Aspen is useful.

@chadwhitacre
Copy link
Contributor Author

P.S. Websockets are in labs at Heroku now:

https://devcenter.heroku.com/articles/heroku-labs-websockets

@chadwhitacre
Copy link
Contributor Author

Here's a slide deck on "Making HTTP realtime with HTTP 2.0":

https://docs.google.com/presentation/d/1eqae3OBCxwWswOsaWMAWRpqnmrVVrAfPQclfSqPkXrA/present#slide=id.p19

@galuszkak
Copy link

@whit537 don't know why none mention but:
gevent-socketio

I was using it with Django and they worked really fine :)

@pjz pjz changed the title implement websocket transport for socket simplates (Re-)Implement websocket/socket.io simplates May 6, 2014
@pjz
Copy link
Contributor

pjz commented May 6, 2014

Okay, #324 just dropped socket simplates as part of ripping out network_engines. This is an issue to remind us that someday we want that functionality back.

@pjz
Copy link
Contributor

pjz commented Sep 21, 2018

...there's a new solution: ASGI which has a good summary in the intro. I think this will allow @chadwhitacre 's original vision of allowing a simplate to be either a page or a websocket.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants