国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

定時(shí)器在大型web項(xiàng)目中的應(yīng)用和實(shí)現(xiàn)

whataa / 713人閱讀

摘要:在軟件項(xiàng)目中,定時(shí)器也被應(yīng)用到了各方各面,本文將從項(xiàng)目入手,講述定時(shí)器,本文的例子都以為例。定時(shí)器總類定時(shí)器有兩種對(duì)應(yīng)重復(fù)任務(wù)和一次性任務(wù)。

在大規(guī)模分布式系統(tǒng)中,每個(gè)業(yè)務(wù)都可能是集群,每個(gè)業(yè)務(wù)機(jī)都會(huì)產(chǎn)生定時(shí)任務(wù),不同的業(yè)務(wù)會(huì)有不同的任務(wù)管理需求,統(tǒng)一的任務(wù)調(diào)度和管理變得非常有必要。

定時(shí)如何準(zhǔn)確,大量的定時(shí)被同時(shí)觸發(fā)怎么辦?

定時(shí)結(jié)束的時(shí)候,怎么通知業(yè)務(wù)機(jī)去處理呢?

某臺(tái)業(yè)務(wù)機(jī)下線了怎么辦?

如何提供任務(wù)更新、刪除功能?

基本模型如下圖:

定時(shí)器在社會(huì)中有著廣泛的應(yīng)用,比如每天叫你起床的鬧鐘。在軟件項(xiàng)目中,定時(shí)器也被應(yīng)用到了各方各面,本文將從 web 項(xiàng)目入手,講述定時(shí)器,本文的例子都以 node 為例。

為什么要用定時(shí)器?

沒有什么比機(jī)器更加準(zhǔn)時(shí)!在我接觸單片機(jī)的時(shí)候,已經(jīng)開始感嘆,為什么機(jī)器時(shí)間可以做到這么準(zhǔn)!

比如文章的定時(shí)發(fā)布、商品的準(zhǔn)點(diǎn)開始搶購、活動(dòng)定時(shí)上下架,肯定不會(huì)是一個(gè)又一個(gè)管理員在后臺(tái)幫你點(diǎn)擊按鈕,完成操作!系統(tǒng)的準(zhǔn)時(shí)可以定位到毫秒級(jí),雖然每個(gè)用戶可能和服務(wù)器的時(shí)間不一致,秒級(jí)的差別還是在可接受范圍的,但是在某些領(lǐng)域也會(huì)有很多精細(xì)到毫秒級(jí)的定時(shí)任務(wù)需求,比如航空航天、定時(shí)炸彈等等。

定時(shí)器總類

定時(shí)器有兩種 intervaltimeout, 對(duì)應(yīng)重復(fù)任務(wù)和一次性任務(wù)。在我的理解里,interval 任務(wù)只是在 timeout 的時(shí)候再次注冊(cè)了本任務(wù)。

// 重復(fù)性任務(wù)
var timer = setInterval(function(){
 // do something
}, milliseconds)
// 一次性任務(wù)
var timer = setTimeout(function(){
 // do something
}, milliseconds)
unix crontab 能解決問題嗎?

crontab 并不能精確到秒,crontab 的最小粒度是分,即當(dāng)?shù)谝晃皇恰?/1」時(shí),即最小單位是每分鐘執(zhí)行,(不排除你們有奇淫技巧可以做到秒級(jí)控制的)。unix 本身支持強(qiáng)大的定時(shí)任務(wù)管理 crontab,定時(shí)的格式也是強(qiáng)大得令人驚嘆。

* * * * * *
┬ ┬ ┬ ┬ ┬ ┬
│ │ │ │ │ |
│ │ │ │ │ └ day of week (0 - 7) (0 or 7 is Sun)
│ │ │ │ └───── month (1 - 12)
│ │ │ └────────── day of month (1 - 31)
│ │ └─────────────── hour (0 - 23)
│ └──────────────────── minute (0 - 59)
└───────────────────────── second (0 - 59, optional)

1)Cron 表達(dá)式的格式:秒 分 時(shí) 日 月 周 年 (可選)。

