在开发微信小程序答题游戏后端的时候,遇到了很多坑。

  1. Supervisor 环境变量需要在ini里面手动设置。

  2. 用root运行Celery,建立Celery实例的时候 platforms.C_FORCE_ROOT = True 。

  3. Celery和Django结合:http://docs.jinkan.org/docs/celery/django/first-steps-with-django.html#using-celery-with-django 。

  4. Celery多任务默认是会阻塞的,使用 -P eventlet(并发模式) -c [线程数] 开启并发。

  5. Django Model的DateTimeField 类型在数据库中的时候为UTC时区,取出后实例中时为当前时区。

  6. 微信小程序推送的实现

主要说一下推送:

之前有个接口需要频繁地调用,所以采取了通过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等等

截图