导读:nginx是一个高性能的反向代理服务器,lua是一个小巧的脚本语言,这两个的巧妙结合会擦出怎样的火花呢。

关键词:nginx,lua,nginx+lua

前言

nginx,lua,nginx+lua,这三个名词不知道大家熟悉多少。为了后面内容的展示,我简单的介绍一下它们,想深入了解的网上资料很多,在这就不啰嗦了。nginx是一个高性能的反向代理服务器,一般会处在网站的最前端(有可能前面还会加一层slb,在这暂时忽略),用来做后端web服务的代理;lua是一个小巧的脚本语言,其设计的目的就是嵌入应用程序中,为其提供一些扩展和增强,比如redis,nginx等等;nginx+lua顾名思义就是nginx和lua的结合体,这两者之间沟通的桥梁是nginx_lua_module,它是nginx的一个模块,有了它nginx和lua才能互通,笔者在最近几年的工作中恰好有这方面的开发经验,所以想把这些真实的使用场景分享出来供大家做参考,具体的api doc还请大家参考官方资料。

案例1-入口层流量的灰度识别

何谓入口层流量的灰度识别呢,简单来说就是A用户的请求打到线上环境,B用户的请求打到灰度环境,目的就是做新功能的验证,实现逻辑很简单,大体流程如下:

1.测试同学在灰度控制台配置灰度规则,规则里会约束哪些url下哪些商户的请求进入灰度环境;

2.灰度控制台推送规则给入口层nginx,nginx会将规则存储到本地内存中,借助ngx.shared.DICT

3.请求进入的时候(通过rewrite_by_lua_file触发)获取本地内存中的规则进行比对,如何命中规则就将请求转发到灰度环境,对nginx来说就是切换不同的upstream,比如线上是prod_serverA,灰度是gray_serverA;

代码片段如下:

upstream  gray_serverA {
server 192.68.1.1:8080;
} upstream prod_serverA {
server 192.68.1.2:8080;
} server {
listen 80;
server_name graytest.demo.com;
charset utf-8; location ~ \.do$ {
set $backend 'prod_serverA'; #默认的upstream为线上服务
rewrite_by_lua_file "conf/lua-gray/rewriter.lua"; # rewrite_by_lua_file 可以简单的理解为一个过滤器,nginx在rewrite阶段会执行你指定的脚本文件,
           #在这个文件中我们会判断请求是否为灰度请求如果是灰度请求就将backend改为gray_serverA
proxy_pass http://$backend;
}
}

  

案例2-入口层记录错误日志

之前有同学反馈说springmvc偶尔会报415错误,这个错误的一个常见原因是传递的Content-Type头不对,比如后端需要application/json,但是前端传递了application/x-www-form-urlencoded,那就会报这个错。但是跟前端确认了传递的头是没有问题的,有人猜测可能是头信息有特殊字符,导致后端web 容器(tomcat、resin)解析头出现了问题,既然这样把所有请求头打出来一看究竟,于是lua再一次出场,这次主要用来输出请求头到日志文件中,主要用到了log_by_lua_block这个指令,代码片段如下:

location  ~ \.do$ {
proxy_pass http://$backend;
log_by_lua_block {
      //判断下如果http 响应状态码为415就输出请求头到文件中
if tonumber(ngx.var.status) == 415 then
ngx.log(ngx.ERR,"upstream reponse status is 415,please notice it,here are request headers:")
local h, err = ngx.req.get_headers(100,true) if err == "truncated" then
ngx.log(ngx.ERR,"request headers beyond 100,will not return")
else
local cjson = require("cjson")
ngx.log(ngx.ERR,cjson.encode(h))
end
end
}
}

