在互联网公司,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的主从实现。
|
请发表评论