字段名 允許的值 允許的特殊字符
秒 0-59 , - * /
分 0-59 , - * /
小時(shí) 0-23 , - * /
日 1-31 , - * ? / L W C
月 1-12 or JAN-DEC , - * /
周幾 1-7 or SUN-SAT , - * ? / L C #
年 (可選字段) empty, 1970-2099 , - * /

「?」字符:表示不確定的值

「,」字符:指定數(shù)個(gè)值

「-」字符:指定一個(gè)值的范圍

「/」字符:指定一個(gè)值的增加幅度。n/m 表示從 n 開始,每次增加 m

「L」字符:用在日表示一個(gè)月中的最后一天,用在周表示該月最后一個(gè)星期 X

「W」字符:指定離給定日期最近的工作日 (周一到周五)

「#」字符:表示該月第幾個(gè)周 X。6#3 表示該月第 3 個(gè)周五

Cron 表達(dá)式范例:

每隔 5 秒執(zhí)行一次:/5 * ?

每隔 1 分鐘執(zhí)行一次:0 /1 ?

每天 23 點(diǎn)執(zhí)行一次:0 0 23 ?

每天凌晨 1 點(diǎn)執(zhí)行一次:0 0 1 ?

每月 1 號(hào)凌晨 1 點(diǎn)執(zhí)行一次:0 0 1 1 * ?

每月最后一天 23 點(diǎn)執(zhí)行一次:0 0 23 L * ?

每周星期天凌晨 1 點(diǎn)實(shí)行一次:0 0 1 ? * L

在 26 分、29 分、33 分執(zhí)行一次:0 26,29,33 * ?

每天的 0 點(diǎn)、13 點(diǎn)、18 點(diǎn)、21 點(diǎn)都執(zhí)行一次:0 0 0,13,18,21 ?

每種開發(fā)語言都提供了 crontab 的相關(guān)封裝,讓開發(fā)者調(diào)用起來得心應(yīng)手。以 node 為例:

require("crontab").load(function(err, crontab) {
 // create with string expression
 var job = crontab.create("ls -la", "0 7 * * 1,2,3,4,5");
});

你在 github 搜索 crontab 能搜到主流語言的實(shí)現(xiàn)。

有個(gè)問題,定時(shí)器不準(zhǔn)時(shí)!

setInterval 的回調(diào)函數(shù)并不是到時(shí)后立即執(zhí)行,而是等系統(tǒng)計(jì)算資源空閑下來后才會(huì)執(zhí)行。而下一次觸發(fā)時(shí)間則是在 setInterval 回調(diào)函數(shù)執(zhí)行完畢之后才開始計(jì)時(shí),所以如果 setInterval 內(nèi)執(zhí)行的計(jì)算過于耗時(shí),或者有其他耗時(shí)任務(wù)在執(zhí)行,setInterval 的計(jì)時(shí)會(huì)越來越不準(zhǔn), 延遲很厲害。crontab 也是同樣的原理。

var startTime = new Date().getTime();
var count = 0;
//耗時(shí)任務(wù)
setInterval(function(){
 var i = 0;
 while(i++ < 100000000);
}, 0);
setInterval(function(){
 count++;
 console.log(new Date().getTime() - (startTime + count * 1000));
}, 1000);

結(jié)果

126
176
163
112
109
107
203
189
170

當(dāng)然,不排除你們有奇淫技巧可以做到秒級(jí)控制的。

成千上萬定時(shí)任務(wù)時(shí)怎么管理?

Crontab 存在任務(wù)上限(其實(shí)我也不知道上限是多少,知道的麻煩告訴我),任務(wù)的同步、備份管理都比較麻煩,也會(huì)有比較多的并發(fā)問題需要處理。在分布式系統(tǒng)中,多帶帶去部署一個(gè)定時(shí)任務(wù)機(jī)器也是可行的。不過任務(wù)調(diào)度、定時(shí)結(jié)束通知客戶端也需要蠻多工作量的。

unix 的 crontab 不再是我們的第一選擇,每種編程可能都有定時(shí)任務(wù)管理的相關(guān)框架。比如 java 的 Quartz,Python 的 APScheduler。nodejs 的 node-schedule。但是這些東西是否能真的滿足你的需求呢?

