覆盖worker
多亏了暴露给插件的”worker”钩子,你可以覆盖每个uWSGI worker运行的代码。
目前,python插件是唯一一个暴露它的插件:
- [uwsgi]
- ; create a bunch of sockets
- socket = 127.0.0.1:3031
- socket = 127.0.0.1:3032
- ; spawn the master
- master = true
- ; spawn 4 processes
- processes = 4
- ; load a python script as the worker code
- python-worker-override = aioserver.py
该python脚本可以访问uwsgi模块,因此它可以控制/改变内部逻辑。
下面的例子展示了aiohttp的使用 (需要python 3.5)
- import asyncio
- from aiohttp import web
- import uwsgi
- import socket
- import sys
- import signal
- async def handle(request):
- name = request.match_info.get('name', "Anonymous")
- text = "Hello, " + name
- return web.Response(body=text.encode('utf-8'))
- async def wshandler(request):
- ws = web.WebSocketResponse()
- await ws.prepare(request)
- async for msg in ws:
- if msg.tp == web.MsgType.text:
- ws.send_str("Hello, {}".format(msg.data))
- elif msg.tp == web.MsgType.binary:
- ws.send_bytes(msg.data)
- elif msg.tp == web.MsgType.close:
- break
- return ws
- async def init(loop, fd):
- app = web.Application(loop=loop)
- app.router.add_route('GET', '/echo', wshandler)
- app.router.add_route('GET', '/{name}', handle)
- srv = await loop.create_server(app.make_handler(),
- sock=socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM))
- print("asyncio server started on uWSGI {0}".format(uwsgi.version))
- return srv
- def destroy():
- print("destroy worker {0}".format(uwsgi.worker_id()))
- sys.exit(0)
- def graceful_reload():
- print("graceful reload for worker {0}".format(uwsgi.worker_id()))
- # TODO do somethign meaningful
- sys.exit(0)
- loop = asyncio.get_event_loop()
- loop.add_signal_handler(signal.SIGINT, destroy)
- loop.add_signal_handler(signal.SIGHUP, graceful_reload)
- # spawn a handler for every uWSGI socket
- for fd in uwsgi.sockets:
- loop.run_until_complete(init(loop, fd))
- uwsgi.accepting()
- loop.run_forever()
在这个例子中 (来自官方的aiohttp文档),我们看到uwsgi.sockets列表 (保存uWSGI socket文件描述符列表),以及对SIGINT和SIGHUP的覆盖,以支持重新加载 (SIGHUP应该调整以支持等待所有的入队请求)
调用 uwsgi.accepting()
以通知master,worker正在接收请求,这对于touch-chain-reload正常工作是必须的。
应该扩展该脚本,在每个请求后调用uwsgi.log(…),以及(最后)更新一些度量