资讯专栏INFORMATION COLUMN

小需求推动新语言快速学习:nginx lua 根据 user_agent 显示不同的页面

Gemini / 1621人阅读

摘要:一个小小的需求,可能会遇到很多问题,但是搜索相关的关键字,就能快速实现出来,完成一个小目标,事半功倍。下面开始一个小需求一个地址有两套页面,需要在后端根据浏览器的来显示不同的页面。而的结果在个并发的时候,失败的请求数依旧是。

之前做一次分享 如何快速学习一门新的语言的直播分享 但是那是以实现一个后端框架的角度来讲的,道理想通,我们要以实际的需求出发。一个小小的需求,可能会遇到很多问题,但是搜索相关的关键字,就能快速实现出来,完成一个小目标,事半功倍。

死记硬背手册,太枯燥了,反正我是看不下去,不如直接来个小项目。下面开始:

一个小需求

pc、mobile 一个地址有两套页面,需要在后端根据浏览器的 user_agent 来显示不同的页面。
通过 php 来做,当然可以,但是活动页面访问量一般都比较大,想优化些,所以想尝试下 lua。

nginx 安装 lua-nginx-module

可以直接上 openresty,不过有时候就是想折腾。
安装的步骤 https://mengkang.net/994.html (如果你想实践的话再看吧)

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))
小结

作为一个 lua 菜鸟,通过这个小需求我查了哪些资料

变量的定义
函数的写法
循环的了解
判断逻辑的写法
注释的写法
文件 i/o
字符串拼接 ..
字符串查找 string.match
字符串转小写 string.lower

稍微调整适配 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;
    }
}
演示地址

https://mengkang.net/promotion/1
https://mengkang.net/promotio...
切换 user_agent 即可看到,不同的 pc 和 mobile 两个版本的页面

和 php 性能对比 nginx 配置
rewrite ^/promotion2/(.*)$  /demo/promotion.php last;
php 代码

也就是说访问 http://mengkang.net/promotion/1 和 http://mengkang.net/promotion2/1 是一样的结果

配置说明

双核4G
nginx 配置一致
php 版本:7.0.11
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 http://mengkang.net/promotion2/1
Requests per second:    3105.21 [#/sec] (mean)
Time per request:       32.204 [ms] (mean)

ab -n 4000 -c 400 http://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 http://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 http://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 http://mengkang.net/promotion/1
Requests per second:    6014.89 [#/sec] (mean)
Time per request:       16.625 [ms] (mean)

ab -n 4000 -c 400 http://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 http://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 http://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。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/39658.html

相关文章

  • 需求推动新语快速学习nginx lua 根据 user_agent 显示不同页面

    摘要:一个小小的需求,可能会遇到很多问题,但是搜索相关的关键字,就能快速实现出来,完成一个小目标,事半功倍。下面开始一个小需求一个地址有两套页面,需要在后端根据浏览器的来显示不同的页面。而的结果在个并发的时候,失败的请求数依旧是。 之前做一次分享 如何快速学习一门新的语言的直播分享 但是那是以实现一个后端框架的角度来讲的,道理想通,我们要以实际的需求出发。一个小小的需求,可能会遇到很多问题...

    DevTalking 评论0 收藏0
  • 如何学习一门新语或框架

    摘要:简评新的语言层出不穷,等等。原作者分享了以下几点先掌握语言,再学习框架有些朋友倾向于学习框架,比如。比如说这段代码方式实现一些东西在功能实现的同时找到编程语言的乐趣,给编程语言找到具体的应用场景。 简评:新的语言层出不穷,Dart, Go, Kotlin, Elixir 等等。极光日报曾经分享过一篇文章 —— 不同编程语言的学习曲线。挑战学习曲线这事儿可能太难,但有些小技巧能帮助我们快...

    TANKING 评论0 收藏0
  • 再见,Python!你好,Go语

    摘要:语言诞生于谷歌,由计算机领域的三位宗师级大牛和写成。作者华为云技术宅基地链接谷歌前员工认为,比起大家熟悉的,语言其实有很多优良特性,很多时候都可以代替,他已经在很多任务中使用语言替代了。 Go 语言诞生于谷歌,由计算机领域的三位宗师级大牛 Rob Pike、Ken Thompson 和 Robert Griesemer 写成。由于出身名门,Go 在诞生之初就吸引了大批开发者的关注。诞生...

    zhaot 评论0 收藏0

发表评论

0条评论

Gemini

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<