覆盖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(...),以及(最后)更新一些度量