国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - 利用Celery實現Django博客PV統計功能詳解

利用Celery實現Django博客PV統計功能詳解

2020-10-07 22:14the5fire Python

給網站增加pv、uv統計,可以是件很簡單的事,也可以是件很復雜的事。下面這篇文章主要給大家介紹了利用Celery實現Django博客PV統計功能的相關資料,文中介紹的非常詳細,需要的朋友可以參考借鑒,下面來一起看看吧。

前言

前幾天給網站的文章增加了pv統計,之前只有uv統計。之前沒加pv統計是覺得每個用戶每訪問一次文章,我都需要做一次數據庫寫操作實在是有損性能,畢竟從用戶在the5fire博客的的一次訪問來看,只需要從數據庫里拿到對應的文章(通常情況下是從緩存中拿),然后返回給瀏覽器。寫操作無意義。之前的uv,也是針對每個用戶24小時內只會有一次寫操作。

不過話說回來,就對于the5fire博客這么個小站點來說,就算每次訪問我寫十幾次數據庫都沒啥影響,畢竟量小的可憐。但是咱們碼農不是得有顆抗億級流量的心嘛。

對于不理解的同學,可以出門調研下,看看別人家的網站。對,就是那些訪問量上億,十億,百億的網站,看看他們是怎么處理用戶寫入的,比如留言。

PV的意義

說完原因,再說業務。所有的網站都會有pv,uv這樣的統計。甚至是停留時長,各類型頁面轉換率等等各方各面的統計。我在搜狐的工作,大白話來說就是做網站。關注的業務指標就是流量相關的東西。同時作為站長這么多年,也會參考百度統計里的一些指標來做些調整。

不過這次只說pv,一篇文章的pv。

拋開非正常訪問,互聯網上的一篇文章,訪問他的人越多,那么意味著這篇文章的價值越高。畢竟有價值的東西大家才會點開看嘛。這個訪問量就是uv(User View/Visit)。那么pv是什么呢,一篇文章寫得很不錯,尤其是技術文章,可能會多次訪問,比如說我就喜歡把不錯的文章收藏起來,有空時回顧一下。每次回顧(刷新頁面)都算是一個pv。能做到人讀者多次閱讀的文章,價值會更高。所以一篇文章的pv/uv比也是衡量文章價值的一個指標。尤其是在標題黨遍布的年代。(好吧,這里再歪一句,標題黨不是自媒體時代的產物,博客時代就有,只是自媒體時代顯得更加集中顯現了而已)

單純的說價值沒啥感覺,古人不是說了嗎,價值能換幾斗米。(我胡謅的)

拿現在的所有新聞網站/媒體平臺來說,pv是可以和¥劃等號的。流量越大,意味著能夠有更多的收入,無論是來自廣告的收入,還是把流量釋放到其他渠道。有時候我也考慮,一切的目標真的是更好的理解用戶,給用戶推送他想看的東西嗎?或許是吧,但是始終繞不開的一個問題是,構建一個商業模式,讓廣告主和投資人為用戶的停留時長買單。讓用戶更多的停留在平臺上,消費更多的時間。(純屬個人觀點,明辨之,慎思之)

再拿另外一個更直接的例子,現在自媒體盛行,多少人想要100000+,一個好的公眾號,可以根據以往文章的瀏覽量(或者粉絲量)來定價廣告/軟文等各種類型合作的價格。其實你到微播易或者易贊看看就知道了。
這么看來pv是不是變得有吸引力了。

統計的方式

對于網站來說,the5fire了解到的pv,uv的統計方式有這么幾種

  • 像the5fire早期的做法:用戶每訪問一篇文章,文章pv+1,uv+1。傻大粗的做法。
  • the5fire博客現在的做法,寫一個分布式的任務服務,然后在業務代碼中調用。
  • 頁面埋點,標簽,或者引用js來發送數據到統計服務器上。
  • 收集nginx access-log(如果是用nginx的話),當然,格式需要自定義,起碼得加上user_id,然后做離線統計、匯總。

前兩種都是耦合比較重的實現方式,需要在具體頁面里插代碼。后兩種也類似,本質上都是收集nginx日志,但是收集的階段不同,第三種是頁面完全打開之后,nginx才會收到日志。而第四種是只要訪問頁面,并且upstream返回狀態碼為200就算成功,那怕最終用戶并未看到頁面。

總之,各有利弊,可以相互參考。

博客實現的方式

上面也說了,主要也是為了用下celery這個分布式任務隊列。在Django中使用是比較簡單的事情。

在Django中使用Celery,需要Celery運行時能夠使用這個Django項目的各個模塊,因此首先要指明settings模塊。我用的Django版本為1.11。在wsgi.py同級目錄下增加celery.py,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
# coding:utf-8
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
PROFILE = os.environ.get('DJANGO_SELFBLOG_PROFILE', 'develop') # 我是把settings.py拆成了:develop.py,product.py
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_selfblog.settings.%s" % PROFILE)
app = Celery('selfblog', broker="redis://127.0.0.1:6666/2")
app.config_from_object('django.conf:settings', namespace='CELERY')
# Load task modules from all registered Django app configs.
app.autodiscover_tasks()

這里使用了官方并不建議的redis作為broker,而不是Rabbitmq,主要是緩存用的是Redis,為了不引入更多需要維護的系統。