So,我們需要一個(gè)定時(shí)任務(wù)管理平臺(tái)。

思路和實(shí)現(xiàn)

目標(biāo)

業(yè)務(wù)方可以定義定時(shí)時(shí)間、時(shí)間結(jié)束的觸發(fā)任務(wù)

業(yè)務(wù)方可以更新或者刪除已經(jīng)發(fā)布的定時(shí)任務(wù)

定時(shí)任務(wù)管理平臺(tái)統(tǒng)一接收和調(diào)度任務(wù)

主要解決兩個(gè)問題:

設(shè)置準(zhǔn)確的定時(shí)時(shí)間

時(shí)間結(jié)束觸發(fā)客戶端,不能重復(fù)消費(fèi)

redis 在 2.8.X 版本可以開啟了鍵空間通知,更多相關(guān)請(qǐng)移步 Redis Keyspace Notifications。(默認(rèn)不開啟,3.x 版本好像就失效了。),redis 支持的很多鍵空間事件,比如:DEL,RENAME,EXPIRE等等,redis 本身可以定義某個(gè)鍵的過期時(shí)間,ttl key。

這個(gè)值正好用來設(shè)置為定時(shí)任務(wù)的時(shí)間。更多相關(guān)請(qǐng)移步 Redis Keyspace Notifications。如果客戶端訂閱了某種規(guī)則的鍵通知,比如過期,那么在某個(gè)鍵過期的時(shí)候就會(huì)收到一個(gè)通知,這個(gè)事件就是定時(shí)結(jié)束,可以告訴業(yè)務(wù)機(jī)可以開啟任務(wù)了。

可如果有多個(gè) redis 客戶端訂閱了某個(gè)鍵的過期時(shí)間,那么任務(wù)還是會(huì)被觸發(fā)很多次。 因?yàn)槊總€(gè)客戶端
都是平等的,你能訂閱,我同樣可以訂閱。解決辦法就是 生產(chǎn)者和消費(fèi)者模式。同一個(gè)過期消息只能被消費(fèi)一次。

重點(diǎn)來了

把所有的定時(shí)任務(wù)按照定時(shí)開啟的時(shí)間倒序排列,存入 sorted Sets , 把時(shí)間設(shè)置為 score。這樣就會(huì)形成一個(gè)按照時(shí)間排好序的集合,可以按照時(shí)間先后依次取出所有的任務(wù),需要新增和修改任務(wù),也是可以通過 redis 的命令實(shí)現(xiàn)的。

定時(shí)管理服務(wù)器每 1000ms 去取 sorted sets 頂部的數(shù)據(jù),如果獲取到的 task 離觸發(fā)小于 1s,那么就可以執(zhí)行 pop() 操作,表示這個(gè)任務(wù)開始被調(diào)度執(zhí)行,因?yàn)?redis 的 pop() 是原子性的,同一個(gè) task 永遠(yuǎn)只會(huì)被消費(fèi)一次。這樣就解決了 redis 鍵空間通知會(huì)被重復(fù)消費(fèi)的問題。

偽代碼如下:

var taskSorts = new Sets(task1, task2, task3); // 在 redis 中建立按時(shí)間排序的集合

// 每隔一秒執(zhí)行一下操作,
var newOne = taskSorts.zrank(-1); // 獲取到最快發(fā)生的任務(wù)
if(newOne.time < 1000){ // 如果滿足消費(fèi)條件
 newOne = taskSorts.pop(); // 消費(fèi)該任務(wù),重復(fù)此循環(huán),繼續(xù)消費(fèi)下一個(gè)任務(wù)
 setTimeout(function(){
 // dosomething
 }, newOne.time)
}
任務(wù)觸發(fā)

任務(wù)的提交和觸發(fā)都應(yīng)該在業(yè)務(wù)方完成。定時(shí)任務(wù)管理平臺(tái)只是幫助管理和調(diào)度任務(wù)。在定義的任務(wù)里面定義好任務(wù)執(zhí)行的回調(diào)參數(shù)和接口。

