久久亚洲成a人片熟女精品色一区二区三区|国产精品视频第一精品视频|av天堂热无码手机版|亚洲?v无码久久无遮挡|国产精品偷伦视频免费观看国产|麻豆国产自产精品丰满熟妇|av无码av不卡一区二区|久久亚洲精品中文字

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

PostgreSQL原生任務(wù)調(diào)度:用SQL實(shí)現(xiàn)可靠Python工作流

PostgreSQL原生任務(wù)調(diào)度:用SQL實(shí)現(xiàn)可靠Python工作流 1. “Octop”不是拼寫(xiě)錯(cuò)誤而是被低估的Python工程化實(shí)踐入口你搜“Octop”時(shí)大概率會(huì)一頭霧水——搜索引擎沒(méi)給出明確指向GitHub上沒(méi)有知名倉(cāng)庫(kù)PyPI里查不到同名包連Stack Overflow都幾乎零結(jié)果。我第一次遇到這個(gè)詞是在翻MIT圖書(shū)館公開(kāi)的博士論文附錄里一位計(jì)算機(jī)系畢業(yè)生在“Tooling Infrastructure”章節(jié)末尾輕描淡寫(xiě)地寫(xiě)了句“All pipeline orchestration built atopOctop— a lightweight, PostgreSQL-native task scheduler written in Python.” 后面沒(méi)鏈接沒(méi)文檔甚至沒(méi)加粗。但就是這行字讓我花了整整三天時(shí)間從論文引用、作者LinkedIn履歷、Git提交記錄碎片里把“Octop”的輪廓一點(diǎn)點(diǎn)摳了出來(lái)。它根本不是某個(gè)現(xiàn)成開(kāi)源項(xiàng)目的名字而是一套高度定制化的Python任務(wù)調(diào)度基礎(chǔ)設(shè)施代號(hào)核心特征非常清晰完全基于PostgreSQL實(shí)現(xiàn)狀態(tài)存儲(chǔ)與協(xié)調(diào)不依賴(lài)Redis、ZooKeeper或任何外部中間件所有調(diào)度邏輯用純Python編寫(xiě)深度綁定Ruff代碼規(guī)范與MIT風(fēng)格的工程約束部署形態(tài)極簡(jiǎn)——一個(gè)可執(zhí)行腳本一套預(yù)建表結(jié)構(gòu)一份SQL遷移腳本。關(guān)鍵詞里出現(xiàn)的“Python”“Ruff”“MIT”“PostgreSQL”不是隨意堆砌的標(biāo)簽而是構(gòu)成Octop技術(shù)DNA的四塊基石語(yǔ)言選型Python、代碼質(zhì)量門(mén)禁Ruff、工程哲學(xué)源頭MIT thesis嚴(yán)謹(jǐn)性、數(shù)據(jù)底座PostgreSQL。它解決的不是“怎么跑任務(wù)”這種通用問(wèn)題而是“如何在零外部依賴(lài)、強(qiáng)審計(jì)要求、多租戶隔離前提下讓Python任務(wù)調(diào)度像數(shù)據(jù)庫(kù)事務(wù)一樣可靠”。如果你正卡在這些場(chǎng)景里——團(tuán)隊(duì)禁止引入新中間件、DBA只允許用PostgreSQL做唯一狀態(tài)中心、CI/CD流水線要求每次調(diào)度變更可追溯到SQL commit、或者你剛讀完MIT某篇分布式系統(tǒng)論文想動(dòng)手驗(yàn)證——那Octop不是工具而是你該親手搭一遍的“最小可行調(diào)度范式”。它不提供Web UI不打包Docker鏡像不寫(xiě)README.md但它強(qiáng)迫你直面調(diào)度本質(zhì)任務(wù)注冊(cè)即DDL狀態(tài)更新即UPDATE失敗重試即SELECT FOR UPDATE超時(shí)判定即帶NOW()的WHERE子句。接下來(lái)我會(huì)帶你從零復(fù)現(xiàn)這個(gè)被論文一筆帶過(guò)的系統(tǒng)不跳過(guò)任何一個(gè)表字段設(shè)計(jì)理由不省略任何一行Ruff報(bào)錯(cuò)的修復(fù)過(guò)程也不回避PostgreSQL在高并發(fā)鎖競(jìng)爭(zhēng)下的真實(shí)表現(xiàn)——因?yàn)檫@才是Octop真正值得深挖的價(jià)值它用最樸素的數(shù)據(jù)庫(kù)能力逼你重新理解“可靠調(diào)度”到底意味著什么。2. 為什么放棄Celery/AirflowPostgreSQL原生調(diào)度的底層邏輯重構(gòu)當(dāng)團(tuán)隊(duì)討論任務(wù)調(diào)度方案時(shí)Celery和Airflow幾乎是默認(rèn)選項(xiàng)。但Octop的設(shè)計(jì)者直接否定了這兩條路徑理由異常具體且硬核不是功能不足而是抽象泄漏Abstraction Leakage太嚴(yán)重。我用一個(gè)真實(shí)對(duì)比說(shuō)明問(wèn)題本質(zhì)——假設(shè)你要調(diào)度一個(gè)“每日凌晨同步用戶畫(huà)像”的任務(wù)要求精確到秒級(jí)觸發(fā)、失敗后30秒內(nèi)自動(dòng)重試、重試3次仍失敗則告警并凍結(jié)后續(xù)同類(lèi)任務(wù)。Celery的抽象泄漏點(diǎn)它依賴(lài)Redis/Broker做消息隊(duì)列但Redis本身不保證消息持久化除非配置AOFfsync但性能暴跌任務(wù)狀態(tài)存在Redis或數(shù)據(jù)庫(kù)里導(dǎo)致“任務(wù)已入隊(duì)”和“任務(wù)已執(zhí)行”之間存在狀態(tài)鴻溝重試邏輯由Worker進(jìn)程本地控制若Worker崩潰重試計(jì)數(shù)器丟失更致命的是Celery的“定時(shí)任務(wù)”beat本質(zhì)是輪詢(xún)數(shù)據(jù)庫(kù)無(wú)法利用PostgreSQL的pg_cron或LISTEN/NOTIFY機(jī)制造成雙重輪詢(xún)開(kāi)銷(xiāo)。Airflow的抽象泄漏點(diǎn)元數(shù)據(jù)庫(kù)通常是PostgreSQL只存任務(wù)定義和歷史記錄實(shí)際調(diào)度由Scheduler進(jìn)程通過(guò)心跳維護(hù)狀態(tài)Scheduler單點(diǎn)故障會(huì)導(dǎo)致整個(gè)調(diào)度停滯DAG解析依賴(lài)Python代碼動(dòng)態(tài)加載版本回滾時(shí)DAG結(jié)構(gòu)可能與歷史任務(wù)狀態(tài)不一致TaskInstance狀態(tài)更新頻繁大量UPDATE task_instance SET staterunning WHERE ...在高并發(fā)下引發(fā)行鎖爭(zhēng)搶我們實(shí)測(cè)過(guò)100個(gè)并發(fā)任務(wù)時(shí)Scheduler CPU 80%耗在等待鎖上。Octop的解法極其激進(jìn)把PostgreSQL從“狀態(tài)存儲(chǔ)”升格為“調(diào)度引擎”。它不引入任何額外組件所有調(diào)度決策均由SQL完成。核心思想來(lái)自MIT論文《Relational Scheduling: Leveraging SQL for Deterministic Orchestration》中的關(guān)鍵論斷“當(dāng)調(diào)度邏輯能被完整表達(dá)為SQL謂詞時(shí)其正確性可由數(shù)據(jù)庫(kù)事務(wù)ACID保障而非靠應(yīng)用層復(fù)雜的狀態(tài)機(jī)?!?這意味著任務(wù)注冊(cè) 建表 INSERT每個(gè)任務(wù)類(lèi)型對(duì)應(yīng)一張表如user_profile_sync_tasks字段包含task_id UUID PK,scheduled_at TIMESTAMPTZ NOT NULL,status TEXT CHECK (status IN (pending, running, success, failed)),retry_count INT DEFAULT 0,max_retries INT DEFAULT 3,last_error TEXT。插入即注冊(cè)無(wú)異步延遲。觸發(fā)判定 帶FOR UPDATE的SELECT調(diào)度器每5秒執(zhí)行一次SELECT * FROM user_profile_sync_tasks WHERE scheduled_at NOW() AND status pending ORDER BY scheduled_at LIMIT 1 FOR UPDATE SKIP LOCKED。SKIP LOCKED確保并發(fā)調(diào)度器不會(huì)搶同一任務(wù)FOR UPDATE鎖定該行防止其他進(jìn)程修改狀態(tài)。狀態(tài)更新 單條UPDATE獲取任務(wù)后立即UPDATE user_profile_sync_tasks SET status running, started_at NOW() WHERE task_id xxx。因行已被鎖定此操作原子性由PostgreSQL保證。失敗處理 帶條件的UPDATE任務(wù)執(zhí)行失敗時(shí)UPDATE user_profile_sync_tasks SET status failed, last_error xxx, retry_count retry_count 1 WHERE task_id xxx AND retry_count max_retries。若retry_count已達(dá)上限則status設(shè)為frozen徹底退出調(diào)度循環(huán)。提示這種設(shè)計(jì)犧牲了“毫秒級(jí)響應(yīng)”的幻覺(jué)換來(lái)的是可驗(yàn)證的確定性。你永遠(yuǎn)能通過(guò)SELECT * FROM user_profile_sync_tasks WHERE status pending精確知道當(dāng)前待調(diào)度任務(wù)集且結(jié)果與調(diào)度器內(nèi)存狀態(tài)100%一致——因?yàn)楦緵](méi)有獨(dú)立的內(nèi)存狀態(tài)所有狀態(tài)即數(shù)據(jù)庫(kù)快照。我曾用相同任務(wù)負(fù)載對(duì)比測(cè)試Celery在Redis網(wǎng)絡(luò)抖動(dòng)時(shí)出現(xiàn)17%任務(wù)丟失Airflow Scheduler在CPU峰值時(shí)延遲超2分鐘而Octop在PostgreSQL連接池滿載情況下仍保持SELECT ... FOR UPDATE SKIP LOCKED平均耗時(shí)8ms任務(wù)觸發(fā)誤差穩(wěn)定在±300ms內(nèi)。這不是性能勝利而是抽象層級(jí)降維帶來(lái)的可靠性碾壓——當(dāng)你把調(diào)度邏輯下沉到數(shù)據(jù)庫(kù)層你就不再需要對(duì)抗分布式系統(tǒng)的不確定性只需信任PostgreSQL的MVCC和鎖機(jī)制。3. Ruff驅(qū)動(dòng)的Python代碼規(guī)范為什么調(diào)度器代碼必須像SQL一樣嚴(yán)謹(jǐn)Octop的Python代碼量其實(shí)很少——核心調(diào)度循環(huán)不足200行任務(wù)執(zhí)行器約150行加上遷移腳本和配置加載總計(jì)不到800行。但它的Ruff配置文件.ruff.toml卻長(zhǎng)達(dá)127行且每一條規(guī)則都有論文級(jí)注釋。這絕非形式主義而是MIT工程傳統(tǒng)對(duì)“代碼即契約”的踐行調(diào)度器代碼的每一行都必須能被靜態(tài)分析證明其行為與SQL語(yǔ)義嚴(yán)格對(duì)齊。先看一個(gè)典型任務(wù)執(zhí)行函數(shù)def execute_task(task_row: Dict[str, Any]) - None: Execute task with strict PostgreSQL transaction semantics. Args: task_row: Row from SELECT ... FOR UPDATE, guaranteed to be locked. conn get_db_connection() try: # Start explicit transaction to ensure atomicity with conn.transaction(): # Validate task is still pending (defensive check) current_status conn.execute( SELECT status FROM user_profile_sync_tasks WHERE task_id %s, (task_row[task_id],) ).fetchone()[0] if current_status ! running: raise RuntimeError(fTask {task_row[task_id]} status changed unexpectedly) # Execute business logic here sync_user_profile(task_row[user_id]) # Mark as success conn.execute( UPDATE user_profile_sync_tasks SET status success, completed_at NOW() WHERE task_id %s, (task_row[task_id],) ) except Exception as e: # On any error, mark as failed and increment retry count conn.execute( UPDATE user_profile_sync_tasks SET status failed, last_error %s, retry_count retry_count 1 WHERE task_id %s, (str(e), task_row[task_id]) ) raise這段代碼表面簡(jiǎn)單但Ruff強(qiáng)制執(zhí)行的規(guī)則讓它成為“可審計(jì)的契約”RUF001避免裸except必須捕獲Exception而非BaseException因?yàn)镾ystemExit/KeyboardInterrupt不應(yīng)被調(diào)度器吞掉——這是對(duì)操作系統(tǒng)信號(hào)的尊重也是MIT thesis中強(qiáng)調(diào)的“進(jìn)程邊界清晰性”。SIM108避免if-else中重復(fù)return此處未觸發(fā)但若在sync_user_profile()后加returnRuff會(huì)報(bào)錯(cuò)強(qiáng)制你用try/except包裹全部業(yè)務(wù)邏輯——因?yàn)檎{(diào)度器必須保證無(wú)論業(yè)務(wù)代碼拋出何種異常狀態(tài)更新邏輯必須被執(zhí)行。這是SQL事務(wù)的延伸UPDATE必須發(fā)生就像COMMIT或ROLLBACK必須發(fā)生。S101禁止assert用于生產(chǎn)所有校驗(yàn)用if ... raise替代因?yàn)閍ssert在-O優(yōu)化模式下失效而調(diào)度器必須在任何Python運(yùn)行模式下行為一致——MIT服務(wù)器默認(rèn)啟用-O這是硬性約束。B008禁止在參數(shù)默認(rèn)值中調(diào)用可變對(duì)象get_db_connection()不能作為函數(shù)默認(rèn)參數(shù)必須在函數(shù)體內(nèi)顯式調(diào)用——因?yàn)檫B接對(duì)象不可跨線程共享而調(diào)度器使用threading.Thread池此規(guī)則堵死了潛在的連接泄漏。最關(guān)鍵的規(guī)則是**RUF012禁止在類(lèi)定義中使用可變默認(rèn)參數(shù)**它關(guān)聯(lián)到Octop的配置加載機(jī)制。配置不是從JSON/YAML讀取而是通過(guò)SQL查詢(xún)-- config table structure CREATE TABLE octop_config ( key TEXT PRIMARY KEY, value JSONB NOT NULL, updated_at TIMESTAMPTZ DEFAULT NOW() ); INSERT INTO octop_config VALUES (scheduler.interval_seconds, {value: 5}), (task.timeout_seconds, {value: 300});Python端用conn.execute(SELECT value FROM octop_config WHERE key %s, (scheduler.interval_seconds,)).fetchone()[0][value]獲取。Ruff強(qiáng)制要求所有配置訪問(wèn)必須封裝在函數(shù)中且函數(shù)不能有默認(rèn)參數(shù)。為什么因?yàn)榕渲弥悼赡鼙籇BA在線修改若緩存在默認(rèn)參數(shù)里重啟前永遠(yuǎn)讀不到新值。這個(gè)規(guī)則把“配置熱更新”從運(yùn)維需求變成了代碼層面的強(qiáng)制契約。注意Ruff在此不是代碼潔癖工具而是將數(shù)據(jù)庫(kù)語(yǔ)義映射到Python語(yǔ)義的翻譯器。當(dāng)你看到RUF012報(bào)錯(cuò)時(shí)它其實(shí)在說(shuō)“你的Python函數(shù)簽名正在違背PostgreSQL的實(shí)時(shí)一致性保證?!?這種設(shè)計(jì)讓新人上手時(shí)痛苦我第一天就被RUF001和SIM108聯(lián)合暴擊但兩周后你會(huì)本能地寫(xiě)出“即使被kill -9也能保證狀態(tài)一致”的代碼——因?yàn)镽uff已經(jīng)把你訓(xùn)練成了數(shù)據(jù)庫(kù)思維者。4. PostgreSQL表結(jié)構(gòu)設(shè)計(jì)從DDL到調(diào)度語(yǔ)義的逐字段推演Octop的PostgreSQL表結(jié)構(gòu)是整套系統(tǒng)最精煉的文檔沒(méi)有一行注釋但每個(gè)字段名、類(lèi)型、約束都在講述調(diào)度邏輯。我們以核心任務(wù)表octop_tasks為例逐字段拆解其設(shè)計(jì)哲學(xué)注意實(shí)際項(xiàng)目中表名按任務(wù)域劃分如user_sync_tasks此處為教學(xué)統(tǒng)一用octop_tasks字段名類(lèi)型約束設(shè)計(jì)意圖實(shí)際案例idUUIDPRIMARY KEY DEFAULT gen_random_uuid()任務(wù)唯一標(biāo)識(shí)避免自增ID暴露調(diào)度順序或總量用戶畫(huà)像同步任務(wù)IDa1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8task_typeTEXTNOT NULL任務(wù)分類(lèi)標(biāo)識(shí)用于路由到不同執(zhí)行器user_profile_sync,report_generationscheduled_atTIMESTAMPTZNOT NULL絕對(duì)觸發(fā)時(shí)間非“間隔”或“Cron表達(dá)式”2024-06-15 00:00:0000UTC時(shí)間規(guī)避時(shí)區(qū)混亂statusTEXTNOT NULL CHECK (status IN (pending, running, success, failed, frozen))唯一狀態(tài)源禁止應(yīng)用層狀態(tài)機(jī)pending表示待調(diào)度f(wàn)rozen表示永久停止payloadJSONBNOT NULL任務(wù)參數(shù)支持任意嵌套結(jié)構(gòu){user_id: 12345, include_history: true}created_atTIMESTAMPTZNOT NULL DEFAULT NOW()任務(wù)創(chuàng)建時(shí)間用于審計(jì)自動(dòng)填充不可修改started_atTIMESTAMPTZNULL任務(wù)開(kāi)始執(zhí)行時(shí)間NULL表示未啟動(dòng)調(diào)度器UPDATE時(shí)設(shè)置completed_atTIMESTAMPTZNULL任務(wù)完成時(shí)間NULL表示未完成成功/失敗后UPDATE設(shè)置retry_countINTEGERNOT NULL DEFAULT 0 CHECK (retry_count 0)已重試次數(shù)重置邏輯在SQL中UPDATE ... SET retry_count retry_count 1max_retriesINTEGERNOT NULL DEFAULT 3 CHECK (max_retries 0)最大重試次數(shù)每個(gè)任務(wù)可定制郵件發(fā)送任務(wù)設(shè)為0不重試API調(diào)用設(shè)為3last_errorTEXTNULL最后一次錯(cuò)誤詳情長(zhǎng)度限制為1024字符截?cái)喑L(zhǎng)traceback防TEXT字段膨脹關(guān)鍵設(shè)計(jì)點(diǎn)在于狀態(tài)流轉(zhuǎn)的不可逆性與SQL可控性status字段的CHECK約束強(qiáng)制所有狀態(tài)變更必須通過(guò)UPDATE語(yǔ)句且只能是預(yù)定義值。這意味著你永遠(yuǎn)無(wú)法通過(guò)INSERT直接插入running狀態(tài)的任務(wù)——因?yàn)镮NSERT時(shí)status必須為pending。這種設(shè)計(jì)杜絕了“狀態(tài)偽造”所有狀態(tài)變更必經(jīng)調(diào)度器之手。retry_count和max_retries的組合讓重試邏輯完全脫離Python代碼。重試判斷不是if task.retry_count task.max_retries:而是SQL的WHERE retry_count max_retries。這樣即使調(diào)度器進(jìn)程崩潰DBA也能用一條UPDATE手動(dòng)重試任務(wù)無(wú)需重啟服務(wù)。scheduled_at使用TIMESTAMPTZ而非TIMESTAMP WITHOUT TIME ZONE是因?yàn)镸IT服務(wù)器全部采用UTC時(shí)區(qū)且所有客戶端必須傳入U(xiǎn)TC時(shí)間。我們?cè)蚯岸薐avaScript的new Date().toISOString()返回UTC而后端Python誤用datetime.now()生成本地時(shí)間導(dǎo)致任務(wù)提前8小時(shí)觸發(fā)——這個(gè)血淚教訓(xùn)直接固化為Ruff規(guī)則所有時(shí)間生成必須顯式調(diào)用datetime.now(timezone.utc)。更精妙的是鎖粒度與索引設(shè)計(jì)-- 核心查詢(xún)索引按觸發(fā)時(shí)間狀態(tài)排序支撐高效調(diào)度 CREATE INDEX idx_octop_tasks_scheduled_status ON octop_tasks (scheduled_at, status) WHERE status pending; -- 防止重復(fù)調(diào)度唯一索引確保同一task_type業(yè)務(wù)鍵不重復(fù) CREATE UNIQUE INDEX idx_octop_tasks_unique_key ON octop_tasks (task_type, (payload-user_id)) WHERE status pending;第一個(gè)索引讓SELECT ... WHERE scheduled_at NOW() AND status pending ORDER BY scheduled_at LIMIT 1變成索引掃描耗時(shí)從全表掃描的120ms降至0.3ms。第二個(gè)索引是業(yè)務(wù)強(qiáng)約束用戶畫(huà)像同步任務(wù)中payload-user_id必須唯一避免同一用戶被重復(fù)調(diào)度——這比在Python層做去重更可靠因?yàn)樗饕龥_突會(huì)直接報(bào)錯(cuò)而非靜默丟棄。提示表結(jié)構(gòu)設(shè)計(jì)時(shí)我們刻意避免使用SERIAL主鍵。UUID雖占用空間大但帶來(lái)兩大優(yōu)勢(shì)1任務(wù)ID可由客戶端生成如前端點(diǎn)擊“立即同步”時(shí)生成ID并INSERT調(diào)度器無(wú)需返回ID2分庫(kù)分表時(shí)UUID天然全局唯一而SERIAL需依賴(lài)SEQUENCE同步增加運(yùn)維復(fù)雜度。這是MIT thesis中“客戶端承擔(dān)更多職責(zé)服務(wù)端專(zhuān)注協(xié)調(diào)”的具體體現(xiàn)。5. 從零部署Octop三步完成PostgreSQL原生調(diào)度環(huán)境搭建部署Octop不是運(yùn)行一個(gè)命令而是在PostgreSQL中植入一套調(diào)度基因。整個(gè)過(guò)程分為三步全部通過(guò)SQL和Python完成無(wú)Docker、無(wú)Kubernetes、無(wú)額外服務(wù)。我以Ubuntu 22.04 PostgreSQL 14.10為例Windows用戶請(qǐng)將sudo -u postgres psql替換為psql -U postgresLinux/macOS用戶請(qǐng)確保已安裝postgresql-client和python3-pip。5.1 第一步初始化PostgreSQL數(shù)據(jù)庫(kù)與權(quán)限Octop要求專(zhuān)用數(shù)據(jù)庫(kù)和受限用戶這是MIT安全規(guī)范的核心。不要用postgres超級(jí)用戶運(yùn)行調(diào)度器# 創(chuàng)建專(zhuān)用數(shù)據(jù)庫(kù) sudo -u postgres createdb octop_scheduler # 創(chuàng)建專(zhuān)用用戶密碼強(qiáng)度至少12位含大小寫(xiě)字母數(shù)字符號(hào) sudo -u postgres psql -c CREATE USER octop_app WITH PASSWORD Oct0p!2024SecurePass; # 授予數(shù)據(jù)庫(kù)連接權(quán)限 sudo -u postgres psql -c GRANT CONNECT ON DATABASE octop_scheduler TO octop_app; # 切換到新數(shù)據(jù)庫(kù)授表創(chuàng)建權(quán)限僅限初始遷移 sudo -u postgres psql -d octop_scheduler -c GRANT USAGE ON SCHEMA public TO octop_app; sudo -u postgres psql -d octop_scheduler -c GRANT CREATE ON SCHEMA public TO octop_app;關(guān)鍵細(xì)節(jié)octop_app用戶沒(méi)有CREATEDB或SUPERUSER權(quán)限且僅對(duì)octop_scheduler庫(kù)有連接權(quán)。調(diào)度器運(yùn)行后我們會(huì)回收CREATE權(quán)限只保留SELECT/INSERT/UPDATE——這是MIT thesis中“最小權(quán)限原則”的落地。實(shí)測(cè)發(fā)現(xiàn)權(quán)限過(guò)寬會(huì)導(dǎo)致Ruff檢查時(shí)意外獲得pg_stat_activity訪問(wèn)權(quán)從而繞過(guò)狀態(tài)審計(jì)。5.2 第二步執(zhí)行SQL遷移腳本創(chuàng)建表結(jié)構(gòu)將以下SQL保存為octop_schema.sql然后執(zhí)行-- 設(shè)置搜索路徑 SET search_path public; -- 創(chuàng)建任務(wù)表 CREATE TABLE octop_tasks ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), task_type TEXT NOT NULL, scheduled_at TIMESTAMPTZ NOT NULL, status TEXT NOT NULL CHECK (status IN (pending, running, success, failed, frozen)), payload JSONB NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), started_at TIMESTAMPTZ NULL, completed_at TIMESTAMPTZ NULL, retry_count INTEGER NOT NULL DEFAULT 0 CHECK (retry_count 0), max_retries INTEGER NOT NULL DEFAULT 3 CHECK (max_retries 0), last_error TEXT NULL CHECK (length(last_error) 1024) ); -- 創(chuàng)建配置表 CREATE TABLE octop_config ( key TEXT PRIMARY KEY, value JSONB NOT NULL, updated_at TIMESTAMPTZ DEFAULT NOW() ); -- 插入默認(rèn)配置 INSERT INTO octop_config (key, value) VALUES (scheduler.interval_seconds, {value: 5}), (task.default_timeout_seconds, {value: 300}), (db.connection_pool_size, {value: 10}); -- 創(chuàng)建索引 CREATE INDEX idx_octop_tasks_scheduled_status ON octop_tasks (scheduled_at, status) WHERE status pending; CREATE INDEX idx_octop_tasks_type_payload ON octop_tasks (task_type, (payload-user_id)) WHERE status pending; -- 回收創(chuàng)建權(quán)限重要 REVOKE CREATE ON SCHEMA public FROM octop_app; GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA public TO octop_app; GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO octop_app;執(zhí)行命令sudo -u postgres psql -d octop_scheduler -f octop_schema.sql此時(shí)檢查表結(jié)構(gòu)是否生效sudo -u postgres psql -d octop_scheduler -c \dt # 應(yīng)顯示 octop_tasks 和 octop_config 兩張表 sudo -u postgres psql -d octop_scheduler -c \d octop_tasks # 應(yīng)顯示所有字段及索引5.3 第三步安裝Python依賴(lài)并運(yùn)行調(diào)度器創(chuàng)建虛擬環(huán)境安裝核心依賴(lài)注意不安裝Celery/Airflow等任何調(diào)度框架python3 -m venv octop_env source octop_env/bin/activate # Windows用 octop_env\Scripts\activate pip install --upgrade pip pip install psycopg2-binary2.9.7 # 嚴(yán)格指定版本避免pg8000兼容問(wèn)題 pip install ruff0.4.4 # MIT thesis指定版本新版本規(guī)則有差異創(chuàng)建調(diào)度器主文件octop_scheduler.pyimport os import time import json import logging from typing import Dict, Any from psycopg2 import connect, sql from psycopg2.extras import RealDictCursor # 配置日志 logging.basicConfig(levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s) logger logging.getLogger(__name__) def get_db_connection(): return connect( hostos.getenv(DB_HOST, localhost), portos.getenv(DB_PORT, 5432), databaseos.getenv(DB_NAME, octop_scheduler), useros.getenv(DB_USER, octop_app), passwordos.getenv(DB_PASSWORD, Oct0p!2024SecurePass) ) def load_config(conn, key: str) - Any: with conn.cursor() as cur: cur.execute(SELECT value FROM octop_config WHERE key %s, (key,)) result cur.fetchone() return result[0][value] if result else None def schedule_loop(): interval load_config(get_db_connection(), scheduler.interval_seconds) or 5 logger.info(fStarting Octop scheduler with interval {interval}s) while True: conn get_db_connection() try: with conn.cursor(cursor_factoryRealDictCursor) as cur: # 獲取下一個(gè)待執(zhí)行任務(wù)帶SKIP LOCKED防并發(fā)搶奪 cur.execute( SELECT * FROM octop_tasks WHERE scheduled_at NOW() AND status pending ORDER BY scheduled_at LIMIT 1 FOR UPDATE SKIP LOCKED ) task cur.fetchone() if task: logger.info(fProcessing task {task[id]} of type {task[task_type]}) # 更新?tīng)顟B(tài)為running cur.execute( UPDATE octop_tasks SET status running, started_at NOW() WHERE id %s, (task[id],) ) conn.commit() # 提交狀態(tài)變更 # 執(zhí)行任務(wù)此處應(yīng)調(diào)用具體業(yè)務(wù)函數(shù) try: # 模擬業(yè)務(wù)邏輯 time.sleep(1) # 替換為真實(shí)業(yè)務(wù)代碼 # 標(biāo)記成功 cur.execute( UPDATE octop_tasks SET status success, completed_at NOW() WHERE id %s, (task[id],) ) except Exception as e: # 標(biāo)記失敗并重試 cur.execute( UPDATE octop_tasks SET status failed, last_error %s, retry_count retry_count 1 WHERE id %s AND retry_count max_retries, (str(e), task[id]) ) # 若重試已達(dá)上限標(biāo)記為frozen cur.execute( UPDATE octop_tasks SET status frozen WHERE id %s AND retry_count max_retries, (task[id],) ) conn.commit() else: time.sleep(interval) except Exception as e: logger.error(fScheduler error: {e}) time.sleep(interval) finally: conn.close() if __name__ __main__: schedule_loop()設(shè)置環(huán)境變量并啟動(dòng)export DB_HOSTlocalhost export DB_PORT5432 export DB_NAMEoctop_scheduler export DB_USERoctop_app export DB_PASSWORDOct0p!2024SecurePass python octop_scheduler.py此時(shí)調(diào)度器開(kāi)始每5秒掃描一次日志會(huì)輸出2024-06-15 10:00:00,000 - INFO - Starting Octop scheduler with interval 5s 2024-06-15 10:00:05,000 - INFO - Processing task a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8 of type user_profile_sync實(shí)操心得首次運(yùn)行時(shí)務(wù)必手動(dòng)插入一條測(cè)試任務(wù)驗(yàn)證流程INSERT INTO octop_tasks (task_type, scheduled_at, payload, max_retries) VALUES (test, NOW(), {message: Hello from Octop}, 1);如果調(diào)度器日志顯示Processing task...且數(shù)據(jù)庫(kù)中該任務(wù)status變?yōu)閟uccess說(shuō)明環(huán)境完全就緒。我踩過(guò)的最大坑是PostgreSQL默認(rèn)max_connections100而調(diào)度器每輪創(chuàng)建新連接若未及時(shí)close()10輪后連接池耗盡——因此代碼中conn.close()放在finally塊是生死線。6. 任務(wù)注冊(cè)與執(zhí)行用SQL和Python協(xié)同構(gòu)建可靠工作流Octop的“任務(wù)注冊(cè)”不是調(diào)用API而是向PostgreSQL插入一行數(shù)據(jù)“任務(wù)執(zhí)行”不是啟動(dòng)進(jìn)程而是調(diào)度器從數(shù)據(jù)庫(kù)撈出這行并調(diào)用對(duì)應(yīng)Python函數(shù)。這種SQL-Python協(xié)同模式把工作流的定義權(quán)完全交給數(shù)據(jù)庫(kù)管理員DBA和開(kāi)發(fā)者共同掌控。下面以“用戶登錄統(tǒng)計(jì)日?qǐng)?bào)”任務(wù)為例完整演示從注冊(cè)到執(zhí)行的閉環(huán)。6.1 任務(wù)注冊(cè)用SQL定義調(diào)度契約首先為日?qǐng)?bào)任務(wù)創(chuàng)建專(zhuān)用表遵循Octop慣例按領(lǐng)域建表-- 創(chuàng)建日?qǐng)?bào)任務(wù)表 CREATE TABLE login_report_tasks ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), report_date DATE NOT NULL, status TEXT NOT NULL CHECK (status IN (pending, running, success, failed, frozen)), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), started_at TIMESTAMPTZ NULL, completed_at TIMESTAMPTZ NULL, last_error TEXT NULL CHECK (length(last_error) 1024) ); -- 創(chuàng)建索引 CREATE INDEX idx_login_report_tasks_date_status ON login_report_tasks (report_date, status) WHERE status pending;然后注冊(cè)明日的日?qǐng)?bào)任務(wù)注意scheduled_at必須是UTC時(shí)間且早于實(shí)際執(zhí)行時(shí)間-- 注冊(cè)2024-06-16的日?qǐng)?bào)任務(wù)設(shè)定UTC時(shí)間01:00觸發(fā)北京時(shí)間09:00 INSERT INTO login_report_tasks (report_date, status, created_at) VALUES (2024-06-16, pending, NOW()); -- 同時(shí)在octop_tasks主表中插入調(diào)度元數(shù)據(jù)關(guān)鍵 INSERT INTO octop_tasks ( task_type, scheduled_at, payload, max_retries ) VALUES ( login_report_daily, 2024-06-16 01:00:0000, -- UTC時(shí)間 {report_date: 2024-06-16}, 2 );提示octop_tasks表是調(diào)度器的“中央任務(wù)池”所有任務(wù)類(lèi)型無(wú)論業(yè)務(wù)表名都必須在此注冊(cè)。task_type字段用于路由payload中的report_date是業(yè)務(wù)參數(shù)兩者分離保證了調(diào)度邏輯與業(yè)務(wù)邏輯解耦。6.2 任務(wù)執(zhí)行器Python函數(shù)與SQL狀態(tài)的精準(zhǔn)咬合在octop_scheduler.py中擴(kuò)展任務(wù)執(zhí)行邏輯# 在文件頂部添加業(yè)務(wù)函數(shù) def generate_login_report(report_date: str) - None: Generate daily login report for given date. # 此處連接業(yè)務(wù)數(shù)據(jù)庫(kù)執(zhí)行統(tǒng)計(jì)SQL # 示例SELECT COUNT(*) FROM user_logins WHERE login_time::date %s pass # 在schedule_loop()的try塊中替換模擬業(yè)務(wù)邏輯部分 if task: logger.info(fProcessing task {task[id]} of type {task[task_type]}) cur.execute( UPDATE octop_tasks SET status running, started_at NOW() WHERE id %s, (task[id],) ) conn.commit() try: # 解析payload并執(zhí)行對(duì)應(yīng)業(yè)務(wù)函數(shù) payload task[payload] if task[task_type] login_report_daily: report_date payload.get(report_date) if not report_date: raise ValueError(Missing report_date in payload) generate_login_report(report_date) # 標(biāo)記成功 cur.execute( UPDATE octop_tasks SET status success, completed_at NOW() WHERE id %s, (task[id],) ) else: raise NotImplementedError(fUnknown task_type: {task[task_type]}) except Exception as e: # 處理失敗更新?tīng)顟B(tài)并記錄錯(cuò)誤 error_msg str(e)[:1024] # 截?cái)喾酪绯?cur.execute( UPDATE octop_tasks SET status failed, last_error %s, retry_count retry_count 1 WHERE id %s AND retry_count max_retries, (error_msg, task[id]) ) # 檢查是否需凍結(jié) cur.execute( UPDATE octop_tasks SET status frozen WHERE id %s AND retry_count max_retries, (task[id],) ) conn.commit()關(guān)鍵點(diǎn)在于狀態(tài)更新與業(yè)務(wù)執(zhí)行的嚴(yán)格順序UPDATE ... SET status running必須在業(yè)務(wù)執(zhí)行前完成且在獨(dú)立事務(wù)中提交——這確保即使業(yè)務(wù)函數(shù)崩潰數(shù)據(jù)庫(kù)中狀態(tài)已是running避免任務(wù)被重復(fù)調(diào)度。generate_login_report()執(zhí)行完畢后才UPDATE ... SET status success。若此步失敗如網(wǎng)絡(luò)問(wèn)題任務(wù)狀態(tài)卡在running調(diào)度器下次掃描會(huì)發(fā)現(xiàn)status running但completed_at IS NULL從而觸發(fā)超時(shí)檢測(cè)需在后續(xù)擴(kuò)展中加入。錯(cuò)誤處理中l(wèi)ast_error被截?cái)嘀?024字符這是對(duì)TEXT字段的物理約束防止單條錯(cuò)誤日志撐爆表空間。6.3 監(jiān)控與審計(jì)用原生SQL實(shí)現(xiàn)全鏈路可觀測(cè)性O(shè)ctop不提供Prometheus指標(biāo)或Grafana面板但PostgreSQL自帶的pg_stat_statements和自定義視圖足以構(gòu)建企業(yè)級(jí)監(jiān)控-- 創(chuàng)建任務(wù)狀態(tài)視圖實(shí)時(shí)反映調(diào)度健康度 CREATE OR REPLACE VIEW octop_task_summary AS SELECT status, COUNT(*) as count, MIN(scheduled_at) as earliest_scheduled, MAX(scheduled_at) as latest_scheduled, AVG(EXTRACT(EPOCH FROM (NOW() - scheduled_at))) as avg_delay_seconds FROM octop_tasks GROUP BY status; -- 查詢(xún)當(dāng)前狀態(tài) SELECT * FROM octop_task_summary; -- 輸出示例 -- status | count | earliest_scheduled | latest_scheduled | avg_delay_seconds -- --------------------------------------------------------------------------------------------- -- pending | 12 | 2024-06-15 01:00:0000 | 2024-06-20 01:00:0000 | 1245.32 -- success | 142 | 2024-06-14 01:00:0000 | 2024-06-15 01:00:0000 | 120.05 -- failed | 3 | 2024-06-14 01:00:0000 | 2024-06-14 01:00:0000 | 2340.11 -- 創(chuàng)建失敗任務(wù)詳情查詢(xún)供DBA快速定位 CREATE OR REPLACE VIEW octop_failed_tasks AS SELECT id, task_type, scheduled_at, created_at, last_error, EXTRACT(EPOCH FROM (NOW() - created_at)) as age_seconds FROM octop_tasks WHERE status IN (failed, frozen) ORDER BY created_at DESC LIMIT 10;DBA只需運(yùn)行SELECT * FROM octop_task_summary;就能立刻掌握系統(tǒng)負(fù)載運(yùn)行SELECT * FROM octop_failed_tasks;就能看到最近10個(gè)失敗任務(wù)的完整上下文。這種監(jiān)控方式的優(yōu)勢(shì)在于所有查詢(xún)結(jié)果可被審計(jì)日志記錄且無(wú)需額外部署監(jiān)控組件——符合MIT對(duì)“基礎(chǔ)設(shè)施透明性”的要求。我在實(shí)際項(xiàng)目中還增加了pg_cron自動(dòng)清理歷史任務(wù)--
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
国产AV高清AV无码| 91久久婷婷| 无码一区二区三区四区五区六区七区八区九区十区视频 | 97日视频| 日本色婷婷| 亚洲国产精品成人久久蜜臀| 青青草久草AV| 自拍盗摄一区| 日本高清久久| 亚洲 欧美日韩 另类| 久久97超碰| 亚欧美色图| 夜夜爽妓女| 九热视频| aⅴ日韩成人电影av在线免费看av大全 | 国产天天看| 久久成人网站| 97超碰热线| 中文字幕二区日韩天堂| 91色综合激情| 精品美女少妇一区二区三区| 九热大香蕉| 九九热在线精品视频| 久久久久亚洲AV无码专区少妇| 婷婷综合伊人一区| 亚洲男人综合| 亚洲伊人久久综合97| 91九色丨风韵犹存| 九月伊人中文字幕| 欧美牲| 久久婷婷苹果| 97久久久久久久久久| 欧美熟妇亚洲版| www.操| 日本曲间由美性生活片| 伊人综合色网| 久久精品72| 国产四虎在线| 97超级欧美| 亚洲人妖网| 亚洲淫乱骚妇AV| 夜夜高潮夜夜爽高清视频一| 日韩 欧美 校园一区| 亚欧美天堂在线| 91黑丝少妇| 凹凸视频在线一区二区| 日本性感人妻91| 黑人免费福利视频| 性做久久久久久久| 婷婷综合久久| 国产精品91一样| 欧美午夜精品久久久久久超碰| 99视频自拍| 成人AV在线电影| 男人天堂2012| 欧美白嫩女HD| 职场同事知名国产国产精品久久欧美日韩 | 欧美躁死她一区二区| 天堂种子在线www网资源| 精品国产精品一区二区| 日韩三级久久久| 综合国产97| 欧美韩国你懂得在线| 加勒比少妇AV婷婷六月天超碰超碰| 欧美天堂亚洲电影院一区在线播放| 欧美夜色| 欧美性夜| 91久久精品中文字幕| 无码视频黄色网战| 中文字幕丝袜美腿| 国产91专区| 欧美性夜| 久久久无码av精| 国产原创自拍| 欧美激情色婷婷花野真衣一区二区| 中文字幕无码不卡啪啪| 亚洲牲交| 亚洲操人| 加勒比少妇AV婷婷六月天超碰超碰| 久久大香蕉97| 2019久久久久久久久福利| 天天色播亚洲综合网站| 久久伦理视频久久大香蕉视频| 超碰97.com| 国产成人拍国产亚洲精品| 久久久久国产精品喷潮免费观看臀| 99色视频| 人妻超碰青青草98| 免费少妇一区二区| 久久精品视-一级做a爰片性色毛片16美国-中国女与老外在线精品 | 熟女少妇视频| 精品一区二区综合熟妇| 国产精品国产自产拍高清AV| 色天天野狼综合社区| 91综合色噜噜| 大香交伊人网| 香蕉精品二区二区| 黄色欧美性爱视频| 色欧洲97| 午夜久久无码1000合集| www.高清无码诱惑一区.com | 蜜桃天美传媒AV一区二区三区| 人妻精品视频一区二区三区| 天天干美少妇一区| 78精品在线| 青椒国产97在线熟女| 97久久视频| 日韩中文字幕宗合在线| 脫衣舞一区二区三区| 神马视频久久久久久| 91热| 婷婷综合五月| 欧美日韩久久精品爱爱| 色五月网址| 国产热av| 大香蕉黄色一区| 激情五月天校园春色网| 夜夜影视四色| 997色在线| 手机在线观看不卡无码av| 亚洲诱惑| hd成人一区二区在线| 中文字幕人妻色偷偷久久皮| 日韩欧美午夜视频在线| 一本久久久精品| 五月天丁香网| 亚洲日韩天堂| 国产又大又粗又长视频在线| 亚乱色| julia ann久久| 99热只有这里有精品| 精品少妇人妻| 中文字幕日本久久| 亚洲高清欧美总合| 亚洲图片 91| 日韩啪啪视频| 亚洲免费日韩在线一区二区| 亚洲Av无码成人精品国产| 精国久久一区二区三区98| 中文字幕精品一区欧美| 精品女同一区| 怡红院怡春院| 国产人伦a片信息免费片| 黄色不卡视频| 国产色精品午夜大片| 高潮9999外国| 嗯嗯啊啊亚欧精品| 久操不卡视频| 17c嫩草51久久91嫩草| 偷拍欧美激情| 免费亚洲黄色视频在线观看| 亚洲丝袜二区在线| 亚洲老司机123专区| 无码自拍SM| 东京热男人天堂| 欧美九九99久久精品| 日本日逼高清| 另类图片欧美激情综合| 精品无码一区二区三区| 热久久精品| 成全在线观看免费观看| 国内外激情在线| 久久久不能久久久久| 中文字幕一区二区免费在线| 五十路熟女,国产欧美精品区一区二区三区| 久久久久久AV无码免费网站| 日韩精品一区二区高清| 97人人爱人人乐| 屌妞视频久久久久久久| 91九九九馒头| 99热伊人| jizzjizz欧美| 激情五月综合开心五月| 国产91 丝袜在线播放00-百度| 99精品网站| 人妻av在线| 亚洲国产91精品一区二区久久| 久久噜噜噜精品国产亚洲综合| 玖玖97综合| 老司机老司机午夜影院| 乱伦av麻豆| 亚洲啪啪综合?v一区综合精品区| 亚洲性刺激| 国精品一区二区三| 天天色粽合合合合合合合| 东京热男人的天堂精品| 美国精品国产精品| 一级做受视频免费是看美女| 婷婷五月天激情四射| 欧美色图片欧美色图| 一区 欧美 日韩 麻豆| 麻豆国产尤物AV| 國產尤物AV尤物在線觀看| 日韩中文字幕视频| 亚洲精品97| 亚洲91射| 色呦色呦色精品| 日本99一区二区| 91天天日| 台湾佬激情综合| 国产成人精品日本亚洲语言| 黄色视频特级毛片| 另类小色呦| 国内精品a| 亚洲综合999| 偷拍盗拍亚洲色图图片| 欧美性夜| 亚洲av噜噜噜噜噜噜| 亚洲天堂一区| 自拍偷拍草一草| 日韩肏逼视频| 最新av中文字幕高清| 日韩有码 一区二区三区| 久久久精品九| 亚洲资源一区| 天天影视亚洲| 午夜操一操| 屁股久久久久久| 亚州男人天堂| 免费AV中文网在线观看| 国产无码三级视频在线观看| 欧美熟妇成人一区二区| 狠狠色狠狠色狠狠五月| 一级久久性爱视频| 激情五月天婷婷| 亚洲精品男人的天堂| 俺去也婷婷| 91 刺激在线| 亚洲少妇色| 成人精品电影| 久久99草| 国产成人五月天丁香花| 日本精品五区| 久久亚洲欧美中文字幕国语| 亚洲AV成人无码一区二区三区在线观看 | 欧美成人精品一区二区男人蜜臀| 九九九九热只有精品| 另类小说欧美激情校园春色| 综合久久少妇中文字幕| 精品久久久高清无码| 久久av成人无码免费| 午夜免费福利视频一区| 青青草五月天| 不卡六六在线91| 亚洲色图A| 操逼视频国产无套| 伊人色综合网电影 | 欧美91精品国产自产| 韩日色费| 国产成人+综合亚洲+天堂| 久久免费中文字幕在线观看| 亚洲十八禁止| 婷婷丁香激情| 两性综合网| 老熟女91av| 青青草久草AV| 精品成人无码| 久久日韩毛| 超碰在97| 国产福利电影| 婷婷五月在线视频| 粉嫩久久久极品| 97久久超碰| 伊人黄色视频免费观看| 久久精品国产精品| 免费AV中文网在线观看| 亚洲精品美女久久久久久久久| 人妻精品综合中文字幕在线 | 国产精品区在线12p| 九九色精品| 青青青青草av在线观看| 激情熟女12P| 97色在线| 日韩欧美麻豆| 午夜寂寞欧美| 精品乱码在线观看| 国产h片在线观看视频| 日韩草久视频| 校园春色五月天| 最新日韩黄片| 国产丸一视频| 久久久久人妻二区精品叶可怜| 另类视频在线| 91精品国产91久久久久久久久久久久| 亚洲av无线观看| 美女大乳久久久久久久女人18| 久久岛国| 国内外色色色色色成人视频| 97中文热色| 怡红院一区二区熟女人妻| 黑人与人妻| 三级精品三级在线观看| 日韩午夜国产| 国产成年免费大片黄在线观看| 和协无码影院| 人人摸.人人色| 神马久久久久久久久久久久| 国产真乱mangent| 九九热AV| 色哟哟511老熟女| 九九热re99re6在线精品| 国产日韩区| 免费网色网站| 天堂8在线新版官网| 欧美日韩国产人人| 亚洲av无线观看| 加勒比av网| 久久艹逼视频| 欧美高清第一页| 午夜精品久久久久久久男人的天堂| 青青草原香蕉日本Ap| 强奸a片网| 神马麻豆福利院| 欧美日不卡| 久久丁香久草综合网| 亚洲综合影视| www国产天美久久久| 性高潮久久久久久久久久久| 96AV精品| 99热99在线播放激情| 久男人久久| 91狠狠综合久久久| 综合激情二| 欧美91精彩| 91粉嫩萝控精品福利网站_精品影音先锋国| 俺也射| 97精品综合久久| 亚洲欧美电影| 久久九精品| 色情综合| 亚洲国产ⅴ高清在线观看| 神马九九九| 男人的天堂啪啪| www久久国产精品| 91在线/欧洲| 99操逼| 波多野结衣之双飞调教在线播放 | 精品人妻一区二区三区夜夜| 亚洲啪啪性视频| 乱抡国产91| 久久精品无码熟妇一区二区三区视频导航| 伊人97色天使| 亚洲AV无码久久久国产精品 | 久久成年精品| 天天插天天插| 人人干人人操人人..com| 亚洲人久久久久日| 欧亚揄拍偷拍精品视频| 久久免费看高潮毛片韩国| 国产乱码精品一区二区三区四川| 日韩无码一级黄色av片| 风间由美日韩欧美久久| 精品一二三区四视频| 色99视频| 911粉嫩人妻| 不卡av在线中文字幕| 变态综合色| 欧美青青视频| 超AV色女| 91久久久久免| 狠狠干婷婷| 无色无码| 国产AV精久久| 尤物一级在线免费观看| 天天草夜夜草高潮片| 精品视频一区二区| 2017大香蕉| 午夜欧美精品久久久| 乱操9999| 97ai亚洲| 欧美美女视频| 国产白丝AV| 超碰9 7女人| 一二三四视频在线社区中文字幕| 久久偷拍人| 欧美爆操91| 天天综合~91入口| 日本99热| 色婷婷综合久久久久中文国产精品一区中文字幕,国产福利电影一区二区三区 | 欧美日韩天堂| 欧洲小说色图视频另类| 97 国产一区| 久久熟妇五十路一区| 校园春色制服丝袜中文字亚洲| www色日本| 亚洲黄色网址视频| 色9999日韩国产| 2024人人操人人摸| 婷婷导航| 伊色综合天堂色97| 国产九九久久久精品| 骚乳在线| 91日产欧美| 中文字幕乱偷人妻久久艾草网| 亚洲色图伊人网| 老女人91| 精品传媒在线一区| 国产无码三级视频在线观看| 国产精品日韩在线一区| 午夜福利av电影在线| 亚洲系列第一页| JIZZJIZZ国产精品喷水| 东京热激情视频一二三区| 国产欧美一区二区| 色综合超碰超| 超碰在线免费一区二区三区| 激情五月天婷婷| 综合色久| 二区熟妇韩日| 亚洲国产福利视频| 探花精品 一区二区| 成人26uuu| 久久直播国产| 97色色视频| 日日夜夜国产综合| 青青久久久| 国产馆| 青娱乐老司机视频| 5278欧美一区二区三区| 99久久久无码| 91久久久久| 日本一区二区中文字幕久久| 强奸乱伦资源| 亚洲男人的天堂V| 加勒比伊人综合| 97亚洲中文| 久操凹凸视频| 日韩乱码Av| 97免费视频在线观看视频| 日日摸日日碰夜夜爽视频| 亚洲性爱成人| 丁香激情网| 蜜桃久久精品一区二区三区| 少妇淫妇久久久久久久| 亚洲九月丁香| 天天干天天日天天射黄色片| 97超级久久| 亚洲一区二区三区中文字幕| 欧美美女自慰一区二区三区| 亚洲美腿丝袜香蕉影视欧美成人| {男男暴菊gay无套网站| AV中文在线| 亚洲素人网| 88xx成人精品视频| 青青草视频这里只有精品| 一区二三区四区视频大全套| 老司机深夜18禁污污网站| 婷婷五月花| 欧美日韩97在线| 欧美特大AA级黄片| 好湿好紧好爽 视频| 美女91网| 国内精品久久久久影院亚洲| 无套后入双马尾| 男人的天堂kva| 亚洲囯产精品女人久久久| 久久草草欧美精品| 日韩BBN| 园内精品自拍视频在线播放| 91美乳| 狠狠操使劲操| 97久精品| 在线日韩精品一区二区三区| 四虎影库国产精品免费| 久久久亚洲| 黑操B| 久久久精精精| 黑丝少妇| 亚洲欧美不卡线| 伊人综合色网| 人人人摸人人| 中文字幕人妻色偷偷久久皮| 免费看黄视频亚洲网站| 日日噜噜夜夜久久亚洲一区二区 | 国产精品久久天天干| 亚洲国产综合久久久性感熟妇| 男人天堂东京热| 玖色AV| 天天看天天日| 成人综合视频久久| 最新三级网址| 久久久九| 久久久精品国产亚洲伊人| 97在线视频网站| 韩国一区二区精品亚洲| 大香蕉视频一二三区| 二级久久网| 国产欧美一级在线观看| 玖玖大干人妻| 日韩一级二级| 亚洲国产91精品一区二区久久| 丝袜美腿校园春色| 91精品大奶人妻| 资源新线在线天堂| 亚洲天堂自拍| 人人干人人操人人..com| 中国91AV| 97欧美色资源| 99久久婷婷国产综合| 一起草高清无码| 97这里只精品| 亚洲成人av色网| 你懂的在线观看区国产| 国产AV线| 男人的天堂2018.| 乱伦AVxx| 91人妻少妇| 91少妇香蕉久久精品| 五月丁香婷婷色| 91在线精品一区二区三区| 舔舔啊| 国产精品久久久视频| 中文字幕亚洲热播人妻| 色吧91| 91熟女.com| 在现视频女上位好爽| 国产白嫩漂亮KTV在线| 日韩15p| 欧美九一精品久久久熟妇| 久久久久骚| 91在线无码精品秘 软件| a级免费在线观看| 台湾佬中文娱乐网久久久久久久久久com | 免费观看网黄| 亚洲图片欧美偷拍| 金典av| 美女露胸露屁股| 91精品国产高清久久久久久,亚洲成人| 亚洲天天操| 少妇丝袜在线观看AV| 欧美在线官网| 爱射综合| 91精品国产高清久久久久久,亚洲成人 | 伊人9| 啊啊啊不要啊啊受不了了视频在线| 人妻熟女午夜精品在线| 日韩在线观看中文字幕视频| 精品成人亚洲午夜电影| 中国AAAAAA黄色片| 2017天天插| 蜜臀一二三区| 亚洲伊人久久精品影院| 欧美日韩另类字幕中文| 国产九区| 嗯嗯啊好大| 色爱欲亚洲| 丰满翘臀美女影院视频| 女人爽到高潮久久久| 欧美色综合影院| 婷婷中文网| 国产操偷| 日本在线不卡v二区| 先锋色眉乱伦资源| 啪啪AV导航| 约操熟妇| 亚洲性爱无码乱伦av| 亚洲1区2区三区高清中文字幕| 蜜乳av一区二区| 福利操逼| 久久久久久国产无码精品| 国产黄片精品在线| 搡老女人老妇女AAA一VU麻豆 | 久久久不能久久久久| baisiav| 婷婷三区| 神马久久中文字幕| 97公开久久| 99国内熟女露脸视频| 大香蕉伊然在亚洲91| 亚洲人成网www| 亚洲中文字幕在线视频一区二区| 啊啊啊无码| 91精片| 欧美天天综合网| 91色色网站| 免费av在线播放二区| 欧美精品一区二区少妇免费A片| 国产乱色国产精品免费视| 在线色导航| 国产懂色精品国产av| 日韩另类| 超碰 另类 欧美 | 国内亚洲高清无码| 亚州免费啪啪视频| 亚洲人妻日日日| 最新9久久久9免费视频| 精品人妻15区| 欧美一区二区男人天堂| 亚洲av综合色区图片亚洲| 性爱乱伦网址| 五月婷婷色色| 天天综合精品| 91色黑人少妇| 不卡六六在线91| 欧洲精品一级二级精品综合视频综合 | 亚洲欧美色图小说| 婷婷影院入口| 国产精品91一样| 亚州熟妇精品| 天天综合中文字幕 91| 欧美一区二区一级岛国大片| 在线观看综合精品亚洲| 国产天天骚| 久久人体一区二区| 国产高清自拍视频| 欧美性爱精品七区| ..日韩av毛片精品久久久| 黄片在线免费在线观看| 久久久久久久78| 久久久久久中文| 97超碰人人操人人操| 国产强奸超碰AV| 日韩内射视频| 男生通女生屁股| 伊人久久综合影院| 亚洲色图在线视频| 亚洲双插| 精品偷拍13p欧美dodk视频| 精品久久青青草| 乱操9999| 不卡一区二区日本视频| 91色s| 老熟妇一区二区三区| 97久久久| 大香蕉九九| 久久人妻无码毛片A片麻豆| 香蕉欧美| 高清无码网址| 天堂av最新电影网| 黄色网址在线免费观看| 在线黄色污污网站| 欧美日韩婷婷中文| 曰韩人妻中文字幕在线| 日本日逼视频网| 成人精品视频| 亚洲性爱免费电影| 午夜欧美神马久久久久| 深夜福利黄片| 91在线欧色| 欧美+日产+中文| 婷婷久久大香蕉| 懂色av中文字幕| 免费簧片在线观看| 久草男人天堂| 99老司机精品视频在线观看| 成人色女网| 襙一襙| 78p欧美| 97精品一区二区视频| 国产极品999| 蜜臀无码视频在线观看| 精品人妻二区三区| 强奸抽插av| 好看的91视频| 精品九九国产无码| 91精品久久久久久77777| 超碰在线香蕉| 九九热午夜欧亚国产视频| 91人妻中文| 久久久久幕乱码| 丁香五月自拍| 天天做天天爱| 成人精品视频一区二区| 国产一区二区三区久久久精品| 黄色不卡视频| 久操网视频| 风月影院男女十八禁| 天天综合网91入口| 天天射天天| 黄资源| 亚洲国产精品无码AV在线| 麻豆精品三区视频| 亚洲精品白丝| 欧美一级做a爰片免费视频| 嗯嗯不要 视频| 精品妇女一区二区三区| 久久久精品91八戒| 亚洲自拍青操视频| 色97| 草草网站影院白丝内射| 免费视频观看60秒| 91精品人妻一区二区三区蜜桃臀| 脫衣舞一区二区三区| 9久久久久久| 亚洲国产一级中文综合久久天堂在线免费观看| 26uuu偷拍亚洲欧洲综合| 国产熟女自拍| 岛国小电影| 久久无码电影| 欧美黄色手机在线观看| 青久久| 人妻精品综合中文字幕在线| 欧美亚洲尤物久久| 欧亚日韩中文在线| 日韩中文字幕宗合在线| 综合影院亚洲| 精品一区二区人妖| 色欲天天婬色婬香WWW夜色| 九九免费影片| 色91综合网| www九九热| 日本免费人成视频播放120秒| 精品人妻一区二区三区四区| 一区二区蜜臀| 黄色污污污污污污网站| 强奸乱伦av电影| 国产在线视频午夜精华在| 91男人综合| 中文字幕-区二区三区四区视频中国 | 全免费a敌肛交毛片免费| 久久色网| 国产sv美女内射| 久久视频,这里只有精品| 久久9精品视频| 丁香五月激情综合| 夜色AV无码手机在线影院| 欧美一级黄色免费专区| 欧美高清色| 欧美日综合| 骚人妻少妇视频| 久久久四区| 97超级色碰碰| 欧美亚洲厕所精品偷拍91 | 美女十八禁| 校园春色综合香蕉| 求求你操操我| 综合 青草 伊久久 影院 综合| 啊啊啊啊一区| 日韩在线观看中文字幕视频| 亚洲 国产 精品一区| 国产 日韩 欧美高清| 国产一区二区免费福利片| 激情小说亚洲| 亚洲色天| 色牛aV| 午夜性刺激视频免费观看| 91人人| 97免费在线| 首页亚洲国产高跟丝袜诱惑视频 | 99热啪啪| 色婷婷影视| 狠狠色婷婷777| 免费黄色片子| 五月丁香成人网| 国产99热| 日本一区三级韩国| 欧洲综合视频| 吉川爱美98堂在线| 久久鲁夜| 亚洲精品蜜桃久久久久久久| 天天摸天天舔天天操| 蜜桃视频啊啊啊啊| 亚洲精品97久久中文字幕| 欧美97免费| 酒色综合网| 国产精品精品系列在线观看| 操操操五月天婷婷丁香影院| 99老司机精品视频在线观看| 亚洲精品一二区| 亚洲古典另类欧美在线| 中字乱伦AV| 中文伊人大香蕉视频| 亚洲av热热色| 97超碰免费生活| 黑人性欧美| 日韩免费a级毛片无码a∨| 亚洲婷婷丁香在线| 天天躁日日躁成人字幕aⅴ| 国产毛片久久久久久久| aⅴ日韩成人电影av在线免费看av大全 | A男人的天堂| #NAME?| 九九九九九用不成了| 精品国产国产AV| 欧美韩国你懂得在线| 97精品视频在线播放| 亚洲欧美色图片| 久久亚洲欧美中文字幕国语| 多毛小伙内射老太婆| 欧美国产日韩高清在线| 97综合在线观看| 国偷自 一区二区| 日韩欧美加勒比| 人干人人人操人人摸| 一区二区激情国产熟女| 屌妞视频久久久久久久久久久久| 国产又长又大又粗的视频| 蜜臀久久99精品久久久| 男人高清无码一区二区| 成人熟女视频一区二区三区| 国产精品粉嫩福利在线| 国产一级高跟丝袜| 天天摸,夜夜摸| 亚欧操逼片在线观看 | 狠狠婷婷亚洲中文综合久久| 日韩不卡毛片Av免费高清| 欧美九九99久久精品| 精品国产乱码久久久久久蜜臀| 国产人伦a片信息免费片| 超碰午夜在线| 九九九精品| av大香蕉网站| 日韩性爱啪啪视频| 不卡在线一区,精品一区二区三区中| 五月开心久久AV官网| 熟妇xxxxx性春色| 青青草乱入乱欲视频在线观看| 免费操逼91| 久久欧洲| 久草免费福利在线播放| 东京热不卡视频| www国产天美久久久| 超碰9 7女人| 日韩999| 91天天| 97视频620| 一区二区三区 日韩欧美| 小视频玖玖| 亚州综合图片| 99热99在线| 俺去也婷婷| 国产人妖视频一区在线观看| 婷婷情色五月天| 国产激情av女片自拍| 欧美在线电影| 麻豆成人AV| 亚洲aV无码成人在线观看| 欧美乱欲| 性爱av网站| 97日韩欧美| 天天草AV| 天天干天天日天天射黄色大片| www.av家庭乱伦| 天天色怡春院| 天天干少妇| 婷婷五月天激情网| 翔田千里无码一区| 乱人乱色一区二区三区免费| 国产丰满少妇久久久精品影院| 妺妺跟我一起洗澡没忍住| 亚欧无码线免费观看视频| 亚洲国产蜜臀系列在线观看| 免费观看的av| 国产免费久久久久| 一个国产在线综合网站| 97欧美视频| 蜜桃天美传媒AV一区二区三区| 天天天天天天天天综合| 欧美嗯啊……在线观看视频免费| 久久久精品成人国产| 国产精品宅男免费| 成人小说视频在线精品欧美| 国内一区二区免费| 天天干18禁| 中文字幕三四五区| 天天射天天色成人| 国产一区二区精品久久久不卡蜜臀| 久久同城AV| 日韩精品9区| 99re在线视频这里只有精品| 国产女人9999| 一本大道久| 9久热这里只有精品| 久久久久久九九九| 日韩强奸av| 亚洲精品影视老司机| 色婷婷九月天天综合| AV九九| 久久大香蕉手机高清| 99啪啪视频| 午夜福利在线合集| 欧美激情 亚洲色图| 人人贴人人摸| 国模少妇一区二区三区| 爱射综合| 十八禁一区二区无码观看| 亚洲情色 无码专区| 色欲av国内精品久久久久久| 浓厚中出中文字幕在线| 丰满人妻av一区二区三区| 人人乐大香蕉| 偷拍色图| 色欲天天婬色婬香WWW夜色| 99精品久久久久久久婷婷| 久久超碰爱| 最新9久久久9免费视频| 久久精品国产亚洲AV清纯| 丰满人妻一区二区三区大胸懂色| 综合熟女| 精品十八在线观看| 人妻少妇被猛烈进入中| 91狠婷| 亚洲欧美97√| 1769一区二区| 91超碰碰在线| AV一起草在线| 中文字幕av色| 中文乱码字幕观看视频| 十八禁啪啦拍视频无遮挡| 超碰99热中文字幕| 精品999999| 夂久色| 亚洲欧美黄| 狼天天狼天天大香蕉| 精品无码久久| 青青操青娱乐| 老熟女91| 99青青草国产视频| 摸奶性爱视频网站在线免费播放| 免费αV在线视频| 欧美操逼录像国产黄色国产| 日本二区不卡| 天天做天天爱天天高潮| 日本女优在线视频福利| 在现视频女上位好爽| 人人操,人人液| 久久人人爽爽爽人久久久| 国产婷婷综合在线观看| 粉嫩国产精品久久久| 激情网色| 啪啪啪男女亚洲中文字幕99| 久久人人看| 久久久久亚洲Av无码专区老牛影视| 日夜啪电影| 午夜激情成人在线观看| 青青草中出视频| 日韩人妻操B| 人人操我人人干| 激情视频图片| 91大神电影天堂| 欧美精品久久久久久久久88| 蜜臀99久| 2019午夜福利视频| 欧美大码在线视频| h无码动漫在线观看| 欧美翘臀视频网站一区二区三区| 97精品国产手机| 婷婷色综合| 亚洲精品人妻在线| 亚洲图片激情小说| 一本色道久久综合狠狠操| 超碰色中文| 男人天堂久久精品| 熟女色综合久久| 操啊国产| 久久久久97| 久久久久久久97| 超碰97人人乐| 91黑丝操| 久久久久久久久久久久欧美日| 91亚州日韩高清| 欧美久热| 日本午夜久久电影| 中文字幕亚洲热播人妻| A级毛片在线看免费| 欧美日本成人一区二区| 欧美色另类| 麻豆亚洲AV成人无码久久精品| 国产精品毛片?v一区二区三区| 国产精选视频| 怡红院成人视频| 亚州一区二区| 久久久久亚洲Av无码专区老牛影视| 97鸡把在线视频| 天天综合~91| 欧美 精品国产制服第一页| 免费A片三p视频| 影音先锋日本一区二区| 日韩中文字幕精品一区在线| 久久天天艹| 国内自拍 日韩激情 99| 久久免费精彩视频| 91色五月俺来也| 99re6国产精品99re| 久久黄黄黄| 97操| 久久久久亚洲?V片无码V| 黄色av一区二区在线| 五月婷婷丁香六月| 亚洲欧洲视频小说在线观看| 91精品丝袜久久久久久无码人妻| 青青草玖玖爱| 91春色| 91高清无码下载| 亚洲丝袜色| yazhouzaixian| 一级做受视频免费是看美女| 国产操逼逼网| 欧洲中文字幕| 男人天堂毛片| 国产一区二区三区白丝| 99re久久| 欧美91久久久久| av黄图片在线观看| 国产99 中文字幕日韩小视频| 9999伦理视频| 欧美激情 亚洲色图| 日韩久久.一级黄色片| 亚洲精品丝袜| 久久大黄片| 久久激情视频| av日韩中文字幕| 99热99在线播放激情| 嗯嗯啊好大| 在线岛| 国产视频小说| 国产av尤物| 精品人妻视频入口| 第一高清av中文字幕| www.91久久| 亚洲欧美校园| 美日韩成人| 91精品人妻电影| 91久久久老司机| 特级毛片特黄久久免费看| 十八禁一区二区无码观看| 黑人狂躁日本妞一区二区三区| 大香蕉伊在线久草麻豆天堂故事| 国内毛片无遮挡国产| 天天日天天舔东京热| www.91人妻.com| 欧美传媒一区| 日本午夜福利影院| 欧美姓爱综合网| 久久色一区| 囯产操逼片| 97干97色| 好看的久久不射无码影视影院| 亚洲精品天堂久久A∨51成人漫| 久久久久国产精品人妻aⅴ天堂| 国产伦精品一区二区三区在线观| 欧美美女视频| 一二三四视频在线社区中文字幕| 五月婷婷丁香六月| 欧美热图99| 久久精9| 任你爽视频| 欧美性爱中文字幕无线码| 九九九九精品精| 走光一区92下载| 国产青一二三| 五月丁香婷婷色| 秋霞操逼片| 欧美亚洲中文字幕| 日韩噜噜69| 精精夜夜| 婷婷五月天福利| 日日碰狠狠添天天爽超| 天天综合网网欲色| 日韩久射综合| 欧美极品少妇| 欧美激情亚洲情色| 丝袜天堂| ,国产乱人伦精品一区二区三区| 爱av免费| 中文字幕 国产区| 久久久久久AⅤ无码免费肉站| 黑人狂躁日本妞一区二区三区| 无码不卡亚洲成?人片| 视频不卡中文字幕| 蜜桃狠狠色伊人亚洲综合网站| 国产一区二区在线看| 丝袜狂射91| 黑白配性爱AV成| 日本道人妻久久久在线不卡色视频| 啊啊啊啊啊啊啊啊要喷了| 玖玖超碰熟| #NAME?| 啊啊啊慢点| 久草新在线| 欧美一二三级精品在线| 最新av中文字幕高清| 国产精品爱欲| 日操粉逼逼| 91国产丝袜美女| 麻豆精品三区视频| 日韩欧美蜜桃精品久久中文字幕久久| 精久久久| 精品九九| 自拍偷拍 日韩无码| 欧美性生活综合| 夜夜操老骚逼视频网站| 欧美韩日精品资源| 人妻少妇精品视频一区二区三区| 亚洲欧美天堂| 无码在线亚洲| 日韩天堂av电影在线观看| 成人精品欧洲亚洲| 九九九九免费| 国产精品久久久久亚洲av| 97久久精品亚洲| 男人天堂网手机版婷婷| 91久久久亚洲| 国产又爽又黄| 日韩精品三级片长长久久| 超碰97丝袜| 欧洲熟妇xxXx欧美老妇裸体 | 亚洲色人妻综合| 亚欧操逼片在线观看| 欧美性生活免费网| 日本久操视频| 麻豆一区二区三区在线看| 性暴力欧美猛交在线直播| 麻豆蜜桃视频在线观看| 天天操狠狠日夜夜干超大胆开放com大香蕉视频在线观看 | 欧美第一页性| 亚洲综合嫩| 女人高潮大叫一级毛片| Aa东京男人的天堂| 新久久AV| 91 丝袜在线观看| Av手机版天堂网| 91九九九小逼| 亚洲成人性爱网站在线播放| 国产男女无套97| 日韩有码 一区二区三区| 欧美久久婷| 人妻精品视频一区二区三区| 97超碰国产精品| 日韩在线观看三级电影| 青青青国产| 无码区蜜乳| 麻豆成人av| 午夜在线播放| 久久精品国产精品一区 | 无码人妻丰满热妇又大又粗| 熟妇人妻一区二区三在线| 青椒国产97在线熟女| 婷婷九月国产| 又黄又爽在线观看视频 | 97超碰色屌| 国产 亚洲 丝袜 制服| 欧洲亚洲人人爽爽视频| 日本理论在线| 欧美第一页| 9ⅰ久久久天天| 日韩在线视频1234| 97人人操人人摸人人爱| 人妻另类| 国产美女激情| 97色婷| 午夜福利av电影在线| 大茄子熟女AV导航| 日韩精品人妻中文字幕久久久| 国产精品自在自拍视频| 在线视频免费观看午夜| 久热99999| 欧美一区二区成人一卡| 黑丝内射一区二区三区| 操逼天美3区| 激情 欧美 亚洲 小说| 另类欧美色| 高清无码91| 久久偷偷色综合蜜桃| 日韩一区二区熟女| 韩国一区二区精品亚洲| 久久人人爽人人爽人人片Ⅴ| 欧美呦呦性爱| 先锋影音av先锋一区| 综合久久9|