定義好啟動文件之后,就需要定義具體的tasks,在app/tasks.py中寫具體的任務:

?
1
2
3
4
5
6
7
8
9
10
11
# coding:utf-8
from __future__ import unicode_literals
from django.db.models import F
from .models import Post
from django_selfblog.celery import app
@app.task
def increase_pv(post_id):
 return Post.objects.filter(id=post_id).update(pv=F('pv')+1)
@app.task
def increase_uv(post_id):
 return Post.objects.filter(id=post_id).update(uv=F('uv')+1)

在訪問文章頁面的views.py對應位置增加調用:

?
1
2
3
4
from .tasks import increase_pv, increase_uv
# ....省略上下文
increase_pv.delay(self.post.id)
increase_uv.delay(self.post.id)

這樣,每次用戶訪問時計算pv和uv的邏輯就放到分布式的任務管理器中去執行了,不會影響本次訪問。

如果你想要查看任務的執行狀態,比如通過:

?
1
2
r = increase_pv.delay(self.post.id)
print r.ready()

想要這樣查看任務是否完成,那就需要引入django-celery-results,使用步驟如下:

  • pip install django-celery-results
  • 把django_celery_results放到INSTALLED_APPS中
  • 配置CELERY_RESULT_BACKEND = 'django-db'或者'django-cache'
  • 如果配置的是django-db,意味著結果需要存儲到數據庫中,那就要執行python manage.py migrate django_celery_results來建表

這些配置完成之后,剩下的就是部署了,the5fire博客每次更新完代碼重新部署時都是通過fabric來做的 fab re_deploy:master 代碼就會部署到服務器上。增加celery之后,只需要增加supervisord的配置,現在畢竟celery的代碼也是在博客代碼里。

supervisord增加配置:

?
1
2
3
4
5
6
7
8
9
10
11
12
[program:celery]
command=celery -A selfblog worker -P gevent --loglevel=INFO --concurrency=5
directory=/home/the5fire/selfblog/
process_name=%(program_name)s_%(process_num)d
umask=022
startsecs=0
stopwaitsecs=0
redirect_stderr=true
stdout_logfile=/tmp/log/celery_%(process_num)02d.log
numprocs=1
numprocs_start=1
environment=DJANGO_SELFBLOG_PROFILE=product

這樣每次重新部署,celery進程也會重新啟動。

Django Tips

在Django項目中,性能損耗最多的就是ORM,不熟悉的話很容易被坑。

就拿增加pv來說,用戶每次訪問一篇文章,pv字段+1,用代碼來說就是:

?
1
2
3
4
# 絕對不要寫這么蠢的代碼
post = Post.objects.get(pk=post_id)
post.pv = post.pv + 1
post.save()

這是最簡單的做法,但是大部分情況,用戶訪問一篇文章,這篇文章通常會在緩存中,畢竟不需要每次都去數據庫中獲取。這樣的話應該怎么處理呢,直觀的做法還是先獲取到post,然后+1,save,如上一樣。但這樣會存在競爭的問題。

比方說,同時100個人訪問一篇文章,我是啟動了多個線程/進程來處理請求,有可能出現所有進程在同一時刻執行了 post = Post.objects.get(pk=post_id) 假設現在數據庫中這篇文章的pv是100,那么此時post.pv就是100。那所有用戶執行完post.save()之后,結果均為101,也就是一百次并發訪問,可能出現pv只加1的情況。

要解決這個問題,兩個辦法。

一、加鎖,這個據我的了解Django沒有提供,需要自己來實現。但是沒人會這么做吧。 二、用mysql來執行自增,也就是我上面用到的。

對于方法二,在Django中怎么實現呢。其實翻譯為sql就是

?
1
UPDATE `blog_post` SET `pv` = (`blog_post`.`pv` + 1) WHERE `blog_post`.`id` = <post_id>;

Django代碼就是: Post.objects.filter(id=post_id).update(pv=F('pv')+1) ,關于F表達式可以參考官方文檔:https://docs.djangoproject.com/en/1.11/ref/models/expressions/#django.db.models.F

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:https://www.the5fire.com/pv-statistics-in-django-blog.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日韩一区二区三区在线观看 | 欧洲精品久久久久毛片完整版 | 麻豆乱码国产一区二区三区 | 亚洲国产成人av好男人在线观看 | 欧美日韩精品一区二区公司 | 91中文在线观看 | 欧美日在线 | 天天干夜夜弄 | 操久在线| www.av欧美| 亚洲天堂高清 | 九一午夜精品av | 一区二区三区视频 | 国产永久免费在线观看 | 久久69精品久久久久久久电影好 | 特黄特黄一级片 | 伊人网在线观看 | 久久久久久久成人 | 一级黄色大片免费 | 美女h视频 | 亚洲精品国产第一综合99久久 | 中文字幕在线免费看 | 伊人伊人 | 亚洲精品专区 | 91精品综合久久久久久五月天 | 在线国产一区二区 | 99精品一区二区 | 欧美精品一二区 | 久久久精品免费视频 | 欧美在线不卡 | 日韩精品免费视频 | 午夜四虎 | 国产精品久久久久久久7电影 | 欧美午夜精品一区二区三区电影 | 国产黄色小视频 | 一卡二卡久久 | 国产精品久久久91 | 在线视频 中文字幕 | 欧美午夜精品久久久 | 日韩在线成人 | 超碰成人在线免费 |