記一次博客被羣壓的經歷

記一次博客被羣壓的經歷

前言

前段時間,博客和論壇都放到的阿里雲新購的三年 T5 實例服務器上,等都轉移過去才發現,所謂的 T5 實例只能滿足10% 的 CPU 峯值。期間經歷了各種卡頓、死機,最終又把博客單獨遷移了回來。靜態文件走 CDN,文章都 Redis,以爲萬事大吉了就。

羣壓

然並卵,有一天,羣裏有網友說要壓測我的論壇,我說那肯定一壓一個死,有本事來壓我的博客啊,順手便扔了博客網址,並@了全體人員。

然後,網友齊上陣,十八般武藝都拿出來了,有AB壓測的,有使用 jmeter 測試的,更有甚者自己使用 Python、Java 寫代碼替我壓測的,結果就是系統 CPU 爆表,訪問博客陷入了漫長的等待。

分析

先說一下博客架構: Nginx + PHP-fpm + CND + Redis + RDS,靜態文件走CDN,命中率基本在百分之八九十左右,動態請求走Nginx,然後交給 php-fpm 處理,博客文章進行了緩存處理,查詢基本不會走數據庫。

這裏總結下原因,在網友壓測的時候,登錄系統,TOP 了一下,發現 PHP-fpm 進程 CPU 佔比居高不下,畢竟1C1G的機器配置,相比於Nginx處理靜態頁面的能力,PHP-fpm 還是太弱雞了,無論怎麼優化,配置總會是瓶頸。

這裏說明一下網友的壓測,也就算是簡單的流量***,其實就是模擬多個用戶不停的進行訪問(訪問那些需要大量數據操作,就是需要大量CPU時間的頁面),從而把服務壓垮。

應對

其實對於壓測這種場景,我們使用 OpenResty + Lua 限流就可以輕鬆解決。

編寫 imit_req.lua 腳本:

-- 平滑限制接口請求數
local limit_req = require "resty.limit.req"
-- 這裏我們使用AB測試,-n訪問1000次, -c併發100個 
-- ab -n 1000 -c 100 http://121.142.155.213/
-- 限制 ip 每秒只能調用 200 次 接口 ,burst設置爲 0 則平滑限流
local lim, err = limit_req.new("my_limit_req_store", 10, 0)
if not lim then
    ngx.log(ngx.ERR,
            "failed to instantiate a resty.limit.req object: ", err)
    return ngx.exit(500)
end

-- IP維度的限流
local key = ngx.var.binary_remote_addr
local delay, err = lim:incoming(key, true)
if not delay then
    if err == "rejected" then
        return ngx.exit(503)
    end
    ngx.log(ngx.ERR, "failed to limit req: ", err)
    return ngx.exit(500)
end

if delay >= 0.001 then
    -- the 2nd return value holds  the number of excess requests
    -- per second for the specified key. for example, number 31
    -- means the current request rate is at 231 req/sec for the
    -- specified key.
    local excess = err

    -- the request exceeding the 200 req/sec but below 300 req/sec,
    -- so we intentionally delay it here a bit to conform to the
    -- 200 req/sec rate.
    ngx.sleep(delay) -- 延時處理
end

導入 nginx.conf 配置:

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    lua_shared_dict my_limit_req_store 100m;
    lua_shared_dict my_limit_conn_store 100m;
    lua_shared_dict my_limit_count_store 100m;
    server{
        listen 80;
        server_name blog.52itstyle.com;
        index index.php;
        root /mnt/domains/blog.52itstyle.com;
        location = /500.html {
            root   /usr/local/openresty/nginx/html;
        }
        error_page 500 502 503 504 = /503/503.html;
        location ~ \.php$ {
            # 導入 lua 限流 配置
            access_by_lua_file /usr/local/openresty/nginx/lua/limit_req.lua;
            fastcgi_pass 127.0.0.1:9000;
            include        fastcgi_params;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    }
    location ~ /\.ht {
        deny  all;
    }
}

劃重點,腳本中:

# 每秒訪問超過2次就拒絕服務,跳轉到503錯誤頁面
limit_req.new("my_limit_req_store", 2, 0)

記一次博客被羣壓的經歷

總結

我經常聽賣鎖具的人說:“再好的鎖,也只防好人,不防壞人!”,同樣適用於網絡,網友也只是娛樂一下而已,如果真有壞人想搞你,有無數種辦法把你搞死死。

參考

http://openresty.org/cn/

https://blog.52itstyle.vip/archives/3608/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章