想详细了解这个案例的,请移步到我的另一篇博客(https://www.cnblogs.com/chopper-poet/p/11625144.html)。

案例3-将nginx信息注册到监控平台

需求很简单,当nginx启动的时候将自身信息上报到redis中,上报内容包扣自身的ip,代理的域名信息等,有个监控平台会定期从redis读取这些信息做展示,方便运维干活,流程很简单就是定时读取自身ip和代理的域名信息写到redis中,为什么要定时呢,这里还起到一种心跳的效果,当长时间没有上报时可能是nginx出问题了,主要用到的指令如下:

1.init_worker_by_lua_file "conf/ua-grayngxReloadListener.lua",当nginx启动或者reload的时候会执行指定的文件;

2.ngx.worker.id() 这个方法会返回nginx worker进程的编号,从0开始,如果nginx有4个worker,那取值范围为0-3,这个主要是为了防止并发上报,因为第一步里面提到的init_worker_by_lua_file,如果有几个worker就会触发几次,所以为了只上报一次,会判断下返回值是否为0,也就是只让第一个worker执行;

3.ngx.timer.every 用来执行定时任务;

代码片段如下:

local workerId = ngx.worker.id()

if(workerId == 0) then
ngx.log(ngx.INFO,'workerId is 0 will startup task') local ok, err = ngx.timer.every(4,function()
#1. get local ip and domins
#2. write to redis
end) else
ngx.log(ngx.INFO,'workerId is not 0 ,just ignore it')
end

 

案例4-将入口层流量同时转发到多个后端服务

类似于消息队列的发布订阅一样,在nginx这一层可以将一个请求同时发到多个地址,代码片段如下:

location  ~ /capture_test$ {
content_by_lua_block {
ngx.req.read_body() res1, res3 = ngx.location.capture_multi{
{ "/capture_test1",{ method = ngx.HTTP_POST, always_forward_body=true}},
{ "/capture_test2",{ method = ngx.HTTP_POST, always_forward_body=true}},
} ngx.say(res3.body)
ngx.exit(res3.status)
}

总结

上面列举了nginx+lua在我司使用的四个案例,真实场景要复杂很多,为了方便大家理解,特意将案例做了简化。如果觉得有用,请点个推荐。

参考资料

https://github.com/openresty/lua-nginx-module

nginx+lua在我司的实践的更多相关文章

  1. 基于nginx+lua+redis高性能api应用实践

    基于nginx+lua+redis高性能api应用实践 前言 比较传统的服务端程序(PHP.FAST CGI等),大多都是通过每产生一个请求,都会有一个进程与之相对应,请求处理完毕后相关进程自动释放. ...

  2. 用Nginx+Lua(OpenResty)开发高性能Web应用

    在互联网公司,Nginx可以说是标配组件,但是主要场景还是负载均衡.反向代理.代理缓存.限流等场景:而把Nginx作为一个Web容器使用的还不是那么广泛.Nginx的高性能是大家公认的,而Nginx开 ...

  3. Nginx+Lua(OpenResty)开发高性能Web应用

    使用Nginx+Lua(OpenResty)开发高性能Web应用 博客分类: 跟我学Nginx+Lua开发 架构 ngx_luaopenresty 在互联网公司,Nginx可以说是标配组件,但是主要场 ...

  4. 使用Nginx+Lua(OpenResty)开发高性能Web应用

    摘自(http://jinnianshilongnian.iteye.com/blog/2280928) 在互联网公司,Nginx可以说是标配组件,但是主要场景还是负载均衡.反向代理.代理缓存.限流等 ...

  5. 搭建OpenResty(Nginx+Lua)

    这篇文章是一个多月前写的,当时之所以搭建这个是为了最大程度上发挥Nginx的高并发效率(主要是结合lua脚本),参考的话,主要参考张开涛先生写的跟开涛学Nginx+lua系列文章,地址为:https: ...

  6. 单机闭环 使用Nginx+Lua开发高性能Web应用

    [西域骆驼D1532101213]西域骆驼(VANCAMEL)D1532101213 休闲套脚鞋 卡其43[行情 报价 价格 评测]-京东 http://item.jd.com/1856564.htm ...

  7. 跟我学OpenResty(Nginx+Lua)开发目录贴 (转)

    使用Nginx+Lua开发近一年的时间,学习和实践了一些Nginx+Lua开发的架构,为了让更多人使用Nginx+Lua架构开发,利用春节期间总结了一份基本的学习教程,希望对大家有用.也欢迎谈探讨学习 ...

  8. Nginx基础 - Nginx+Lua实现灰度发布与WAF

    1.Nginx加载Lua环境默认情况下Nginx不支持Lua模块, 需要安装LuaJIT解释器, 并且需要重新编译Nginx, 建议使用openrestry 1)环境准备 [root@localhos ...

  9. 使用Nginx+Lua代理Hadoop HA

    一.Hadoop HA的Web页面访问 Hadoop开启HA后,会同时存在两个Master组件提供服务,其中正在使用的组件称为Active,另一个作为备份称为Standby,例如HDFS的NameNo ...

随机推荐

  1. DispatcherServlet的url-pattern尽量不要配置为"/*"

    DispatcherServlet的url-pattern尽量不要配置为"/*" 原因 当Dispatcher的url配置为"/*"时,会把tomcat的web ...

  2. ArcEngine 创建要素,删除要素,生成网格,渲染图层(VB)

    示例代码:https://github.com/yu969890202/ArcEngine/tree/master/WinFrom_ArcEngine_PointDistribution博客后面有两张 ...

  3. JS怎样做四舍五入

    1 .tofixed方法 toFixed() 方法可把 Number 四舍五入为指定小数位数的数字.例如将数据Num保留2位小数,则表示为:toFixed(Num):但是其四舍五入的规则与数学中的规则 ...

  4. Python使用requests爬取一个网页并保存

    #导入 requests模块import requests #设置请求头,让网站监测是浏览器 headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 6. ...

  5. 基于 HTML5 WebGL + WebVR 的 3D 虚实现实可视化系统

    前言 2019 年 VR, AR, XR, 5G, 工业互联网等名词频繁出现在我们的视野中,信息的分享与虚实的结合已经成为大势所趋,5G 是新一代信息通信技术升级的重要方向,工业互联网是制造业转型升级 ...

  6. Beetlex实现完整的HTTP协议

    在传统网络服务中扩展中需要处理Bytes来进行协议的读写,这种原始的处理方式让工作变得相当繁琐复杂,出错和调试的工作量都非常大:组件为了解决这一问题引用Stream读写方式,这种方式可以极大的简化网络 ...

  7. Spring Boot2 系列教程(一) | 如何使用 IDEA 构建 Spring Boot 工程

    微信公众号:一个优秀的废人 如有问题或建议,请后台留言,我会尽力解决你的问题. Search 前言 新年立了个 flag,好好运营这个公众号.具体来说,就是每周要写两篇文章在这个号发表.刚立的 fla ...

  8. 简单介绍HTTP的请求(get请求和post请求)以及对应的响应的内容

    链接解析: https://oa.hbgf.net.cn/login.jsp;jsessionid=47084322738F8DB18D60752944DFD1AA http或者https表示使用的是 ...

  9. kaggle竞赛分享:NFL大数据碗(上篇)

    kaggle竞赛分享:NFL大数据碗 - 上 竞赛简介 一年一度的NFL大数据碗,今年的预测目标是通过两队球员的静态数据,预测该次进攻推进的码数,并转换为该概率分布: 竞赛链接 https://www ...

  10. MySQL 行列相互转换

    行列相互转换 /*创建表*/ CREATE TABLE ic ( NAME ), Product ), amount INT ); INSERT INTO ic VALUES (), (), (), ...