前段時(shí)間寫的那個(gè)域用戶平臺(tái),要做大量的新功能運(yùn)維測(cè)試,據(jù)說要抄 IT 組,讓那幫人到搞,跑一下! 尼瑪,這可嚇壞了我了。 因?yàn)槠脚_(tái)要和 windows 做大量的交互,那邊 powershell 又很不給力,改成多線程版本后,出現(xiàn)莫名的問題,很讓人鬧心?,F(xiàn)在的狀態(tài)是,client 給 server 端可以同時(shí)推送兩片信息,要是多的話,powershell 實(shí)在處理不了,我只能放到 queue 隊(duì)列里面了。
現(xiàn)在很多的堵塞都是在 windows 那邊,我這邊因?yàn)橛玫氖?tornado,對(duì)于用戶訪問是無壓力的,但是 windows 那邊不能同時(shí)運(yùn)行多了,不然會(huì)提示 bug。。。
ad 的信息我暫時(shí)還沒有批量的同步過來,所以只能單點(diǎn)搞了 ~
一直在想咋才能不出丑。所以做了好多的限制,比如短信接口的 token 機(jī)制,用戶更新接口的次數(shù)的限制。 現(xiàn)在唯一的節(jié)點(diǎn)就是和 win 那邊的交互。別等到了周一的時(shí)候,一幫人把 獲取手機(jī)號(hào)碼、修改密碼、更新用戶信息的接口給點(diǎn)爆了。
突然想到 12306 那個(gè)渣渣,可以用排隊(duì)呀。。。 這樣的話,最少能看起來很高端的樣子。
http://wiki.jikexueyuan.com/project/python-actual-combat/images/36.jpg" alt="pic" />
我的前端實(shí)現(xiàn) ~
用戶點(diǎn)擊的時(shí)候,我會(huì)從后端的 api 查看隊(duì)列中的數(shù)目,以及有誰排在我的前面 ~
$("#dialog").hide();
$("#mailname").focus();
$("#service").click(function(){
$.ajax({
type: "POST",
url: "/queue",
data : $("#form_service").serialize(),
dataType: "html",
timeout:5000,
error: function(){
alert('nima,超時(shí)了');
},
success: function(data,status){
if( data=="ok"){
<!-- alert (data+status+"成功了");-->
var a=$("input[name=mailname]").val();
window.location.href="/mailpost?mailname="+a; }
else{
$('#myModal').modal();
}
}
});
});
});
后端的實(shí)現(xiàn)~
不用 redis 做隊(duì)列的原因是,python 調(diào)用隊(duì)列的時(shí)候總是莫名的關(guān)閉,卸載安裝了好多遍。。。怪事 ~ 和 powershell 多線程一樣都很怪~
安裝配置 memcached 環(huán)境,簡(jiǎn)單點(diǎn)直接 yum ~
需要編譯安裝的朋友,用下面的腳本~
wget https://github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz
tar xzf libevent-2.0.21-stable.tar.gz
cd libevent-2.0.21-stable
./configure
make
make install
wget http://memcached.googlecode.com/files/memcached-1.4.15.tar.gz
tar vxzf memcached-1.4.15.tar.gz
cd memcached-1.4.15
./configure --prefix=/usr/local/webserver/memcached
make
make install
http://wiki.jikexueyuan.com/project/python-actual-combat/images/37.jpg" alt="pic" />
啟動(dòng) memcached 命令是: /usr/local/memcached/bin/memcached -d -m 100 -c 1000 -u root -p 11211
-d 選項(xiàng)是啟動(dòng)一個(gè)守護(hù)進(jìn)程
-m 是分配給 Memcache 使用的內(nèi)存數(shù)量,單位是 MB,默認(rèn) 64 MB
-M return error on memory exhausted (rather than removing items)
-u 是運(yùn)行 Memcache 的用戶,如果當(dāng)前為 root 的話,需要使用此參數(shù)指定用戶
-l 是監(jiān)聽的服務(wù)器 IP 地址,默認(rèn)為所有網(wǎng)卡
-p 是設(shè)置 Memcache 的 TCP 監(jiān)聽的端口,最好是 1024 以上的端口
-c 選項(xiàng)是最大運(yùn)行的并發(fā)連接數(shù),默認(rèn)是 1024
-P 是設(shè)置保存 Memcache 的 pid 文件
-f chunk size growth factor (default: 1.25)
-I Override the size of each slab page. Adjusts max item size(1.4.2 版本新增)
有朋友可能沒有接觸過 memcached,也有沒有用 python 操作 memcached 的。 我在這里就簡(jiǎn)單操作下,讓大家瞅瞅哈~
python 操作 memcached 需要安裝 python-memcached 模塊
pip install python-memcached
import memcache
mc=memcache.Client(['127.0.0.1:11211'],debug=0)
mc.set(“xiaorui.cc”,”fengyun”)
value=mc.get(“xiaorui.cc”)
mc.set(“another_key”,3)
mc.delete(“another_key)
mc.set(“key”,”1″) #用于自動(dòng)增量/減量的必須是字符串
mc.incr(“key”)
mc.decr(“key”)
標(biāo)準(zhǔn)的使用 memcache 作為數(shù)據(jù)庫緩存的方法如下:
key=derive_key(obj)
obj=mc.get(key)
if not obj:
obj=backend_api.get(…)
mc.set(obj)
#現(xiàn)在可以操作 obj
構(gòu)造函數(shù)
delete(key,time=0)
刪除某個(gè)鍵。time 的單位是秒,確保特定時(shí)間內(nèi)的 set/update 操作會(huì)失敗。返回 1 成功,0 失敗。
incr(key,delta=1)
給自增量變量加上 delta,默認(rèn)為 1。
decr(key,delta=1)
給自減量變量減去 delta,默認(rèn)為 1。
add(key,val,time=0,min_compress_len=0)
添加一個(gè)鍵值對(duì),內(nèi)部調(diào)用 _set() 方法。
replace(key,val,time=0,min_compress_len=0)
替換值,內(nèi)部調(diào)用_set() 方法。
set(key,val,time=0,min_compress_len=0)
無條件的設(shè)置鍵值對(duì)。time 設(shè)置超時(shí),單位是秒。min_compress_len 用于設(shè)置 zlib 壓縮。內(nèi)部調(diào)用_set() 方法。
set_multi(mapping,time=0,key_prefix=”,min_compress_len=0)
設(shè)置多個(gè)鍵值對(duì)。
get(key)
獲取值。出錯(cuò)則返回 None。
get_multi(keys,key_prefix=”)
獲取多個(gè)鍵的值,返回字典。keys 為健明列表。key_prefix 是鍵名前綴,可以最終構(gòu)成 key_prefix+key 的完整鍵名。與 set_multi 中一樣。
Memcached 本身沒有的實(shí)現(xiàn)的,但是高手還是多呀,有個(gè)高手開源了一個(gè) memcached 隊(duì)列的 python 實(shí)現(xiàn)方案。
RedQueue 參考了 github 開源項(xiàng)目 starling(ruby 寫的), twitter 曾經(jīng)使用伊做隊(duì)列服務(wù),后來改成了用 scala 寫的 scaling(kestrol) . Redqueue 用 python 的高性能框架 tornado 寫成。支持 memcache 協(xié)議, 也就是說偽裝成一個(gè) memcache server,由于許多語言都有了 memcache 庫,也就有了應(yīng)用 redqueue 的土壤。
redqueue 是可以持久化的,使用日志文件記錄所有的操作,當(dāng)系統(tǒng)重啟的時(shí)候,可以恢復(fù)沒有處理的未超時(shí)任務(wù)重新處理。 這樣對(duì)于 server 端的容錯(cuò)性有好處。更進(jìn)一步的是,redqueue 具有客戶端容錯(cuò)性,客戶通過 get 命令從隊(duì)列中得到一個(gè)任務(wù),使用 delete 刪除這個(gè)任務(wù),如果沒有 delete 而因某種原因退出了,則該任務(wù)會(huì)被 server 重新塞入隊(duì)列等待處理。
http://wiki.jikexueyuan.com/project/python-actual-combat/images/38.jpg" alt="pic" />
關(guān)于 redqueue 的 python 應(yīng)用小 demo ~
# 引入 memcache 模塊
import memcache
#初始化客戶端
mc = memcache.Client(['127.0.0.1:12345']) # 假設(shè) redqueue server 守候在 localhost 的 12345 端口
# 發(fā)布一個(gè)項(xiàng)目到 key myqueue 中, 值為"Hello world"
mc.set("xiaorui", "good")
# 消費(fèi)者從 queue server 中取出一個(gè)任務(wù), 并打印
print mc.get("xiaorui") # 應(yīng)該是 good
# 刪除一個(gè)任務(wù),必須做,否則 server 會(huì)認(rèn)為客戶端異常發(fā)生了,而重新隊(duì)列處理該任務(wù)
# 什么時(shí)候客戶端確認(rèn)該任務(wù)已經(jīng)確保執(zhí)行了,就可以 delete 掉。在這之間,任務(wù)不會(huì)被其他客戶端執(zhí)行。
mc.delete("xiaorui")
http://wiki.jikexueyuan.com/project/python-actual-combat/images/39.jpg" alt="pic" />
這個(gè)是作者給的過程:
== Install and Run
Install tornado and (optional) python-memcached for client testing
Get the source from
git@github.com:superisaac/redqueue.git
Install
% python setup.py install
Make the log dir
% mkdir -p log
Run the server
% redqueue_server.py
For more options please run
% redqueue_server.py --help
== Reserve/delete mode
Reserve/delete mode is currently the sole mode, once an item is fetched, a delete request must be send later to mark the item is used, or else the item will be recycled back later.
>>> mc.set('abc', '123')
>>> v = mc.get('abc')
>>> if v is not None:
>>> mc.delete('abc')
現(xiàn)在隊(duì)列有了,我給大家說下,我那邊是咋實(shí)現(xiàn)排隊(duì)的~
當(dāng)用戶訪問頁面下一步的時(shí)候,我會(huì)判斷隊(duì)列,要是他前面有人在進(jìn)行,我會(huì)給他重定向到最初的頁面。當(dāng)別人搞完了,他才可以的。
但是這樣的話,還有個(gè)問題,那就是要是有 5 個(gè)人同時(shí)進(jìn)了隊(duì)列里面了,我給他們已經(jīng)排序了,要是老大和老二,他不在進(jìn)行了,老三的話,咋辦。。。 這時(shí)候就需要配置隊(duì)列里面的值和 kv 的一個(gè)值做時(shí)間的生效。 也就是說 老大和老二要是在指定的時(shí)間內(nèi)沒有完成的話,我會(huì)把他們踢出去,這樣老三就成老大了。
本文出自 “峰云,就她了?!?博客,謝絕轉(zhuǎn)載!