1. 程式人生 > >【網頁加速】lua redis的二次升級

【網頁加速】lua redis的二次升級

ebs 緩存 如果 錯誤頁 ast sca 技術分享 網絡 socket

之前發過openresty的相關文章,也是用於加速網頁速度的,但是上次沒有優化好代碼,這次整理了下,優化了nginx的配置和lua的代碼,感興趣的話可以看看上篇的文章:
https://www.cnblogs.com/w1570631036/p/8449373.html

為了學習,不斷的給自己的服務器裝東西,又是logstash,又是kafka,導致主站網絡負載、cpu消耗過大,再加上tomcat這個本身就特別占用內存的東西,只要稍微刷新一下網站,就能感受到蝸牛般的速度,實在受不了,前段時間給網站加了n多層緩存,依舊沒有改觀多少,想了想,算了,一直都這麽卡,還不如直接將動態的網站直接變成靜態網頁存儲在redis裏面,然後關掉tomcat,貌似沒有改觀多少,但是在xshell裏面敲命令沒那麽卡了,這裏,也提出了一種別樣的網站加速方法——redis存儲靜態網頁。

技術分享圖片

一、總體流程如下

技術分享圖片

1.一次請求過來,通過openresty的nginx來訪問lua腳本;
2.讀取redis中是否存在該uri對應的靜態網頁,如果有,則直接返回,否則回源到tomcat,然後將響應的內容保存到redis裏面。

二、nginx的設置

openresty中自帶了nginx,所以只需要配置一下即可,我們最終的目前是攔截所有以html結尾的請求,如果是以其他後綴結尾的,比如do,則可以直接回滾到tomat裏面去。
由於篇幅的關系,只粘貼部分nginx配置,想看全的請轉至:mynginxconfig.ngx

    server {
        listen       80;
        # listen       443 ssl;   # ssl
        server_name  www.wenzhihuai.com;
        location  ~ .*\.(html)$ {       //攔截所有以html結尾的請求,調用lua腳本
            ...
            charset utf8;
            proxy_pass_request_headers off ;
            # 關閉緩存lua腳本,調試的時候專用
            lua_code_cache off;
            content_by_lua_file /opt/lua/hello.lua;
        }
        location / {        //nginx是按順序匹配的,如果上面的不符合,那麽將回滾tomcat
            default_type    text/html;
            root   html;
            index  index.html index.htm;
            ...
            # websocket
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_pass http://backend;
        }

三、lua腳本

為了方便key的操作,經過測試,即使uri帶有各種字符,比如 ? . html = &等,都是可以直接設置為redis中的key的,所以,不是那麽的需要考慮redis的key違反規則,可以直接將uri設置為key。具體流程如下:

local key = request_uri
首先,key為請求訪問的uri
local resp, err = red:get(key)
去redis上查找有沒有
if resp == ngx.null then
    如果沒有
    ngx.req.set_header("Accept", "text/html,application/xhtml+xml,application/xml;")
    ngx.req.set_header("Accept-Encoding", "")
    這裏,特別需要註意的是,要把頭部的信息去掉,這裏之前說過。(如果不去掉,就是gzip加密返回,然後再經過一層gzip加密返回給用戶,導致用戶看到的是gzip壓縮過的亂碼)
    local targetURL = string.gsub(uri, "html", "do")
    這裏講html替換為do,即:不攔截*.do的請求,其可以直接訪問tomcat
    local respp = ngx.location.capture(targetURL, { method = ngx.HTTP_GET, args = uri_args })
    開始回源到tomcat
    red:set(key, respp.body)
    將uri(key)和響應的內容設到redis裏面去
    red:expire(key, 600)
    lua redis並沒有提供在set的時候同時設置過期時間,所以,額外加一行設置過期時間
    ngx.print(respp.body)
    將響應的內容輸出給用戶
    return
end
ngx.print(resp)

四、測試

進行一次測試,以訪問http://www.wenzhihuai.com/jaowejoifjefoijoifaew.html 為例,我的網站並沒有設置這個uri,所以,訪問的時候,會統一調到錯誤頁面,之後,會在redis中看到有這條記錄:

技術分享圖片

該地址已經成功被緩存到redis裏面去,點擊其他頁面,可以看到,只要是點擊的頁面,都被緩存到redis裏面去了。總體來說,如果不設置過期時間,可以把整個網頁靜態化緩存到redis裏面,甚至是可以關閉tomcat了,但是這種做法只適用於萬年不變的頁面,至於用於企業的話,,,,

後記:
其實我有個疑問,我的代碼裏,並沒有設置lua斷開redis的連接,不知道會不會有影響,而且它這個是指每次請求過來,都需要重新連接redis麽?光是TCP三次握手就耗時不少啊,不知道怎麽優化這些信息。

全部代碼如下:

local redis = require "resty.redis"
local red = redis:new()
local request_uri = ngx.var.request_uri
local ngx_log = ngx.log
local ngx_ERR = ngx.ERR

local function close_redis(red)
    if not red then
        return
    end
    local pool_max_idle_time = 10000
    local pool_size = 100
    red:set("pool_size", pool_size)
    local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)
    if not ok then
        ngx_log(ngx_ERR, "set redis keepalive error : ", err)
    end
end

local uri = ngx.var.uri

red:set_timeout(1000)
red:connect("119.23.46.71", 6340)
red:auth("root")
local uri_args = ngx.req.get_uri_args()

local key = request_uri
local resp, err = red:get(key)

if resp == ngx.null then
    ngx.req.set_header("Accept", "text/html,application/xhtml+xml,application/xml;")
    ngx.req.set_header("Accept-Encoding", "")
    local targetURL = string.gsub(uri, "html", "do")
    local respp = ngx.location.capture(targetURL, { method = ngx.HTTP_GET, args = uri_args })
    red:set(key, respp.body)
    red:expire(key, 600)
    ngx.print(respp.body)
    return
end
ngx.print(resp)
close_redis(red)

【網頁加速】lua redis的二次升級