A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 xiaozuoquan 于 2019-2-26 16:03 编辑

    在互联网公司,Nginx可以说是标配组件,但是主要场景还是负载均衡、反向代理、代理缓存
、限流等场景;而把Nginx作为一个Web容器使用的还不是那么广泛。Nginx的高性能是大家公
认的,而Nginx开发主要是以C/C++模块的形式进行,整体学习和开发成本偏高;如果有一种简单
的语言来实现Web应用的开发,那么Nginx绝对是把好的瑞士军刀;目前Nginx团队也开始意识到
这个问题,开发了nginxScript:可以在Nginx中使用JavaScript进行动态配置一些变量和动态脚本
执行;而目前市面上用的非常成熟的扩展是由章亦春将Lua和Nginx粘合的ngx_lua模块,并且
将Nginx核心、LuaJIT、ngx_lua模块、许多有用的Lua库和常用的第三方Nginx模块组合在一起成
为OpenResty,这样开发人员就可以安装OpenResty,使用Lua编写脚本,然后部署到Nginx Web
容器中运行。从而非常轻松就能开发出高性能的Web服务。
       接下来我们就认识下Nginx、Lua、ngx_lua模块和ngx_lua到底能开发哪些类型的web应用。
一、ngx_lua简介
1、Nginx优点
Nginx设计为一个主进程多个工作进程的工作模式,每个进程是单线程来处理多个连接,而且
每个工作进程采用了非阻塞I/O来处理多个连接,从而减少了线程上下文切换,从而实现了公认的
高性能、高并发;因此在生成环境中会通过把CPU绑定给Nginx工作进程从而提升其性能;另外
因为单线程工作模式的特点,内存占用就非常少了。
Nginx更改配置重启速度非常快,可以毫秒级,而且支持不停止Nginx进行升级Nginx版本、
动态重载Nginx配置。
Nginx模块也是非常多,功能也很强劲,不仅可以作为http负载均衡,Nginx发布1.9.0版本还
支持TCP负载均衡,还可以很容易的实现内容缓存、web服务器、反向代理、访问控制等功能。
2、Lua的优点
Lua是一种轻量级、可嵌入式的脚本语言,这样可以非常容易的嵌入到其他语言中使用。另
外Lua提供了协程并发,即以同步调用的方式进行异步执行,从而实现并发,比起回调机制的并发
来说代码更容易编写和理解,排查问题也会容易。Lua还提供了闭包机制,函数可以作为First
Class Value 进行参数传递,另外其实现了标记清除垃圾收集。
因为Lua的小巧轻量级,可以在Nginx中嵌入Lua VM,请求的时候创建一个VM,请求结束的
时候回收VM。
3、什么是ngx_lua
ngx_lua是Nginx的一个模块,将Lua嵌入到Nginx中,从而可以使用Lua来编写脚本,这样就
可以使用Lua编写应用脚本,部署到Nginx中运行,即Nginx变成了一个Web容器;这样开发人员
就可以使用Lua语言开发高性能Web应用了。
ngx_lua提供了与Nginx交互的很多的API,对于开发人员来说只需要学习这些API就可以进行
功能开发,而对于开发web应用来说,如果接触过Servlet的话,其开发和Servlet类似,无外乎就
更多精彩攻略访问gl.baidu.com 1
是知道接收请求、参数解析、功能处理、返回响应这几步的API是什么样子的。
4、开发环境
我们可以使用OpenResty来搭建开发环境,OpenResty将Nginx核心、LuaJIT、许多有用
的Lua库和Nginx第三方模块打包在一起;这样开发人员只需要安装OpenResty,不需要了
解Nginx核心和写复杂的C/C++模块就可以,只需要使用Lua语言进行Web应用开发了。
如何安装可以参考《跟我学Nginx+Lua开发》。
5、OpenResty生态
OpenResty提供了一些常用的ngx_lua开发模块:如
lua-resty-memcached
lua-resty-mysql
lua-resty-redis
lua-resty-dns
lua-resty-limit-traffic
lua-resty-template
这些模块涉及到如mysql数据库、redis、限流、模块渲染等常用功能组件;另外也有很多第
三方的ngx_lua组件供我们使用,对于大部分应用场景来说现在生态环境中的组件已经足够多了;
如果不满足需求也可以自己去写来完成自己的需求。
6、场景
理论上可以使用ngx_lua开发各种复杂的web应用,不过Lua是一种脚本/动态语言,不适合业
务逻辑比较重的场景,适合小巧的应用场景,代码行数保持在几十行到几千行。目前见到的一些
应用场景:               
web应用:会进行一些业务逻辑处理,甚至进行耗CPU的模板渲染,
一般流程:mysql/redis/http获取数据、业务处理、产生JSON/XML/模板渲染内容,
比如京东的列表页/商品详情页;
接入网关:实现如数据校验前置、缓存前置、数据过滤、API请求聚合、AB测试、灰度发布
、降级、监控等功能,比如京东的交易大Nginx节点、无线部门正在开发的无线网关、单品页统一
服务、实时价格、动态服务;
Web防火墙:可以进行IP/URL/UserAgent/Referer黑名单、限流等功能;
缓存服务器:可以对响应内容进行缓存,减少到后端的请求,从而提升性能;
其他:如静态资源服务器、消息推送服务、缩略图裁剪等。
二、基于Nginx+Lua的常用架构模式


