【Python使用】嘿馬頭條項(xiàng)目從到完整開發(fā)教程第10篇:APScheduler定時(shí)任務(wù),定時(shí)修正統(tǒng)計(jì)數(shù)據(jù)【附代碼文檔】

??????教程全知識(shí)點(diǎn)簡介:1.APScheduler任務(wù)調(diào)度涵蓋安裝配置、使用方式、調(diào)度器Scheduler、執(zhí)行器executors、觸發(fā)器Trigger等核心組件。2. RPC遠(yuǎn)程過程調(diào)用包括RPC概念、背景用途、優(yōu)缺點(diǎn)分析。3. Protocol Buffers數(shù)據(jù)序列化涉及文檔結(jié)構(gòu)、注釋語法、數(shù)據(jù)類型、枚舉類型、消息類型(字段編號(hào)、字段規(guī)則、嵌套類型、保留字段、默認(rèn)值)。4. 客戶端開發(fā)包含頭條首頁新聞推薦接口編寫。5. 即時(shí)通訊技術(shù)涵蓋需求場景、傳統(tǒng)推送實(shí)現(xiàn)、Socket.IO(Python服務(wù)器端開發(fā)、事件處理)。6. Elasticsearch搜索引擎包括簡介原理、倒排索引、分析器、相關(guān)性排序、集群概念、IK中文分析器、索引類型、文檔操作(索引文檔、獲取文檔、判斷存在、更新刪除)、Logstash數(shù)據(jù)導(dǎo)入、查詢(基本查詢、高級(jí)查詢)、全文檢索實(shí)現(xiàn)、Python客戶端使用、聯(lián)想提示(拼寫糾錯(cuò)、自動(dòng)補(bǔ)全)。7. 單元測(cè)試涵蓋測(cè)試分類、基本寫法、測(cè)試必要性。8. 服務(wù)器部署包括Gunicorn、Supervisor配置管理。9. 項(xiàng)目開發(fā)流程涉及產(chǎn)品介紹、原型圖UI圖、技術(shù)架構(gòu)、開發(fā)環(huán)境(ToutiaoWeb虛擬機(jī)、Pycharm遠(yuǎn)程開發(fā))。10. 數(shù)據(jù)庫技術(shù)包含ORM理解、SQLAlchemy映射構(gòu)建、數(shù)據(jù)庫連接設(shè)置、模型類字段選項(xiàng)。11. 分布式系統(tǒng)涵蓋分布式ID方案選擇、Twitter Snowflake算法(64位ID劃分、最大取值計(jì)算、移位偏移計(jì)算、序號(hào)循環(huán)掩碼、時(shí)間戳處理)。12. Redis數(shù)據(jù)庫包括Redis持久化機(jī)制。13. Git工作流涵蓋Gitflow工作流(工作方式、歷史分支、功能分支、發(fā)布分支、維護(hù)分支)、調(diào)試方法。14. 身份認(rèn)證技術(shù)包含JWT、JWS、JWE概念、Python庫使用、項(xiàng)目封裝實(shí)施方案。15. 對(duì)象存儲(chǔ)涉及OSS對(duì)象存儲(chǔ)、七牛云存儲(chǔ)服務(wù)。16. 緩存系統(tǒng)包括緩存架構(gòu)、緩存數(shù)據(jù)保存方式、緩存有效期TTL、緩存淘汰策略、緩存問題(緩存穿透、緩存雪崩)、頭條項(xiàng)目緩存設(shè)計(jì)(User Cache、Article Cache、Announcement Cache)、持久存儲(chǔ)設(shè)計(jì)(閱讀歷史、搜索歷史、統(tǒng)計(jì)數(shù)據(jù))。


??????????本站這篇博客:???http://www.itdecent.cn/p/043de7e784eb ???中查看

??????????本站這篇博客:???http://www.itdecent.cn/p/043de7e784eb ???中查看

??????????本站這篇博客:???http://www.itdecent.cn/p/a558bfa41765 ???中查看

? 本教程項(xiàng)目亮點(diǎn)