客戶端定義任務(wù)的時(shí)候,同時(shí)注冊(cè)好定時(shí)結(jié)束的回調(diào)接口,或者應(yīng)該在項(xiàng)目啟動(dòng)的時(shí)候,就注冊(cè)好所有回調(diào)的接口。因?yàn)橥粋€(gè)業(yè)務(wù)的 A 機(jī)器提交了任務(wù),觸發(fā)的時(shí)候可能 A 機(jī)器下線了,只能定時(shí)任務(wù)平臺(tái)只能去觸發(fā)業(yè)務(wù) A 的 B 機(jī)器了。

引入跨服務(wù)遠(yuǎn)程調(diào)用。業(yè)務(wù)和定時(shí)任務(wù)管理平臺(tái)可能不在同一個(gè)機(jī)器,可能分布在不同的 ip。聽起來很復(fù)雜,實(shí)際上跨語言的調(diào)用調(diào)用方式有很多,比如 REST API、消息隊(duì)列、RPC。我的團(tuán)隊(duì)選擇了 Thrift(Facebook 開源的,跨語言的,現(xiàn)在共享給了 Apache 基金)。以上的方式都可以實(shí)現(xiàn)任務(wù)只被觸發(fā)了一次,遠(yuǎn)程通知給客戶端(任務(wù)注冊(cè)方)。

成品 -- nodejs 的實(shí)現(xiàn) cron-redis

https://github.com/MZMonster/cron-redis
主要依賴 bull 實(shí)現(xiàn)了任務(wù)隊(duì)列的管理功能實(shí)現(xiàn)的定時(shí)任務(wù)管理工具。

demo:

// 就這樣定義,3 秒鐘之后,hello 函數(shù)將被執(zhí)行。
function hello (x, y){
 console.log(new Date());
 console.log(x + " + "+ y +" = %s", x+y);
}

// 我是一個(gè)任務(wù)
var task1 = {
 method: hello.name, // 任務(wù)回調(diào)的函數(shù)
 params: [2, 3], // 任務(wù)執(zhí)行的參數(shù)
 rule: moment().add(3, "s").toDate() // 任務(wù)執(zhí)行間隔,支持 crontab 格式
}

queue.register(hello)
queue.publish(task1);

如果你要求不高,unix 自帶的 crontab 也足夠你折騰了。使用 redis 來實(shí)現(xiàn)定時(shí)也是一種極好的思路,cron-redis 值得你去試一試。

該庫只是一個(gè)定時(shí)任務(wù)的庫,實(shí)際上可以通過以上的思路實(shí)現(xiàn)微服務(wù)————定時(shí)任務(wù)管理平臺(tái)。通過 cron-redis 組合遠(yuǎn)程服務(wù)調(diào)用 thrift、服務(wù)的注冊(cè)發(fā)現(xiàn)工具 zookeeper,定時(shí)任務(wù)管理平臺(tái)分分鐘就被搭建了(等我下一篇文章吧,分分鐘搭建微服務(wù))。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/65684.html

