遊戲類或是論壇類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 刪除時間 """
複製代碼
到這裏一個簡陋的積分系統就基本完成了,不過這樣制定的規則會有不少限制,好比分享博客能夠得到積分這種,若是針對某個具體的博客分享後所得到積份量不一樣,這就須要更進一步的設計。異步