?? 知識(shí)體系完整:覆蓋從基礎(chǔ)原理、核心方法到高階應(yīng)用的全流程內(nèi)容
?? 全技術(shù)鏈覆蓋:完整前后端技術(shù)棧,涵蓋開發(fā)必備技能
?? 從零到實(shí)戰(zhàn):適合 0 基礎(chǔ)入門到提升,循序漸進(jìn)掌握核心能力
?? 豐富文檔與代碼示例:涵蓋多種場景,可運(yùn)行、可復(fù)用
?? 工作與學(xué)習(xí)雙參考:不僅適合系統(tǒng)化學(xué)習(xí),更可作為日常開發(fā)中的查閱手冊(cè)
?? 模塊化知識(shí)結(jié)構(gòu):按知識(shí)點(diǎn)分章節(jié),便于快速定位和復(fù)習(xí)
?? 長期可用的技術(shù)積累:不止一次學(xué)習(xí),而是能伴隨工作與項(xiàng)目長期參考


??????全教程總章節(jié)


??????本篇主要內(nèi)容

APScheduler定時(shí)任務(wù)

定時(shí)修正統(tǒng)計(jì)數(shù)據(jù)

toutiao-backend/toutiao/__init__.py中添加APScheduler調(diào)度器對(duì)象

from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.executors.pool import ThreadPoolExecutor

def create_app(config, enable_config_file=False):
    ...

    # 添加定時(shí)任務(wù)APScheduler
    executors = {
        'default': ThreadPoolExecutor(10)
    }
    app.scheduler = BackgroundScheduler(executors=executors)

    from .schedule.statistic import fix_statistics

    # 每天3點(diǎn)執(zhí)行
    app.scheduler.add_job(fix_statistics, 'cron', hour=3, args=[app])
    # 立即執(zhí)行,用于測(cè)試
    # app.scheduler.add_job(fix_statistics, 'date', args=[app])

    app.scheduler.start()

    ...

toutiao-backend/toutiao中新建schedule目錄用于存放定時(shí)任務(wù)

toutiao-backend/toutiao/schedule/statistics.py

from cache import statistic as cache_statistic

def fix_process(count_storage_cls):
    """
    修復(fù)處理方法
    """
    # 進(jìn)行數(shù)據(jù)庫查詢
    ret = count_storage_cls.db_query()
    # 設(shè)置redis數(shù)據(jù)
    count_storage_cls.reset(ret)

def fix_statistics(flask_app):
    """
    修正統(tǒng)計(jì)數(shù)據(jù)
    """
    with flask_app.app_context():
        fix_process(cache_statistic.UserArticlesCountStorage)
        fix_process(cache_statistic.UserFollowingsCountStorage)

common/cache/statistic.py

class CountStorageBase(object):
    """
    統(tǒng)計(jì)數(shù)量存儲(chǔ)的父類
    """
    ...

    @classmethod
    def reset(cls, db_query_ret):
        """
        由定時(shí)任務(wù)調(diào)用的重置數(shù)據(jù)方法
        """
        # 設(shè)置redis的存儲(chǔ)記錄
        pl = current_app.redis_master.pipeline()
        pl.delete(cls.key)

        # zadd(key, score1, val1, score2, val2, ...)
        # 方式一
        # for data_id, count in db_query_ret:
        #     pl.zadd(cls.key, count, data_id)

        # 方式二
        redis_data = []
        for data_id, count in db_query_ret:
            redis_data.append(count)
            redis_data.append(data_id)

        # redis_data = [count1, data_id1, count2, data_id2, ..]
        pl.zadd(cls.key, *redis_data)
        # pl.zadd(cls.key, count1, data_id1, count2, data_id2, ..]

        pl.execute()

class UserArticlesCountStorage(CountStorageBase):
    """
    用戶文章數(shù)量
    """
    key = 'count:user:arts'

    @staticmethod
    def db_query():
        ret = db.session.query(Article.user_id, func.count(Article.id)) \
            .filter(Article.status == Article.STATUS.APPROVED).group_by(Article.user_id).all()
        return ret


class UserFollowingsCountStorage(CountStorageBase):
    """
    用戶關(guān)注數(shù)量
    """
    key = 'count:user:followings'

    @staticmethod
    def db_query():
        ret = db.session.query(Relation.user_id, func.count(Relation.target_user_id)) \
            .filter(Relation.relation == Relation.RELATION.FOLLOW)\
            .group_by(Relation.user_id).all()
        return ret

Jupyter 文檔

