gunicorn + flask + gevent + websocket
エコーバックするだけのアプリです。
websocket といえば node.js みたいな空気が嫌だったので python でもやれるよってことを書きたかっただけっていう。
apache で公開しようとするとなんか普通にやっても無理っぽいし、じゃあ gunicorn 使えばいいじゃんってことでやってみたんだけど意外とこういう情報がまとまっていなかったので折角だし。
gunicorn, libevent は既に入っているものとして書きます。
python 側は、flask, gevent, gevent-websocket が必要になるので pip とかで install してください。
ファイル構成
├── gunicorn.py ├── index.py ├── runserver.sh └── templates └── index.html
index.py
#!/bin/env python from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import WSGIServer from flask import Flask, request, render_template app = Flask(__name__) app.config.from_object(__name__) ctx = {} ctx['port'] = 8080 @app.route('/') def index(): return render_template('index.html', ctx=ctx) @app.route('/api') def api(): if request.environ.get('wsgi.websocket'): ws = request.environ['wsgi.websocket'] while True: message = ws.receive() if message is None: break ws.send(message) return if __name__ == '__main__': http_server = WSGIServer(('',ctx['port']), app, handler_class=WebSocketHandler) http_server.serve_forever()
templates/index.html
<!DOCTYPE HTML> <html> <head> <title>Flask/Gevent WebSocket Test</title> <script type="text/javascript" src="http://code.jquery.com/jquery-1.8.2.min.js"></script> <script type="text/javascript" charset="utf-8"> $(document).ready(function(){ $('form').submit(function(event){ ws.send($('#data').val()) return false; }); if ("WebSocket" in window) { ws = new WebSocket("ws://" + document.domain + ":" + {{ ctx.port }} + "/api"); console.log("WebSocket is supported by your Browser!"); // Let us open a web socket ws.onopen = function() { // Web Socket is connected. console.log("Message is sent..."); }; ws.onmessage = function(msg) { $("#log").append("<p>"+msg.data+"</p>") }; ws.onerror = function() { // websocket is closed. console.log("Error ..."); }; ws.onclose = function() { // websocket is closed. console.log("Connection is closed..."); }; } else { alert("WebSocket not supported"); } }); </script> </head> <body> <p>gunicorn + flask + gevent + websocket</p> <h1>Send:</h1> <form method='POST' action='#'> <textarea name='data' id="data"></textarea> <div><input type='submit'></div> </form> <h1>Receive:</h1> <div id="log"></div> </body> </html>
gunicorn.py
bind = '127.0.0.1:8080' workers = 5 backlog = 2048 worker_class = 'gevent' debug = True daemon = True pidfile = 'gunicorn.pid' logfile = 'gunicorn.log'
runserver.sh
pkill -f 'gunicorn' gunicorn -c gunicorn.py -k "geventwebsocket.gunicorn.workers.GeventWebSocketWorker" index:app
参考
flask + gevent + websocket - http://blog.liris.org/2010/11/flask-gevent-websocket.html
gevent-websocket - http://www.gelens.org/code/gevent-websocket/