导读: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. @Configuration结合@Bean实现对象的配置

    @Configuration结合@Bean实现对象的配置 前提:最近项目中需要做支付接口,支付宝以及微信支付,本文并不介绍如何写支付接口,而是通过这个示例讲解配置应该怎么写,项目中使用的是Kotlin ...

  2. Spring Data JPA使用findAllOrderBy时踩的坑

    Spring Data JPA使用findAllOrderBy时踩的坑 按照以往的编程经验,我的写法是这样的: List<ActivityEntity> findAllOrderByWis ...

  3. structs2的048漏洞复现 2.3.32版本

    S2-048 远程代码执行漏洞 影响版本: 2.0.0 - 2.3.32 之前在网上说只要时2.3.*的版本都有这个漏洞,自己装了个2.3.34的试了几次都没有执行 然后下载了找到了这篇文章才知道影响 ...

  4. Go 每日一库之 go-homedir

    简介 今天我们来看一个很小,很实用的库go-homedir.顾名思义,go-homedir用来获取用户的主目录. 实际上,使用标准库os/user我们也可以得到这个信息: package main i ...

  5. .net Core 使用IHttpClientFactory请求

            导读:本文已添加在晨曦微服务之旅,现在自己在尝试微服务架构,一边学边做项目快速的进入状态.当然在学习的过程中会将自己学到的知识进行分享. 一.为什么不用HttpClient       ...

  6. 自学 JAVA 的几点建议

    微信公众号:一个优秀的废人 如有问题或建议,请后台留言,我会尽力解决你的问题. 前言 许久不见,最近公众号多了很多在校的师弟师妹们.有很多同学都加了我微信问了一些诸如 [如何自学 Java ]的问题, ...

  7. Java框架之Spring02-AOP-动态代理-AspectJ-JdbcTemplate-事务

    AOP 动态代理 代理设计模式的原理:使用一个代理将原本对象包装起来,然后用该代理对象”取代”原始对象.任何对原始对象的调用都要通过代理.代理对象决定是否以及何时将方法调用转到原始对象上. 代理模式的 ...

  8. 由Kaggle竞赛wiki文章流量预测引发的pandas内存优化过程分享

    pandas内存优化分享 缘由 最近在做Kaggle上的wiki文章流量预测项目,这里由于个人电脑配置问题,我一直都是用的Kaggle的kernel,但是我们知道kernel的内存限制是16G,如下: ...

  9. redis 注意事项

    1.scan_iter car_key = 'shopping*' # print(car_key) data_li = [] for i in con.scan_iter(car_key): # p ...

  10. Oracle GoldenGate for DB2

    --Enable logdb2 update db cfg using LOGARCHMETH1 DISK:/home/db2inst1/arclogs--Rebootdb2 terminatedb2 ...