游戏类或是论坛类web应用,到后面不少都会有积分系统:像发成功一篇文章,回复一条博客得多少积分这种。积分系统和不少的业务场景都有关系,可是和具体的用户请求没有关系。应该将积分系统和具体的业务程序进行隔离,以下降耦合度。笔者要开发的积分系统不须要具备实时性
,因此打算用异步的方式来实现积分计算程序。 实现方案:html
- 使用
celery
实现积分计算和验证程序- 在django middleware 中准备好参数,并异步调用积分系统
Middleware is a framework of hooks into Django’s request/response processing. It’s a light, low-level “plugin” system for globally altering Django’s input or output. 以上摘自django官网 我的以为 django middleware 是一种面向方面编程(AOP)思想的实现: 对全部的views程序提供统一的无感的处理。实际场景中可用middleware来统一response输出格式,统一异常处理,还有统一在输入中加入登陆验证信息等。 新版的自定义middleware方式很简单:python
class TestMiddleware:
def __init__(self, get_response):
self.get_response = get_response
# 这后面写的代码对中间件进行初始化,只执行一次
def __call__(self, request):
# 这里写的代码在调用view的方法以前执行,能够对request进行处理
response = self.get_response(request)
# 这里写的代码在调用view方法以后执行,能够对response的返回值进行统一格式处理等
return response
复制代码
# 注意: django调用middle时按照这里的排列顺序来 装饰 的,越前面的装饰的越外层,即:
# 排在越前面的,在调用views方法前越早被执行,调用views方法后越晚被执行
# 排在越后面的,在调用views方法前越晚被执行,调用views方法后越早被执行
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'your middleware path',
]
复制代码
写好这些后,这个middleware就完成了 django middlewaregit
Celery - Distributed Task Queue Celery is a simple, flexible, and reliable distributed system to process vast amounts of messages, while providing operations with the tools required to maintain such a system. It’s a task queue with focus on real-time processing, while also supporting task scheduling. 以上信息摘自celery官网 celery是用python语言开发的分布式任务队列,可用于任务的同步处理(接收任务处理返回结果),也可用于异步处理(不接收返回结果)。在django中处理异步任务(发邮件;消息推送等)时,celery是个很好的选择。 运行celery须要中间件,这里使用rabbitMQ,下面简单介绍如何集成。github
PATH=$PATH:/usr/local/sbin
$ sudo rabbitmqctl add_user myuser mypassword
$ sudo rabbitmqctl add_vhost myvhost
$ sudo rabbitmqctl set_user_tags myuser mytag
$ sudo rabbitmqctl set_permissions -p myvhost myuser ".*" ".*" ".*"
设置好后在celery中直接配置'amqp://myuser:mypassword@localhost:5672/myvhost'
就能够用了web
sudo rabbitmq-server
之后台运行方式启动: $ sudo rabbitmq-server -detached
中止: $ sudo rabbitmqctl stop
Never use kill (kill(1)) to stop the RabbitMQ server(忌直接杀进程!!!) 详细操做见rabbit官网celery 是用python开发的,能够直接用pip安装 $ pip install -U Celery
更多详细安装选项见celery官网django
django集成celery是将celery的配置嵌入到django的settings文件中,更重要的,是celery执行任务的时候,能直接使用django项目的运行环境。编程
CELERY_BROKER_URL = 'amqp://myuser:mypassword@localhost:5672/myvhost'
celery.py
,文件放在settings的同级目录下from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'test_app.settings')
app = Celery('msl')
# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')
# Load task modules from all registered Django app configs.
app.autodiscover_tasks()
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
复制代码
一级目录
下面新建python文件,名称为 tasks.py用于构建自定义的任务。# Create your tasks here
from __future__ import absolute_import, unicode_literals
from celery import shared_task
@shared_task
def add(x, y):
return x + y
@shared_task
def mul(x, y):
return x * y
@shared_task
def xsum(numbers):
return sum(numbers)
复制代码
supervisord
等管理程序进行启停管理。非后台方式启动为:celery -A proj worker -l info
;proj 为celery所在目录的目录名,不作修改的话就是项目名字。 这样启动的使用ctrl + c
中止就能够。 django集成celery官方示例
- 本次调用的具体是哪一个业务(request的METHOD和path一块儿来肯定)
签到接口调用:调用完成后,在task中判断,若是这次签到调用成功,则记录该时间点上完成某个用户完成一次签到任务session
将奖励规则制定为: 完成一次签到任务能够得到1点积分,连续完成十次签到任务能够额外得到2点积分。则这次签到任务完成后,会对应去判断这两条规则。第一条确定直接知足,记录下该条规则下签到获取积分进度为完成,并记录积分获取记录。第二条若是不知足,记录下该规则下调到积分获取进度为未完成,未完成的就没有积分获取记录了。app
from django.db import models
class TaskConfig(models.Model):
"""任务配置表 task_type 任务类型 task_desc 任务描述 method 方法(GET, POST, ...) interface_name 接口名 id_group_name 业务主键分组名字(正则式中的分组名称) status 状态 (编辑中, 使用中, 废弃) created_at 建立时间 deleted_at 删除时间 updated_at 修改时间 """
class UserTaskRecord(models.Model):
"""用户任务记录表 user 用户 task 任务类型(外键) business_id 业务主键(建立博客的就是哪条博客的ID) created_at 建立时间 updated_at 修改时间 delete_at 删除时间 """
class ScoreRule(SoftDeleteModel):
"""积分规表 task_type 任务类型 score_type 积分规则类型 score_desc 积分规则描述 statistical_period 统计周期(天天,每周,每个月,每一年,无周期,...) required_number_of_times 所需次数 number_limit_all 获取人数上限 start_time 规则生效时间 end_time 规则截止时间 status 规则状态(编辑中和已生效) can_repeat 任务内容是否可重复(默认为可重复) created_at 建立时间 deleted_at 删除时间 updated_at 修改时间 """
class UserScoreInfo(SoftDeleteModel):
"""用户积分信息表 user 用户 achievement_type 积分规则类型(外键) required_number 所需任务量 achievement_amount_now 当任务就量 achieved 达成标志 created_at 建立时间 deadline 计算截止时间 updated_at 修改时间 deleted_at 删除时间 """
class ScoreRecord(SoftDeleteModel):
"""积分记录 profile 帐户 user 用户 serial_number 流水号 trade_amount 积分 amount_before_trade 计算前帐户积份量 amount_after_trade 计算后帐户积份量 business_type 业务类型(积分规则描述) score_info 积分信息(外键) location 地点 country 国家 lang_type 语言 created_at 建立时间 updated_at 修改时间 deleted_at 删除时间 """
复制代码
到这里一个简陋的积分系统就基本完成了,不过这样制定的规则会有不少限制,好比分享博客能够得到积分这种,若是针对某个具体的博客分享后所得到积份量不一样,这就须要更进一步的设计。异步