相關(guān)文章

  • 時(shí)器大型web項(xiàng)目中的應(yīng)用實(shí)現(xiàn)

    摘要:在軟件項(xiàng)目中,定時(shí)器也被應(yīng)用到了各方各面,本文將從項(xiàng)目入手,講述定時(shí)器,本文的例子都以為例。定時(shí)器總類定時(shí)器有兩種對(duì)應(yīng)重復(fù)任務(wù)和一次性任務(wù)。 在大規(guī)模分布式系統(tǒng)中,每個(gè)業(yè)務(wù)都可能是集群,每個(gè)業(yè)務(wù)機(jī)都會(huì)產(chǎn)生定時(shí)任務(wù),不同的業(yè)務(wù)會(huì)有不同的任務(wù)管理需求,統(tǒng)一的任務(wù)調(diào)度和管理變得非常有必要。 定時(shí)如何準(zhǔn)確,大量的定時(shí)被同時(shí)觸發(fā)怎么辦? 定時(shí)結(jié)束的時(shí)候,怎么通知業(yè)務(wù)機(jī)去處理呢? 某臺(tái)業(yè)務(wù)機(jī)下線...

    douzifly 評(píng)論0 收藏0
  • 微服務(wù)與Spring Cloud概述

    摘要:微服務(wù)架構(gòu)概述應(yīng)用架構(gòu)的發(fā)展應(yīng)用是可獨(dú)立運(yùn)行的程序代碼,提供相對(duì)完善的業(yè)務(wù)功能。阿里開源的是的典型實(shí)現(xiàn)。它目前由官方開發(fā)維護(hù),基于開發(fā),提供一套完整的微服務(wù)解決方案。 微服務(wù)與Spring Cloud 隨著互聯(lián)網(wǎng)的快速發(fā)展, 云計(jì)算近十年也得到蓬勃發(fā)展, 企業(yè)的IT環(huán)境和IT架構(gòu)也逐漸在發(fā)生變革,從過去的單體應(yīng)用架構(gòu)發(fā)展為至今廣泛流行的微服務(wù)架構(gòu)。 微服務(wù)是一種架構(gòu)風(fēng)格, 能給軟件應(yīng)用...

    scwang90 評(píng)論0 收藏0
  • 深度解析Tengine的調(diào)試與資源監(jiān)控方法論

    摘要:是由淘寶網(wǎng)發(fā)起的服務(wù)器項(xiàng)目。回源監(jiān)控是內(nèi)容分發(fā)網(wǎng)絡(luò)的簡(jiǎn)稱,其分發(fā)的內(nèi)容來自用戶源站,負(fù)責(zé)回源的模塊是最重要組成部分之一,使跨越單機(jī)的限制,完成網(wǎng)絡(luò)數(shù)據(jù)的接收處理和轉(zhuǎn)發(fā)。這部分主要介紹的一些調(diào)試技巧和回源資源監(jiān)控的內(nèi)容,以及相應(yīng)的實(shí)例分享。 摘要: Tengine是由淘寶網(wǎng)發(fā)起的Web服務(wù)器項(xiàng)目。它在Nginx的基礎(chǔ)上,針對(duì)大訪問量網(wǎng)站的需求,提供更強(qiáng)大的流量負(fù)載均衡能力、全站HTTPS...

    everfight 評(píng)論0 收藏0
  • 大型網(wǎng)站技術(shù)架構(gòu)(1)

    摘要:網(wǎng)站都是從小網(wǎng)站一步一步發(fā)展為大型網(wǎng)站的,而這之中的挑戰(zhàn)主要來自于龐大的用戶安全環(huán)境惡劣高并發(fā)的訪問和海量的數(shù)據(jù),任何簡(jiǎn)單的業(yè)務(wù)處理,一旦需要處理數(shù)以計(jì)的數(shù)據(jù)和面對(duì)數(shù)以億計(jì)的用戶時(shí),問題就會(huì)變的很棘手下面我們就來說說這個(gè)演變過程初始階段大型 網(wǎng)站都是從小網(wǎng)站一步一步發(fā)展為大型網(wǎng)站的,而這之中的挑戰(zhàn)主要來自于龐大的用戶、安全環(huán)境惡劣、高并發(fā)的訪問和海量的數(shù)據(jù),任何簡(jiǎn)單的業(yè)務(wù)處理,一旦需要...

    fredshare 評(píng)論0 收藏0
  • 深入理解js

    摘要:詳解十大常用設(shè)計(jì)模式力薦深度好文深入理解大設(shè)計(jì)模式收集各種疑難雜癥的問題集錦關(guān)于,工作和學(xué)習(xí)過程中遇到過許多問題,也解答過許多別人的問題。介紹了的內(nèi)存管理。 延遲加載 (Lazyload) 三種實(shí)現(xiàn)方式 延遲加載也稱為惰性加載,即在長(zhǎng)網(wǎng)頁中延遲加載圖像。用戶滾動(dòng)到它們之前,視口外的圖像不會(huì)加載。本文詳細(xì)介紹了三種延遲加載的實(shí)現(xiàn)方式。 詳解 Javascript十大常用設(shè)計(jì)模式 力薦~ ...

    caikeal 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<