覆盖worker

多亏了暴露给插件的”worker”钩子,你可以覆盖每个uWSGI worker运行的代码。

目前,python插件是唯一一个暴露它的插件:

  1. [uwsgi]
  2. ; create a bunch of sockets
  3. socket = 127.0.0.1:3031
  4. socket = 127.0.0.1:3032
  5. ; spawn the master
  6. master = true
  7. ; spawn 4 processes
  8. processes = 4
  9. ; load a python script as the worker code
  10. python-worker-override = aioserver.py

该python脚本可以访问uwsgi模块,因此它可以控制/改变内部逻辑。

下面的例子展示了aiohttp的使用 (需要python 3.5)

  1. import asyncio
  2. from aiohttp import web
  3.  
  4. import uwsgi
  5. import socket
  6. import sys
  7. import signal
  8.  
  9. async def handle(request):
  10. name = request.match_info.get('name', "Anonymous")
  11. text = "Hello, " + name
  12. return web.Response(body=text.encode('utf-8'))
  13.  
  14. async def wshandler(request):
  15. ws = web.WebSocketResponse()
  16. await ws.prepare(request)
  17.  
  18. async for msg in ws:
  19. if msg.tp == web.MsgType.text:
  20. ws.send_str("Hello, {}".format(msg.data))
  21. elif msg.tp == web.MsgType.binary:
  22. ws.send_bytes(msg.data)
  23. elif msg.tp == web.MsgType.close:
  24. break
  25.  
  26. return ws
  27.  
  28. async def init(loop, fd):
  29. app = web.Application(loop=loop)
  30. app.router.add_route('GET', '/echo', wshandler)
  31. app.router.add_route('GET', '/{name}', handle)
  32.  
  33. srv = await loop.create_server(app.make_handler(),
  34. sock=socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM))
  35. print("asyncio server started on uWSGI {0}".format(uwsgi.version))
  36. return srv
  37.  
  38. def destroy():
  39. print("destroy worker {0}".format(uwsgi.worker_id()))
  40. sys.exit(0)
  41.  
  42. def graceful_reload():
  43. print("graceful reload for worker {0}".format(uwsgi.worker_id()))
  44. # TODO do somethign meaningful
  45. sys.exit(0)
  46.  
  47. loop = asyncio.get_event_loop()
  48. loop.add_signal_handler(signal.SIGINT, destroy)
  49. loop.add_signal_handler(signal.SIGHUP, graceful_reload)
  50. # spawn a handler for every uWSGI socket
  51. for fd in uwsgi.sockets:
  52. loop.run_until_complete(init(loop, fd))
  53. uwsgi.accepting()
  54. loop.run_forever()

在这个例子中 (来自官方的aiohttp文档),我们看到uwsgi.sockets列表 (保存uWSGI socket文件描述符列表),以及对SIGINT和SIGHUP的覆盖,以支持重新加载 (SIGHUP应该调整以支持等待所有的入队请求)

调用 uwsgi.accepting() 以通知master,worker正在接收请求,这对于touch-chain-reload正常工作是必须的。

应该扩展该脚本,在每个请求后调用uwsgi.log(…),以及(最后)更新一些度量