APScheduler定時(shí)任務(wù)

RPC簡介

1. 什么是RPC

遠(yuǎn)程過程調(diào)用(英語:Remote Procedure Call,縮寫為 RPC,也叫遠(yuǎn)程程序調(diào)用)是一個(gè)計(jì)算機(jī)通信協(xié)議。該協(xié)議允許運(yùn)行于一臺(tái)計(jì)算機(jī)的程序調(diào)用另一臺(tái)計(jì)算機(jī)的子程序,而程序員無需額外地為這個(gè)交互作用編程。如果涉及的軟件采用面向?qū)ο缶幊蹋敲催h(yuǎn)程過程調(diào)用亦可稱作遠(yuǎn)程調(diào)用遠(yuǎn)程方法調(diào)用。

2. 背景與用途

在單臺(tái)計(jì)算機(jī)中, 可以通過程序調(diào)用來傳遞控制和數(shù)據(jù);或者說通過程序調(diào)用, 可以將多個(gè)程序組成一個(gè)整體來實(shí)現(xiàn)某個(gè)功能。

aiohttp 文檔

如果將這種調(diào)用機(jī)制推廣到多臺(tái)彼此間可以進(jìn)行網(wǎng)絡(luò)通訊的計(jì)算機(jī),由多臺(tái)計(jì)算機(jī)中的多個(gè)程序組成一個(gè)整體來實(shí)現(xiàn)某個(gè)功能,這也是可以的。調(diào)用的一方(發(fā)起遠(yuǎn)程過程調(diào)用,然后調(diào)用這方的環(huán)境掛起,參數(shù)通過網(wǎng)絡(luò)傳遞給被調(diào)用方,被調(diào)用的一方執(zhí)行程序,當(dāng)程序執(zhí)行完成后,產(chǎn)生的結(jié)果再通過網(wǎng)絡(luò)回傳給調(diào)用的一方,調(diào)用的一方恢復(fù)繼續(xù)執(zhí)行。這樣一種原型思想,就是 所說的RPC遠(yuǎn)程過程調(diào)用。

RPC這種思想最早可以追溯到1976年,RPC的發(fā)展到今天已經(jīng)40年有余了。

如今的計(jì)算機(jī)應(yīng)用中,單機(jī)性能上很難承受住產(chǎn)品的壓力,需要不斷擴(kuò)充多臺(tái)機(jī)器來提升整體的性能。同時(shí)為了充分利用這些集群里的計(jì)算機(jī),需要對(duì)其從架構(gòu)上進(jìn)行劃分,以提供不同的服務(wù),服務(wù)間相互調(diào)用完成整個(gè)產(chǎn)品的功能。RPC就能幫助 解決這些服務(wù)間的信息傳遞和調(diào)用。

3. 概念說明

關(guān)于RPC的概念, 可以從廣義和狹義來分別進(jìn)行理解。

廣義

可以將所有通過網(wǎng)絡(luò)來進(jìn)行通訊調(diào)用的實(shí)現(xiàn)統(tǒng)稱為RPC。

按照這樣來理解的話,那 發(fā)現(xiàn)HTTP其實(shí)也算是一種RPC實(shí)現(xiàn)。

狹義

區(qū)別于HTTP的實(shí)現(xiàn)方式,在傳輸?shù)臄?shù)據(jù)格式上和傳輸?shù)目刂粕溪?dú)立實(shí)現(xiàn)。比如在機(jī)器間通訊傳輸?shù)臄?shù)據(jù)不采用HTTP協(xié)議的方式(分為起始行、header、body三部份),而是使用自定義格式的二進(jìn)制方式。

更多時(shí)候談到的RPC都是指代這種狹義上的理解。

aiofiles 文檔

4. 優(yōu)缺點(diǎn)

pydantic 文檔

相比于傳統(tǒng)HTTP的實(shí)現(xiàn)而言:

優(yōu)點(diǎn)

  • 效率高
  • 發(fā)起RPC調(diào)用的一方,在編寫代碼時(shí)可忽略RPC的具體實(shí)現(xiàn),如同編寫本地函數(shù)調(diào)用一樣

