2015-03-17 3 views
1

Можно ли запустить (монтировать в вишневое дерево) класс websocket autobahnn для работы на одном и том же порту, но с другим URL-адресом?Витрины Cherrypy + Autobahn на том же порту

Например:

  • http://localhost:8080/web к серверу статического контента (HTML + JavaScript)
  • WS: // локальный: 8080/websocketA к серверу некоторые WS связи через класс WSA
  • WS: // локальный: 8080/websocketB к серверу некоторые WS связи через класс WSB

Это моя конфигурация автобан & пробег:

self.loop = asyncio.new_event_loop() 
asyncio.set_event_loop(self.loop) 

factory = WebSocketServerFactory("ws://0.0.0.0:8081", debug = False) 
factory.protocol = WSA.SocketClient 

coro = self.loop.create_server(factory, "0.0.0.0", 8081) 
server = self.loop.run_until_complete(coro) 

self.loop.run_forever() 

Это моя конфигурация CherryPy & пробег:

cherrypy.config.update({ 
    'server.socket_host' : '0.0.0.0', 
    'server.socket_port' : 80, 
}) 

cherrypy.tree.mount(WebApi.Web(), '/web', { 
    '/': { 
     "tools.staticdir.on": True, 
     "tools.staticdir.root": os.path.dirname(os.path.abspath(__file__)), 
     "tools.staticdir.dir": "Web", 
     "tools.staticdir.index": "index.html" 
    } 
}) 

cherrypy.engine.start() 

На данный момент, WebSocket сервер работает на порту 8081, но я хотел бы, чтобы запустить его на тот же порт, как веб (8080). Если это возможно ..

+0

я сделал что-то похожее на это с WSS: и HTTPS :, я побежал HAProxy, который обработал соединение с веб-браузером, то HAProxy бэкенд направлены либо на моем HTTP-сервер или мой веб-сокетов маршрутизатора (автобан). Таким образом, они были на разных портах на бэкэнде, но они были тем же самым портом на интерфейсе (гапрокси выяснил, что именно). – Greg

ответ

1

Отвечая на ваш вопрос буквально, это значит, что вы не можете сделать это с CherryPy и Autobahn. Обычная обработка запросов CherryPy является синхронной и, кроме того, это поточный сервер. Другими словами, нецелесообразно посвятить поток подключению WebSocket. Способность CherryPy монтировать отдельное приложение WSGI здесь не имеет смысла, поскольку WSGI по сути является синхронным протоколом. И WebSockets по своей сути асинхронны. Но это не делает вас не может сделать это совсем иначе.

CherryPy и ws4py

К счастью, из-за смарт-дизайна CherryPy он не ограничивается WSGI и позволяет расширить. Этот факт используется в хорошей библиотеке автором CherryPy Сильваном Хельлегауархом, ws4py. У этого есть интеграция CherryPy.

#!/usr/bin/env python3 


import cherrypy 
from ws4py.server.cherrypyserver import WebSocketPlugin, WebSocketTool 
from ws4py.websocket import WebSocket 


class Ws: 

    @cherrypy.expose 
    def a(self): 
    '''WebSocket upgrade method. 
    Method must exist for ``WebSocketTool`` to work, 404 returned otherwise. 
    ''' 

    @cherrypy.expose 
    def b(self): 
    pass 


class HandlerA(WebSocket): 

    def received_message(self, message): 
    self.send('"A" is my reply') 


class HandlerB(WebSocket): 

    def received_message(self, message): 
    self.send('"B" is my reply') 


class App: 

    @cherrypy.expose 
    def index(self): 
    return '''<!DOCTYPE html> 
     <html> 
     <body> 
     <table cellspacing='10'> 
      <tr> 
      <td id='a'></td> 
      <td id='b'></td> 
      </tr> 
     </table> 

     <script type='application/javascript'> 
      var wsA  = new WebSocket('ws://127.0.0.1:8080/websocket/a'); 
      wsA.onmessage = function(event) 
      { 
      document.getElementById('a').innerHTML += event.data + '<br/>'; 
      }; 

      var wsB  = new WebSocket('ws://127.0.0.1:8080/websocket/b'); 
      wsB.onmessage = function(event) 
      { 
      document.getElementById('b').innerHTML += event.data + '<br/>'; 
      }; 

      setInterval(function() 
      { 
      wsA.send('foo'); 
      wsB.send('bar'); 
      }, 1000); 
      </script> 
     </body> 
     </html> 
    ''' 


if __name__ == '__main__': 
    cherrypy.config.update({ 
    'server.socket_host' : '127.0.0.1', 
    'server.socket_port' : 8080, 
    'server.thread_pool' : 8 
    }) 

    cherrypy.tools.websocket = WebSocketTool() 
    WebSocketPlugin(cherrypy.engine).subscribe() 

    cherrypy.tree.mount(Ws(), '/websocket', { 
    '/a' : { 
     'tools.websocket.on'   : True, 
     'tools.websocket.handler_cls' : HandlerA 
    }, 
    '/b' : { 
     'tools.websocket.on'   : True, 
     'tools.websocket.handler_cls' : HandlerB 
    } 
    }) 

    cherrypy.tree.mount(App(), '/') 

    cherrypy.engine.signals.subscribe() 
    cherrypy.engine.start() 
    cherrypy.engine.block() 

CherryPy, Nginx и АВТОБАН

С 1.3 nginx поддерживает WebSockets. Таким образом, вы можете легко мультиплексировать различные серверы.

server { 
    listen 80; 

    server_name localhost; 

    location /web { 
    proxy_pass   http://127.0.0.1:8080; 
    proxy_set_header Host    $host; 
    proxy_set_header X-Real-IP  $remote_addr; 
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
    } 

    location /websocket { 
    proxy_pass   http://127.0.0.1:8081; 
    proxy_set_header Host    $host; 
    proxy_set_header X-Real-IP  $remote_addr; 
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
    } 

} 
+0

Большое спасибо за ответ. Я сделал несколько тестов с Cherrypy/ws4py, и я заставил его работать :) Таким образом, ваш ответ на 100% правильный. – Baboon

0

Попробуйте использовать cherrypy.tree.graft для установки WSA на другой конечной точке (называемой «имя_источника» в документах cherrypy).

Смотрите пример здесь монтажных WSGI приложений на другой конечной точке, как статические файлы: http://rhodesmill.org/brandon/2011/wsgi-under-cherrypy/

Больше Docs здесь: http://cherrypy.readthedocs.org/en/latest/advanced.html#host-a-foreign-wsgi-application-in-cherrypy