閱讀929 返回首頁    go 阿裏雲 go 技術社區[雲棲]


nginx lua 小項目:根據 user_agent 顯示不同的頁麵,附帶和 php 性能的對比

需求

pc、mobile 一個地址有兩套頁麵,需要在後端根據瀏覽器的 user_agent 來顯示不同的頁麵

lua demo 腳本

-- 判斷是否是手機瀏覽器
function isMobile(userAgent)
    -- 99% 前三個都能匹配上吧
    local mobile = {
        "phone", "android", "mobile", "itouch", "ipod", "symbian", "htc", "palmos", "blackberry", "opera mini", "windows ce", "nokia", "fennec",
        "hiptop", "kindle", "mot", "webos", "samsung", "sonyericsson", "wap", "avantgo", "eudoraweb", "minimo", "netfront", "teleca"
    }
    userAgent = string.lower(userAgent)

    for i, v in ipairs(mobile) do
        if string.match(userAgent, v) then
            return true
        end
    end

    return false
end

-- 根據id + 瀏覽器類型展示活動頁麵
function showPromotionHtml(id, isMobile)
    local path = "/data/www/mengkang/demo/promotion/"
    local filename

    if isMobile then
        path = path .. "mobile"
    else
        path = path .. "pc"
    end

    filename = path .. "/" .. id .. ".html"

    if file_exists(filename) then
        local file = io.open(filename,"r")
        io.input(file)
        print(io.read("*a"))
        io.close(file)
    else
        print("文件不存在: " .. string.gsub(filename, "/data/www/mengkang/demo", ""))
    end
end

-- 判斷文件是否存在
function file_exists(path)
    local file = io.open(path, "rb")
    if file then file:close() end
    return file ~= nil
end

local id = 1
local userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"
showPromotionHtml(id, isMobile(userAgent))

稍微調整適配 nginx lua 模塊

-- 判斷是否是手機瀏覽器
function isMobile(userAgent)
    -- 99% 前三個都能匹配上吧
    local mobile = {
        "phone", "android", "mobile", "itouch", "ipod", "symbian", "htc", "palmos", "blackberry", "opera mini", "windows ce", "nokia", "fennec",
        "hiptop", "kindle", "mot", "webos", "samsung", "sonyericsson", "wap", "avantgo", "eudoraweb", "minimo", "netfront", "teleca"
    }
    userAgent = string.lower(userAgent)

    for i, v in ipairs(mobile) do
        if string.match(userAgent, v) then
            return true
        end
    end

    return false
end

-- 根據id + 瀏覽器類型展示活動頁麵
function showPromotionHtml(id, isMobile)
    local path = "/data/www/mengkang/demo/promotion/"
    local filename

    if isMobile then
        path = path .. "mobile"
    else
        path = path .. "pc"
    end

    filename = path .. "/" .. id .. ".html"

    if file_exists(filename) then
        local file = io.open(filename,"r")
        io.input(file)
        ngx.say(io.read("*a"))
        io.close(file)
    else
        ngx.say("file not found : " .. string.gsub(filename, "/data/www/mengkang/demo", ""))
    end
end

-- 判斷文件是否存在
function file_exists(path)
    local file = io.open(path, "rb")
    if file then file:close() end
    return file ~= nil
end

local id = ngx.var.id
local userAgent = ngx.req.get_headers().user_agent
showPromotionHtml(id, isMobile(userAgent))

nginx 配置

server
{
    listen       80;
    server_name mengkang.net

    location ~ /promotion/(\d+)
    {
        set $id $1;
        default_type "text/html";
        content_by_lua_file /data/www/lua/1.lua;
    }
}

nginx 單獨安裝 lua 模塊也行,使用 openresty 也可以。單獨安裝參考:https://mengkang.net/994.html

演示地址

https://mengkang.net/promotion/1
https://mengkang.net/promotion/100
切換 user_agent 即可看到,不同的 pc 和 mobile 兩個版本的頁麵

和 php 性能對比