缺點(diǎn)

  • 通用性不如HTTP好 因?yàn)閭鬏數(shù)臄?shù)據(jù)不是HTTP協(xié)議格式,所以調(diào)用雙方需要專門實(shí)現(xiàn)的通信庫,對(duì)于不同的編程開發(fā)語言,都要有相關(guān)實(shí)現(xiàn)。而HTTP作為一個(gè)標(biāo)準(zhǔn)協(xié)議,大部分的語言都已有相關(guān)的實(shí)現(xiàn),通用性更好。

HTTP更多的面向用戶與產(chǎn)品服務(wù)器的通訊。

RPC更多的面向產(chǎn)品內(nèi)部服務(wù)器間的通訊。 thrift

invoke 文檔

RPC結(jié)構(gòu)

RPC的設(shè)計(jì)思想是力圖使遠(yuǎn)程調(diào)用中的通訊細(xì)節(jié)對(duì)于使用者透明,調(diào)用雙方無需關(guān)心網(wǎng)絡(luò)通訊的具體實(shí)現(xiàn)。因而實(shí)現(xiàn)RPC要進(jìn)行一定的封裝。

RPC原理上是按如下結(jié)構(gòu)流程進(jìn)行實(shí)現(xiàn)的。

流程:

  1. 調(diào)用者(Caller, 也叫客戶端、Client)以本地調(diào)用的方式發(fā)起調(diào)用;
  2. Client stub(客戶端存根,可理解為輔助助手)收到調(diào)用后,負(fù)責(zé)將被調(diào)用的方法名、參數(shù)等打包編碼成特定格式的能進(jìn)行網(wǎng)絡(luò)傳輸?shù)南Ⅲw;
  3. Client stub將消息體通過網(wǎng)絡(luò)發(fā)送給對(duì)端(服務(wù)端)
  4. Server stub(服務(wù)端存根,同樣可理解為輔助助手)收到通過網(wǎng)絡(luò)接收到消息后按照相應(yīng)格式進(jìn)行拆包解碼,獲取方法名和參數(shù);
  5. Server stub根據(jù)方法名和參數(shù)進(jìn)行本地調(diào)用;
  6. 被調(diào)用者(Callee,也叫Server)本地調(diào)用執(zhí)行后將結(jié)果返回給server stub;
  7. Server stub將返回值打包編碼成消息,并通過網(wǎng)絡(luò)發(fā)送給對(duì)端(客戶端);
  8. Client stub收到消息后,進(jìn)行拆包解碼,返回給Client;
  9. Client得到本次RPC調(diào)用的最終結(jié)果。

gRPC

簡介

  • gRPC是由Google公司開源的高性能RPC框架。

  • gRPC支持多語言

gRPC原生使用C、Java、Go進(jìn)行了三種實(shí)現(xiàn),而C語言實(shí)現(xiàn)的版本進(jìn)行封裝后又支持C++、C#、Node、ObjC、 Python、Ruby、PHP等開發(fā)語言

  • gRPC支持多平臺(tái)

支持的平臺(tái)包括:Linux、Android、iOS、MacOS、Windows

  • gRPC的消息協(xié)議使用Google自家開源的Protocol Buffers協(xié)議機(jī)制(proto3) 序列化

  • gRPC的傳輸使用HTTP/2標(biāo)準(zhǔn),支持雙向流和連接多路復(fù)用

架構(gòu)

C語言實(shí)現(xiàn)的gRPC支持多語言,其架構(gòu)如下

使用方法

  1. 使用Protocol Buffers(proto3)的IDL接口定義語言定義接口服務(wù),編寫在文本文件(以.proto為后綴名)中。
  2. 使用protobuf編譯器生成服務(wù)器和客戶端使用的stub代碼
  3. 編寫補(bǔ)充服務(wù)器和客戶端邏輯代碼

RPC

Protocol Buffers

Protocol Buffers 是一種與語言無關(guān),平臺(tái)無關(guān)的可擴(kuò)展機(jī)制,用于序列化結(jié)構(gòu)化數(shù)據(jù)。使用Protocol Buffers 可以一次定義結(jié)構(gòu)化的數(shù)據(jù),然后可以使用特殊生成的源代碼輕松地在各種數(shù)據(jù)流中使用各種語言編寫和讀取結(jié)構(gòu)化數(shù)據(jù)。

現(xiàn)在有許多框架等在使用Protocol Buffers。gRPC也是基于Protocol Buffers。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容