1、负载均衡


如上图,我们首先通过LVS+HAProxy将流量转发给核心Nginx 1和核心Nginx 2,即实现了流
量的负载均衡,此处可以使用如轮训、一致性哈希等调度算法来实现负载的转发;然后核心Nginx
会根据请求特征如“Host:item.jd.com”,转发给相应的业务Nginx节点如单品页Nginx 1。此处为什
么分两层呢?
1、核心Nginx层是无状态的,可以在这一层实现流量分组(内网和外网隔离、爬虫和非爬虫
流量隔离)、内容缓存、请求头过滤、故障切换(机房故障切换到其他机房)、限流、防火墙等
一些通用型功能;
2、业务Nginx如单品页Nginx,可以在在业务Nginx实现业务逻辑、或者反向代理到如Tomcat
,在这一层可以实现内容压缩(放在这一层的目的是减少核心Nginx的CPU压力,将压力分散到
各业务Nginx)、AB测试、降级;即这一层的Nginx跟业务有关联,实现业务的一些通用逻辑。
不管是核心Nginx还是业务Nginx,都应该是无状态设计,可以水平扩容。

业务Nginx一般会把请求直接转
发给后端的业务应用,如Tomcat、PHP,即将请求内部转发到相应的业务应用;当有的Tomcat出
现问题了,可以在这一层摘掉;或者有的业务路径变了在这一层进行rewrite;或者有的后
端Tomcat压力太大也可以在这一层降级,减少对后端的冲击;或者业务需要灰度发布时也可以在
这一层Nginx上控制。
2、单机闭环
所谓单机闭环即所有想要的数据都能从本服务器直接获取,在大多数时候无需通过网络去其
他服务器获取。


如上所示,主要有三种应用模式:
2.1、第一张图应用场景是Nginx应用谁也不依赖,比如我们的Cookie白名单应用,其目的是
不在白名单中的Cookie将被清理,防止大家随便将Cookie写到jd.om根下;大家访
问http://www.jd.com时,会看到一个http://ccc.jd.com/cookie_check的请求用来清理Cookie的;对
于这种应用非常简单,不需要依赖数据源,直接单应用闭环即可。
2.2、第二张图,是读取本机文件系统,如静态资源合并:比如访
问http://item.jd.com/1856584.html,查看源码会发现【//misc.360buyimg.com/jdf/1.0.0/unit/??ui-
base/1.0.0/ui-base.css,shortcut/2.0.0/shortcut.css,global-header/1.0.0/global-
header.css,myjd/2.0.0/myjd.css,nav/2.0.0/nav.css,shoppingcart/2.0.0/shoppingcart.css,global-
footer/1.0.0/global-footer.css,service/1.0.0/service.css”/>】这种请求,即多个请求合并为一个发给
服务端,服务端进行了文件资源的合并;


目前有成熟的Nginx模块如nginx-http-concat进行静态资源合并;
因为我们使用了OpenResty,那么我们完全可以使用Lua编写程序
实现该功能,比如已经有人写了nginx-lua-static-merger来实现这个功能。
还一些业务型应用场景如下图所示


商品页面是由商品框架和其他维度的页面片段(面包屑、相关分类、商家信息、规格参数、商品详情)组成;
或者首页是由首页框架和一些页面片段(分类、轮播图、楼层1、楼层N)组成;分维度是因为不同的维度是
独立变化的。对于这种静态内容但是需要进行框架内容嵌入的方式,Nginx自带的SSI(ServerSide Include)
可以很轻松的完成;也可以使用Lua程序更灵活的完成(读取框架、读取页面片段、合并输出)。
比如商品页面的架构我们可以这样。

首先接收到商品变更消息,商品页面同步Worker会根据消息维度生成相关的页面推送到Nginx服
务器;Nginx应用再通过SSI输出。目前京东商品详情页没有再采用这种架构,具体架构可以参
考《构建需求响应式亿级商品详情页》。
对于首页的架构是类似的,因为其特点(框架变化少,楼层变化较频繁)和个性化的要求,
楼层一般实现为异步加载。
2.3、 第三张图和第二张图的不同处是不再直接读取文件系统,而是读取本机的Redis或
者Redis集群或者如SSDB这种持久化存储或者其他存储系统都是可以的,比如直接说的商品页面
可以使用SSDB进行存储实现。文件系统一个很大的问题是当多台服务器时需要Worker去写多台
服务器,而这个过程可以使用SSDB的主从实现。













1 个回复

倒序浏览
感谢分享
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马