nginx 配置

rewrite ^/promotion2/(.*)$  /demo/promotion.php last;

php 代碼

<?php
header("Content-type:text/html;charset=utf-8");
header_remove('x-powered-by');
ini_set('display_errors', 'Off');

function getId(){
    $uri = $_SERVER["REQUEST_URI"];
    $tmp = explode("?",$uri);
    $uri = $tmp[0];
    $uri = trim($uri,"/");
    $tmp = explode("/",$uri);
    return intval(array_pop($tmp));
}

function isMobile()
{
    $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? strtolower ( $_SERVER['HTTP_USER_AGENT'] ) : '';

    if ( preg_match ( "/phone|itouch|ipod|symbian|android|htc_|htc-|palmos|blackberry|opera mini|windows ce|nokia|fennec|hiptop|kindle|mot |mot-|webos\/|samsung|sonyericsson|mobile|pda;|avantgo|eudoraweb|minimo|netfront|nintendo/", $user_agent ) ) {
        return true;
    }

    return false;
}

$id = getId();

$isMobile = isMobile();


if ($isMobile){
    $filename = __DIR__."/promotion/mobile/".$id.".html";
}else{
    $filename = __DIR__."/promotion/pc/".$id.".html";
}


if (file_exists($filename)) {
    echo file_get_contents($filename);
}else{
    echo "file not found : /promotion/pc/".$id.".html";
}

exit;

也就是說訪問 https://mengkang.net/promotion/1https://mengkang.net/promotion2/1 是一樣的結果

配置說明

雙核4G
nginx 配置一致
php-fpm 配置:

pm = dynamic
pm.max_children = 10
pm.start_servers = 4
pm.min_spare_servers = 4
pm.max_spare_servers = 10

php 壓測結果

ab -n 1000 -c 100 https://mengkang.net/promotion2/1
Requests per second:    3105.21 [#/sec] (mean)
Time per request:       32.204 [ms] (mean)

ab -n 4000 -c 400 https://mengkang.net/promotion2/1
Requests per second:    3361.87 [#/sec] (mean)
Time per request:       118.981 [ms] (mean)
Complete requests:      4000
Failed requests:        259

ab -n 8000 -c 800 https://mengkang.net/promotion2/1
Requests per second:    3358.20 [#/sec] (mean)
Time per request:       238.223 [ms] (mean)
Complete requests:      8000
Failed requests:        654

ab -n 10000 -c 1000 https://mengkang.net/promotion2/1
Requests per second:    3275.30 [#/sec] (mean)
Time per request:       305.315 [ms] (mean)
Complete requests:      10000
Failed requests:        9150

lua 壓測結果

ab -n 1000 -c 100 https://mengkang.net/promotion/1
Requests per second:    6014.89 [#/sec] (mean)
Time per request:       16.625 [ms] (mean)

ab -n 4000 -c 400 https://mengkang.net/promotion/1
Complete requests:      4000
Failed requests:        0
Requests per second:    6190.57 [#/sec] (mean)
Time per request:       64.614 [ms] (mean)

ab -n 8000 -c 800 https://mengkang.net/promotion/1
Complete requests:      8000
Failed requests:        0
Requests per second:    7046.66 [#/sec] (mean)
Time per request:       113.529 [ms] (mean

ab -n 10000 -c 1000 https://mengkang.net/promotion/1
Complete requests:      10000
Failed requests:        0
Requests per second:    5670.38 [#/sec] (mean)
Time per request:       176.355 [ms] (mean)

對比可見

PHP qps 在 3000左右,nginx_lua qps 在 7000 左右。qps 提升了1倍多,而且響應時間更短,而且 php 在 400 個並發的時候開始出現比較多的失敗請求,吞吐率開始下降。而 lua 的結果在 1000 個並發的時候,失敗的請求數依舊是0。

最後更新:2017-09-19 16:02:42

  上一篇:go  初來乍到,有失遠迎
  下一篇:go  《算法技術手冊》一2.3.1 最壞情況