在开发微信小程序答题游戏后端的时候,遇到了很多坑。
-
Supervisor 环境变量需要在ini里面手动设置。
-
用root运行Celery,建立Celery实例的时候 platforms.C_FORCE_ROOT = True 。
-
Celery和Django结合:http://docs.jinkan.org/docs/celery/django/first-steps-with-django.html#using-celery-with-django 。
-
Celery多任务默认是会阻塞的,使用 -P eventlet(并发模式) -c [线程数] 开启并发。
-
Django Model的DateTimeField 类型在数据库中的时候为UTC时区,取出后实例中时为当前时区。
-
微信小程序推送的实现
主要说一下推送:
之前有个接口需要频繁地调用,所以采取了通过Websocket事件通知的形式来减少请求数量。
小程序端直接调用Websocket接口就行了,后端我是用Django写的,但是感觉Django channels和Django耦合度较高
所以我采用了Tornado,跑在另外的端口,请求通过Nginx转发,注意Nginx配置里面 proxy_set_header Connection “upgrade”; 开启支持Websocket。这里为了不阻塞其他Websocket请求,使用异步的Redis库:tornado-redis。
# coding: utf-8
import tornado.ioloop
import tornado.web
import tornado.websocket
import tornadoredis
from tornado import gen
CHANNEL = ['group_info', 'question_status']
class WSHandler(tornado.websocket.WebSocketHandler):
def __init__(self, *args, **kwargs):
self._redis_client = None
super(WSHandler, self).__init__(*args, **kwargs)
self._connect_to_redis()
self._listen()
def open(self):
pass
def _connect_to_redis(self):
self._redis_client = tornadoredis.Client(host='localhost', port=6379, selected_db=2)
self._redis_client.connect()
def on_message(self, message):
pass
# self.write_message(message)
@gen.coroutine
def _on_update(self, message):
if message.kind == 'message':
self.write_message(message.body)
@gen.engine
def _listen(self):
yield gen.Task(self._redis_client.subscribe, CHANNEL)
self._redis_client.listen(self._on_update)
def on_close(self):
self._redis_client.unsubscribe(CHANNEL)
self._redis_client.disconnect()
def check_origin(self, origin):
return True
def make_app():
return tornado.web.Application([
(r"/ws", WSHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
这里主要是通过Redis的订阅发布来实现。在HTTP请求中的一些操作触发了通知,比如新成员加入了群组后
直接操作redis发布消息到某个频道。
publish group_info somestring
具体的内容(somestring)可以自己和客户端商量一个协议,比如通过JSON等等