OpenResty中使用lua

ngx_lua

1. 原理

ngx_lua将Lua嵌入Nginx,可以让Nginx执行Lua脚本,并且高并发、非阻塞的处理各种请求。Lua内建协程,这样就可以很好的将异步回调转换成顺序调用的形式。ngx_lua在Lua中进行的IO操作都会委托给Nginx的事件模型,从而实现非阻塞调用。开发者可以采用串行的方式编写程序,ngx_lua会自动的在进行阻塞的IO操作时中断,保存上下文;然后将IO操作委托给Nginx事件处理机制,在IO操作完成后,ngx_lua会恢复上下文,程序继续执行,这些操作都是对用户程序透明的。

每个NginxWorker进程持有一个Lua解释器或者LuaJIT实例,被这个Worker处理的所有请求共享这个实例。每个请求的Context会被Lua轻量级的协程分割,从而保证各个请求是独立的。

ngx_lua采用“one-coroutine-per-request”的处理模型,对于每个用户请求,ngx_lua会唤醒一个协程用于执行用户代码处理请求,当请求处理完成这个协程会被销毁。每个协程都有一个独立的全局环境(变量空间),继承于全局共享的、只读的“comman data”。所以,被用户代码注入全局空间的任何变量都不会影响其他请求的处理,并且这些变量在请求处理完成后会被释放,这样就保证所有的用户代码都运行在一个“sandbox”(沙箱),这个沙箱与请求具有相同的生命周期。

得益于Lua协程的支持,ngx_lua在处理10000个并发请求时只需要很少的内存。根据测试,ngx_lua处理每个请求只需要2KB的内存,如果使用LuaJIT则会更少。所以ngx_lua非常适合用于实现可扩展的、高并发的服务。

2.典型应用

  • Mashup’ing and processing outputs of various nginx upstream outputs(proxy, drizzle, postgres, redis, memcached, and etc) in Lua,

  • doing arbitrarily complex access control and security checks in Luabefore requests actually reach the upstream backends,

  • manipulating response headers in an arbitrary way (by Lua)

  • fetching backend information from external storage backends (likeredis, memcached, mysql, postgresql) and use that information to choose whichupstream backend to access on-the-fly,

  • coding up arbitrarily complex web applications in a content handlerusing synchronous but still non-blocking access to the database backends andother storage,

  • doing very complex URL dispatch in Lua at rewrite phase,

  • using Lua to implement advanced caching mechanism for nginxsubrequests and arbitrary locations.

3.Hello Lua!

配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# nginx.conf      
worker_processes 4;

events {
worker_connections 1024;
}
http {

server {
listen 80;
server_name localhost;

location = /lua {
content_by_lua
ngx.say("Hello, Lua!")
';
}
}
}

输出:

1
2
$ curl 'localhost/lua'  
Hello,Lua!

这样就实现了一个很简单的ngx_lua应用,如果这么简单的模块要是用C来开发的话,代码量估计得有100行左右,从这就可以看出ngx_lua的开发效率。

4.Benchmark

通过和nginx访问静态文件还有nodejs比较,来看一下ngx_lua提供的高并发能力。
返回的内容都是"Hello World!"151bytes
通过.ab -n 60000 取10次平均
| || 1000 | 3000 | 5000 | 7000 | 10000 |
| ——| ——| ——| ——| ——| ——|
| nginx静态文件 | 11351 | 9653 | 8929 | 8997 | 9722 |
| nodejs | 10846 | 9510 | 8898 | 8387 | 7820 |
| ngx_lua | 13839 | 10174 | 9523 | 10309 | 10711 |
从图表中可以看到,在各种并发条件下ngx_lua的rps都是最高的,并且基本维持在10000rps左右,nginx读取静态文件因为会有磁盘io所以性能略差一些,而nodejs是相对最差的。通过这个简单的测试,可以看出ngx_lua的高并发能力。

ngx_lua的开发者也做过一个测试对比nginx+fpm+php和nodejs,他得出的结果是ngx_lua可以达到28000rps,而nodejs有10000多一点,php则最差只有6000。可能是有些配置我没有配好导致ngx_lua rps没那么高。

Git常用命令

git stash


如果当前分支有修改的代码,现在需要切换分支或者rebase,则可以用git stash隐匿当前工作区的改动。 git stash #将当前工作区里未commit的文件隐匿
git stash list #显示之前stash的列表 git stash apply #恢复之前的stash

阅读全文 »

我不是为了输赢,我就是认真

老罗的Smartisan T1手机发布会很多人应该都看了,发布会的最后老罗凝视着自己的工匠自画像,半晌没说话,随后转过身,慢慢离开舞台,屏幕下方只留下一句话:
我不是为了输赢,我就是认真。

阅读全文 »

PHP 过往及现在及变革

众所周知,PHP是一个单线程的脚本开发语言,它常在Web开发及系统集成中出现。其灵活简单成本低廉深受互联网公司青睐,初期大量公司使用它进行快速迭代高效迭代出大量产品服务,但是当流量增长后他的弊端会渐渐展现,很多公司为此吃过不少他的苦头。但往往都是短期放弃后,待后端底层数据完善后又用起来,让人又爱又恨,其中发生了什么,是什么造成这个状态,下面我简单介绍下PHP目前架构中碰到的各种问题及解决方法来慢慢分析事情的原因经过结果,当然最后还要介绍下PHP新的技术革命的并发编程开始。

阅读全文 »

Tclip

Tclip致力于人脸识别和图片显著性区域的识别。它与其他图片裁剪程序最大的不同之处在于,在裁剪后的图片中保留人脸和其他图片显著性区域。

阅读全文 »

Basics of Memory Addresses in C

Memory Addresses

It is helpful to think of everything in C in terms of computer memory. Let’s think of computer memory as an array of bytes where each address in memory holds 1 byte. If our computer has 4K of memory for example, it would have 4096 elements in the memory array. When we talk about pointers storing addresses, we are talking about a pointer storing an index to an element in the memory array. Dereferencing a pointer would be getting the value at that index in the array. All of this is of course a lie. How operating systems handle memory is much more complex than this. Memory is not necessarily contiguous and it is not necessarily handed out sequentially. But the analogy provides an easy way to think about memory in C to get started.

阅读全文 »