
??????教程全知識(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
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è)功能。
如果將這種調(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都是指代這種狹義上的理解。
4. 優(yōu)缺點(diǎn)
相比于傳統(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
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)的。

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

使用方法
- 使用Protocol Buffers(proto3)的IDL接口定義語言定義接口服務(wù),編寫在文本文件(以
.proto為后綴名)中。 - 使用protobuf編譯器生成服務(wù)器和客戶端使用的stub代碼
- 編寫補(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。